Mercurial > audio-send
changeset 0:f9476ff7637e
initial forking of open-al to create multiple listeners
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/.hgignore Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,3 @@ 1.4 +syntax: glob 1.5 +build* 1.6 +
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/Alc/ALc.c Tue Oct 25 13:02:31 2011 -0700 2.3 @@ -0,0 +1,2681 @@ 2.4 +/** 2.5 + * OpenAL cross platform audio library 2.6 + * Copyright (C) 1999-2007 by authors. 2.7 + * This library is free software; you can redistribute it and/or 2.8 + * modify it under the terms of the GNU Library General Public 2.9 + * License as published by the Free Software Foundation; either 2.10 + * version 2 of the License, or (at your option) any later version. 2.11 + * 2.12 + * This library is distributed in the hope that it will be useful, 2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 2.15 + * Library General Public License for more details. 2.16 + * 2.17 + * You should have received a copy of the GNU Library General Public 2.18 + * License along with this library; if not, write to the 2.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 2.20 + * Boston, MA 02111-1307, USA. 2.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 2.22 + */ 2.23 + 2.24 +#include "config.h" 2.25 + 2.26 +#include <math.h> 2.27 +#include <stdlib.h> 2.28 +#include <stdio.h> 2.29 +#include <memory.h> 2.30 +#include <ctype.h> 2.31 + 2.32 +#include "alMain.h" 2.33 +#include "alSource.h" 2.34 +#include "AL/al.h" 2.35 +#include "AL/alc.h" 2.36 +#include "alThunk.h" 2.37 +#include "alSource.h" 2.38 +#include "alBuffer.h" 2.39 +#include "alAuxEffectSlot.h" 2.40 +#include "bs2b.h" 2.41 +#include "alu.h" 2.42 + 2.43 +// RLM: try to include the file here. 2.44 + 2.45 + 2.46 + 2.47 +#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } 2.48 +static struct BackendInfo BackendList[] = { 2.49 +#ifdef HAVE_PULSEAUDIO 2.50 + { "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs }, 2.51 +#endif 2.52 +#ifdef HAVE_ALSA 2.53 + { "alsa", alc_alsa_init, alc_alsa_deinit, alc_alsa_probe, EmptyFuncs }, 2.54 +#endif 2.55 +#ifdef HAVE_COREAUDIO 2.56 + { "core", alc_ca_init, alc_ca_deinit, alc_ca_probe, EmptyFuncs }, 2.57 +#endif 2.58 +#ifdef HAVE_OSS 2.59 + { "oss", alc_oss_init, alc_oss_deinit, alc_oss_probe, EmptyFuncs }, 2.60 +#endif 2.61 +#ifdef HAVE_SOLARIS 2.62 + { "solaris", alc_solaris_init, alc_solaris_deinit, alc_solaris_probe, EmptyFuncs }, 2.63 +#endif 2.64 +#ifdef HAVE_SNDIO 2.65 + { "sndio", alc_sndio_init, alc_sndio_deinit, alc_sndio_probe, EmptyFuncs }, 2.66 +#endif 2.67 +#ifdef HAVE_MMDEVAPI 2.68 + { "mmdevapi", alcMMDevApiInit, alcMMDevApiDeinit, alcMMDevApiProbe, EmptyFuncs }, 2.69 +#endif 2.70 +#ifdef HAVE_DSOUND 2.71 + { "dsound", alcDSoundInit, alcDSoundDeinit, alcDSoundProbe, EmptyFuncs }, 2.72 +#endif 2.73 +#ifdef HAVE_WINMM 2.74 + { "winmm", alcWinMMInit, alcWinMMDeinit, alcWinMMProbe, EmptyFuncs }, 2.75 +#endif 2.76 +#ifdef HAVE_PORTAUDIO 2.77 + { "port", alc_pa_init, alc_pa_deinit, alc_pa_probe, EmptyFuncs }, 2.78 +#endif 2.79 +#ifdef HAVE_OPENSL 2.80 + { "opensl", alc_opensl_init, alc_opensl_deinit, alc_opensl_probe, EmptyFuncs }, 2.81 +#endif 2.82 + 2.83 + { "null", alc_null_init, alc_null_deinit, alc_null_probe, EmptyFuncs }, 2.84 +#ifdef HAVE_WAVE 2.85 + { "wave", alc_wave_init, alc_wave_deinit, alc_wave_probe, EmptyFuncs }, 2.86 +#endif 2.87 + { "send", alc_send_init, alc_send_deinit, alc_send_probe, EmptyFuncs }, 2.88 + // this entry is so that the list is terminated by a "null" object, 2.89 + // and helps things to tell when they've reached the end of the list. 2.90 + { NULL, NULL, NULL, NULL, EmptyFuncs } 2.91 +}; 2.92 +static struct BackendInfo BackendLoopback = { 2.93 + "loopback", alc_loopback_init, alc_loopback_deinit, alc_loopback_probe, EmptyFuncs 2.94 +}; 2.95 +#undef EmptyFuncs 2.96 + 2.97 +static struct BackendInfo PlaybackBackend; 2.98 +static struct BackendInfo CaptureBackend; 2.99 + 2.100 +/////////////////////////////////////////////////////// 2.101 +// STRING and EXTENSIONS 2.102 + 2.103 +typedef struct ALCfunction { 2.104 + const ALCchar *funcName; 2.105 + ALCvoid *address; 2.106 +} ALCfunction; 2.107 + 2.108 +typedef struct ALCenums { 2.109 + const ALCchar *enumName; 2.110 + ALCenum value; 2.111 +} ALCenums; 2.112 + 2.113 + 2.114 +static const ALCfunction alcFunctions[] = { 2.115 + { "alcCreateContext", (ALCvoid *) alcCreateContext }, 2.116 + { "alcMakeContextCurrent", (ALCvoid *) alcMakeContextCurrent }, 2.117 + { "alcProcessContext", (ALCvoid *) alcProcessContext }, 2.118 + { "alcSuspendContext", (ALCvoid *) alcSuspendContext }, 2.119 + { "alcDestroyContext", (ALCvoid *) alcDestroyContext }, 2.120 + { "alcGetCurrentContext", (ALCvoid *) alcGetCurrentContext }, 2.121 + { "alcGetContextsDevice", (ALCvoid *) alcGetContextsDevice }, 2.122 + { "alcOpenDevice", (ALCvoid *) alcOpenDevice }, 2.123 + { "alcCloseDevice", (ALCvoid *) alcCloseDevice }, 2.124 + { "alcGetError", (ALCvoid *) alcGetError }, 2.125 + { "alcIsExtensionPresent", (ALCvoid *) alcIsExtensionPresent }, 2.126 + { "alcGetProcAddress", (ALCvoid *) alcGetProcAddress }, 2.127 + { "alcGetEnumValue", (ALCvoid *) alcGetEnumValue }, 2.128 + { "alcGetString", (ALCvoid *) alcGetString }, 2.129 + { "alcGetIntegerv", (ALCvoid *) alcGetIntegerv }, 2.130 + { "alcCaptureOpenDevice", (ALCvoid *) alcCaptureOpenDevice }, 2.131 + { "alcCaptureCloseDevice", (ALCvoid *) alcCaptureCloseDevice }, 2.132 + { "alcCaptureStart", (ALCvoid *) alcCaptureStart }, 2.133 + { "alcCaptureStop", (ALCvoid *) alcCaptureStop }, 2.134 + { "alcCaptureSamples", (ALCvoid *) alcCaptureSamples }, 2.135 + 2.136 + { "alcSetThreadContext", (ALCvoid *) alcSetThreadContext }, 2.137 + { "alcGetThreadContext", (ALCvoid *) alcGetThreadContext }, 2.138 + 2.139 + { "alcLoopbackOpenDeviceSOFT", (ALCvoid *) alcLoopbackOpenDeviceSOFT}, 2.140 + { "alcIsRenderFormatSupportedSOFT",(ALCvoid *) alcIsRenderFormatSupportedSOFT}, 2.141 + { "alcRenderSamplesSOFT", (ALCvoid *) alcRenderSamplesSOFT }, 2.142 + 2.143 + { "alEnable", (ALCvoid *) alEnable }, 2.144 + { "alDisable", (ALCvoid *) alDisable }, 2.145 + { "alIsEnabled", (ALCvoid *) alIsEnabled }, 2.146 + { "alGetString", (ALCvoid *) alGetString }, 2.147 + { "alGetBooleanv", (ALCvoid *) alGetBooleanv }, 2.148 + { "alGetIntegerv", (ALCvoid *) alGetIntegerv }, 2.149 + { "alGetFloatv", (ALCvoid *) alGetFloatv }, 2.150 + { "alGetDoublev", (ALCvoid *) alGetDoublev }, 2.151 + { "alGetBoolean", (ALCvoid *) alGetBoolean }, 2.152 + { "alGetInteger", (ALCvoid *) alGetInteger }, 2.153 + { "alGetFloat", (ALCvoid *) alGetFloat }, 2.154 + { "alGetDouble", (ALCvoid *) alGetDouble }, 2.155 + { "alGetError", (ALCvoid *) alGetError }, 2.156 + { "alIsExtensionPresent", (ALCvoid *) alIsExtensionPresent }, 2.157 + { "alGetProcAddress", (ALCvoid *) alGetProcAddress }, 2.158 + { "alGetEnumValue", (ALCvoid *) alGetEnumValue }, 2.159 + { "alListenerf", (ALCvoid *) alListenerf }, 2.160 + { "alListener3f", (ALCvoid *) alListener3f }, 2.161 + { "alListenerfv", (ALCvoid *) alListenerfv }, 2.162 + { "alListeneri", (ALCvoid *) alListeneri }, 2.163 + { "alListener3i", (ALCvoid *) alListener3i }, 2.164 + { "alListeneriv", (ALCvoid *) alListeneriv }, 2.165 + { "alGetListenerf", (ALCvoid *) alGetListenerf }, 2.166 + { "alGetListener3f", (ALCvoid *) alGetListener3f }, 2.167 + { "alGetListenerfv", (ALCvoid *) alGetListenerfv }, 2.168 + { "alGetListeneri", (ALCvoid *) alGetListeneri }, 2.169 + { "alGetListener3i", (ALCvoid *) alGetListener3i }, 2.170 + { "alGetListeneriv", (ALCvoid *) alGetListeneriv }, 2.171 + { "alGenSources", (ALCvoid *) alGenSources }, 2.172 + { "alDeleteSources", (ALCvoid *) alDeleteSources }, 2.173 + { "alIsSource", (ALCvoid *) alIsSource }, 2.174 + { "alSourcef", (ALCvoid *) alSourcef }, 2.175 + { "alSource3f", (ALCvoid *) alSource3f }, 2.176 + { "alSourcefv", (ALCvoid *) alSourcefv }, 2.177 + { "alSourcei", (ALCvoid *) alSourcei }, 2.178 + { "alSource3i", (ALCvoid *) alSource3i }, 2.179 + { "alSourceiv", (ALCvoid *) alSourceiv }, 2.180 + { "alGetSourcef", (ALCvoid *) alGetSourcef }, 2.181 + { "alGetSource3f", (ALCvoid *) alGetSource3f }, 2.182 + { "alGetSourcefv", (ALCvoid *) alGetSourcefv }, 2.183 + { "alGetSourcei", (ALCvoid *) alGetSourcei }, 2.184 + { "alGetSource3i", (ALCvoid *) alGetSource3i }, 2.185 + { "alGetSourceiv", (ALCvoid *) alGetSourceiv }, 2.186 + { "alSourcePlayv", (ALCvoid *) alSourcePlayv }, 2.187 + { "alSourceStopv", (ALCvoid *) alSourceStopv }, 2.188 + { "alSourceRewindv", (ALCvoid *) alSourceRewindv }, 2.189 + { "alSourcePausev", (ALCvoid *) alSourcePausev }, 2.190 + { "alSourcePlay", (ALCvoid *) alSourcePlay }, 2.191 + { "alSourceStop", (ALCvoid *) alSourceStop }, 2.192 + { "alSourceRewind", (ALCvoid *) alSourceRewind }, 2.193 + { "alSourcePause", (ALCvoid *) alSourcePause }, 2.194 + { "alSourceQueueBuffers", (ALCvoid *) alSourceQueueBuffers }, 2.195 + { "alSourceUnqueueBuffers", (ALCvoid *) alSourceUnqueueBuffers }, 2.196 + { "alGenBuffers", (ALCvoid *) alGenBuffers }, 2.197 + { "alDeleteBuffers", (ALCvoid *) alDeleteBuffers }, 2.198 + { "alIsBuffer", (ALCvoid *) alIsBuffer }, 2.199 + { "alBufferData", (ALCvoid *) alBufferData }, 2.200 + { "alBufferf", (ALCvoid *) alBufferf }, 2.201 + { "alBuffer3f", (ALCvoid *) alBuffer3f }, 2.202 + { "alBufferfv", (ALCvoid *) alBufferfv }, 2.203 + { "alBufferi", (ALCvoid *) alBufferi }, 2.204 + { "alBuffer3i", (ALCvoid *) alBuffer3i }, 2.205 + { "alBufferiv", (ALCvoid *) alBufferiv }, 2.206 + { "alGetBufferf", (ALCvoid *) alGetBufferf }, 2.207 + { "alGetBuffer3f", (ALCvoid *) alGetBuffer3f }, 2.208 + { "alGetBufferfv", (ALCvoid *) alGetBufferfv }, 2.209 + { "alGetBufferi", (ALCvoid *) alGetBufferi }, 2.210 + { "alGetBuffer3i", (ALCvoid *) alGetBuffer3i }, 2.211 + { "alGetBufferiv", (ALCvoid *) alGetBufferiv }, 2.212 + { "alDopplerFactor", (ALCvoid *) alDopplerFactor }, 2.213 + { "alDopplerVelocity", (ALCvoid *) alDopplerVelocity }, 2.214 + { "alSpeedOfSound", (ALCvoid *) alSpeedOfSound }, 2.215 + { "alDistanceModel", (ALCvoid *) alDistanceModel }, 2.216 + 2.217 + { "alGenFilters", (ALCvoid *) alGenFilters }, 2.218 + { "alDeleteFilters", (ALCvoid *) alDeleteFilters }, 2.219 + { "alIsFilter", (ALCvoid *) alIsFilter }, 2.220 + { "alFilteri", (ALCvoid *) alFilteri }, 2.221 + { "alFilteriv", (ALCvoid *) alFilteriv }, 2.222 + { "alFilterf", (ALCvoid *) alFilterf }, 2.223 + { "alFilterfv", (ALCvoid *) alFilterfv }, 2.224 + { "alGetFilteri", (ALCvoid *) alGetFilteri }, 2.225 + { "alGetFilteriv", (ALCvoid *) alGetFilteriv }, 2.226 + { "alGetFilterf", (ALCvoid *) alGetFilterf }, 2.227 + { "alGetFilterfv", (ALCvoid *) alGetFilterfv }, 2.228 + { "alGenEffects", (ALCvoid *) alGenEffects }, 2.229 + { "alDeleteEffects", (ALCvoid *) alDeleteEffects }, 2.230 + { "alIsEffect", (ALCvoid *) alIsEffect }, 2.231 + { "alEffecti", (ALCvoid *) alEffecti }, 2.232 + { "alEffectiv", (ALCvoid *) alEffectiv }, 2.233 + { "alEffectf", (ALCvoid *) alEffectf }, 2.234 + { "alEffectfv", (ALCvoid *) alEffectfv }, 2.235 + { "alGetEffecti", (ALCvoid *) alGetEffecti }, 2.236 + { "alGetEffectiv", (ALCvoid *) alGetEffectiv }, 2.237 + { "alGetEffectf", (ALCvoid *) alGetEffectf }, 2.238 + { "alGetEffectfv", (ALCvoid *) alGetEffectfv }, 2.239 + { "alGenAuxiliaryEffectSlots", (ALCvoid *) alGenAuxiliaryEffectSlots}, 2.240 + { "alDeleteAuxiliaryEffectSlots",(ALCvoid *) alDeleteAuxiliaryEffectSlots}, 2.241 + { "alIsAuxiliaryEffectSlot", (ALCvoid *) alIsAuxiliaryEffectSlot }, 2.242 + { "alAuxiliaryEffectSloti", (ALCvoid *) alAuxiliaryEffectSloti }, 2.243 + { "alAuxiliaryEffectSlotiv", (ALCvoid *) alAuxiliaryEffectSlotiv }, 2.244 + { "alAuxiliaryEffectSlotf", (ALCvoid *) alAuxiliaryEffectSlotf }, 2.245 + { "alAuxiliaryEffectSlotfv", (ALCvoid *) alAuxiliaryEffectSlotfv }, 2.246 + { "alGetAuxiliaryEffectSloti", (ALCvoid *) alGetAuxiliaryEffectSloti}, 2.247 + { "alGetAuxiliaryEffectSlotiv", (ALCvoid *) alGetAuxiliaryEffectSlotiv}, 2.248 + { "alGetAuxiliaryEffectSlotf", (ALCvoid *) alGetAuxiliaryEffectSlotf}, 2.249 + { "alGetAuxiliaryEffectSlotfv", (ALCvoid *) alGetAuxiliaryEffectSlotfv}, 2.250 + 2.251 + { "alBufferSubDataSOFT", (ALCvoid *) alBufferSubDataSOFT }, 2.252 + 2.253 + { "alBufferSamplesSOFT", (ALCvoid *) alBufferSamplesSOFT }, 2.254 + { "alBufferSubSamplesSOFT", (ALCvoid *) alBufferSubSamplesSOFT }, 2.255 + { "alGetBufferSamplesSOFT", (ALCvoid *) alGetBufferSamplesSOFT }, 2.256 + { "alIsBufferFormatSupportedSOFT",(ALCvoid *) alIsBufferFormatSupportedSOFT}, 2.257 + 2.258 + { "alDeferUpdatesSOFT", (ALCvoid *) alDeferUpdatesSOFT }, 2.259 + { "alProcessUpdatesSOFT", (ALCvoid *) alProcessUpdatesSOFT }, 2.260 + 2.261 + { NULL, (ALCvoid *) NULL } 2.262 +}; 2.263 + 2.264 +static const ALCenums enumeration[] = { 2.265 + // Types 2.266 + { "ALC_INVALID", ALC_INVALID }, 2.267 + { "ALC_FALSE", ALC_FALSE }, 2.268 + { "ALC_TRUE", ALC_TRUE }, 2.269 + 2.270 + // ALC Properties 2.271 + { "ALC_MAJOR_VERSION", ALC_MAJOR_VERSION }, 2.272 + { "ALC_MINOR_VERSION", ALC_MINOR_VERSION }, 2.273 + { "ALC_ATTRIBUTES_SIZE", ALC_ATTRIBUTES_SIZE }, 2.274 + { "ALC_ALL_ATTRIBUTES", ALC_ALL_ATTRIBUTES }, 2.275 + { "ALC_DEFAULT_DEVICE_SPECIFIER", ALC_DEFAULT_DEVICE_SPECIFIER }, 2.276 + { "ALC_DEVICE_SPECIFIER", ALC_DEVICE_SPECIFIER }, 2.277 + { "ALC_ALL_DEVICES_SPECIFIER", ALC_ALL_DEVICES_SPECIFIER }, 2.278 + { "ALC_DEFAULT_ALL_DEVICES_SPECIFIER", ALC_DEFAULT_ALL_DEVICES_SPECIFIER }, 2.279 + { "ALC_EXTENSIONS", ALC_EXTENSIONS }, 2.280 + { "ALC_FREQUENCY", ALC_FREQUENCY }, 2.281 + { "ALC_REFRESH", ALC_REFRESH }, 2.282 + { "ALC_SYNC", ALC_SYNC }, 2.283 + { "ALC_MONO_SOURCES", ALC_MONO_SOURCES }, 2.284 + { "ALC_STEREO_SOURCES", ALC_STEREO_SOURCES }, 2.285 + { "ALC_CAPTURE_DEVICE_SPECIFIER", ALC_CAPTURE_DEVICE_SPECIFIER }, 2.286 + { "ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER", ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER}, 2.287 + { "ALC_CAPTURE_SAMPLES", ALC_CAPTURE_SAMPLES }, 2.288 + { "ALC_CONNECTED", ALC_CONNECTED }, 2.289 + 2.290 + // EFX Properties 2.291 + { "ALC_EFX_MAJOR_VERSION", ALC_EFX_MAJOR_VERSION }, 2.292 + { "ALC_EFX_MINOR_VERSION", ALC_EFX_MINOR_VERSION }, 2.293 + { "ALC_MAX_AUXILIARY_SENDS", ALC_MAX_AUXILIARY_SENDS }, 2.294 + 2.295 + // Loopback device Properties 2.296 + { "ALC_FORMAT_CHANNELS_SOFT", ALC_FORMAT_CHANNELS_SOFT }, 2.297 + { "ALC_FORMAT_TYPE_SOFT", ALC_FORMAT_TYPE_SOFT }, 2.298 + 2.299 + // Buffer Channel Configurations 2.300 + { "ALC_MONO", ALC_MONO }, 2.301 + { "ALC_STEREO", ALC_STEREO }, 2.302 + { "ALC_QUAD", ALC_QUAD }, 2.303 + { "ALC_5POINT1", ALC_5POINT1 }, 2.304 + { "ALC_6POINT1", ALC_6POINT1 }, 2.305 + { "ALC_7POINT1", ALC_7POINT1 }, 2.306 + 2.307 + // Buffer Sample Types 2.308 + { "ALC_BYTE", ALC_BYTE }, 2.309 + { "ALC_UNSIGNED_BYTE", ALC_UNSIGNED_BYTE }, 2.310 + { "ALC_SHORT", ALC_SHORT }, 2.311 + { "ALC_UNSIGNED_SHORT", ALC_UNSIGNED_SHORT }, 2.312 + { "ALC_INT", ALC_INT }, 2.313 + { "ALC_UNSIGNED_INT", ALC_UNSIGNED_INT }, 2.314 + { "ALC_FLOAT", ALC_FLOAT }, 2.315 + 2.316 + // ALC Error Message 2.317 + { "ALC_NO_ERROR", ALC_NO_ERROR }, 2.318 + { "ALC_INVALID_DEVICE", ALC_INVALID_DEVICE }, 2.319 + { "ALC_INVALID_CONTEXT", ALC_INVALID_CONTEXT }, 2.320 + { "ALC_INVALID_ENUM", ALC_INVALID_ENUM }, 2.321 + { "ALC_INVALID_VALUE", ALC_INVALID_VALUE }, 2.322 + { "ALC_OUT_OF_MEMORY", ALC_OUT_OF_MEMORY }, 2.323 + 2.324 + { NULL, (ALCenum)0 } 2.325 +}; 2.326 +// Error strings 2.327 +static const ALCchar alcNoError[] = "No Error"; 2.328 +static const ALCchar alcErrInvalidDevice[] = "Invalid Device"; 2.329 +static const ALCchar alcErrInvalidContext[] = "Invalid Context"; 2.330 +static const ALCchar alcErrInvalidEnum[] = "Invalid Enum"; 2.331 +static const ALCchar alcErrInvalidValue[] = "Invalid Value"; 2.332 +static const ALCchar alcErrOutOfMemory[] = "Out of Memory"; 2.333 + 2.334 +/* Device lists. Sizes only include the first ending null character, not the 2.335 + * second */ 2.336 +static ALCchar *alcDeviceList; 2.337 +static size_t alcDeviceListSize; 2.338 +static ALCchar *alcAllDeviceList; 2.339 +static size_t alcAllDeviceListSize; 2.340 +static ALCchar *alcCaptureDeviceList; 2.341 +static size_t alcCaptureDeviceListSize; 2.342 +/* Default is always the first in the list */ 2.343 +static ALCchar *alcDefaultDeviceSpecifier; 2.344 +static ALCchar *alcDefaultAllDeviceSpecifier; 2.345 +static ALCchar *alcCaptureDefaultDeviceSpecifier; 2.346 + 2.347 + 2.348 +static const ALCchar alcNoDeviceExtList[] = 2.349 + "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE " 2.350 + "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device"; 2.351 +static const ALCchar alcExtensionList[] = 2.352 + "ALC_ENUMERATE_ALL_EXT ALC_ENUMERATION_EXT ALC_EXT_CAPTURE " 2.353 + "ALC_EXT_DEDICATED ALC_EXT_disconnect ALC_EXT_EFX " 2.354 + "ALC_EXT_thread_local_context ALC_SOFTX_loopback_device"; 2.355 +static const ALCint alcMajorVersion = 1; 2.356 +static const ALCint alcMinorVersion = 1; 2.357 + 2.358 +static const ALCint alcEFXMajorVersion = 1; 2.359 +static const ALCint alcEFXMinorVersion = 0; 2.360 + 2.361 +/////////////////////////////////////////////////////// 2.362 + 2.363 + 2.364 +/////////////////////////////////////////////////////// 2.365 +// Global Variables 2.366 + 2.367 +static CRITICAL_SECTION ListLock; 2.368 + 2.369 +/* Device List */ 2.370 +static ALCdevice *g_pDeviceList = NULL; 2.371 +static ALCuint g_ulDeviceCount = 0; 2.372 + 2.373 +// Context List 2.374 +static ALCcontext *g_pContextList = NULL; 2.375 +static ALCuint g_ulContextCount = 0; 2.376 + 2.377 +// Thread-local current context 2.378 +static tls_type LocalContext; 2.379 +// Process-wide current context 2.380 +static ALCcontext *GlobalContext; 2.381 + 2.382 +// Context Error 2.383 +static ALCenum g_eLastNullDeviceError = ALC_NO_ERROR; 2.384 + 2.385 +// Default context extensions 2.386 +static const ALchar alExtList[] = 2.387 + "AL_EXT_DOUBLE AL_EXT_EXPONENT_DISTANCE AL_EXT_FLOAT32 AL_EXT_IMA4 " 2.388 + "AL_EXT_LINEAR_DISTANCE AL_EXT_MCFORMATS AL_EXT_MULAW " 2.389 + "AL_EXT_MULAW_MCFORMATS AL_EXT_OFFSET AL_EXT_source_distance_model " 2.390 + "AL_LOKI_quadriphonic AL_SOFTX_buffer_samples AL_SOFT_buffer_sub_data " 2.391 + "AL_SOFTX_deferred_updates AL_SOFT_loop_points " 2.392 + "AL_SOFTX_non_virtual_channels"; 2.393 + 2.394 +// Mixing Priority Level 2.395 +ALint RTPrioLevel; 2.396 + 2.397 +// Output Log File 2.398 +FILE *LogFile; 2.399 + 2.400 +// Output Log Level 2.401 +#ifdef _DEBUG 2.402 +enum LogLevel LogLevel = LogWarning; 2.403 +#else 2.404 +enum LogLevel LogLevel = LogError; 2.405 +#endif 2.406 + 2.407 +// Cone scalar 2.408 +ALdouble ConeScale = 0.5; 2.409 + 2.410 +// Localized Z scalar for mono sources 2.411 +ALdouble ZScale = 1.0; 2.412 + 2.413 +/* One-time configuration init control */ 2.414 +static pthread_once_t alc_config_once = PTHREAD_ONCE_INIT; 2.415 + 2.416 +/////////////////////////////////////////////////////// 2.417 + 2.418 + 2.419 +/////////////////////////////////////////////////////// 2.420 +// ALC Related helper functions 2.421 +static void ReleaseALC(ALCboolean doclose); 2.422 + 2.423 +static void alc_initconfig(void); 2.424 +#define DO_INITCONFIG() pthread_once(&alc_config_once, alc_initconfig) 2.425 + 2.426 +#if defined(_WIN32) 2.427 +static void alc_init(void); 2.428 +static void alc_deinit(void); 2.429 +static void alc_deinit_safe(void); 2.430 + 2.431 +#ifndef AL_LIBTYPE_STATIC 2.432 +BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) 2.433 +{ 2.434 + // Perform actions based on the reason for calling. 2.435 + switch(ul_reason_for_call) 2.436 + { 2.437 + case DLL_PROCESS_ATTACH: 2.438 + DisableThreadLibraryCalls(hModule); 2.439 + alc_init(); 2.440 + break; 2.441 + 2.442 + case DLL_PROCESS_DETACH: 2.443 + if(!lpReserved) 2.444 + alc_deinit(); 2.445 + else 2.446 + alc_deinit_safe(); 2.447 + break; 2.448 + } 2.449 + return TRUE; 2.450 +} 2.451 +#elif defined(_MSC_VER) 2.452 +#pragma section(".CRT$XCU",read) 2.453 +static void alc_constructor(void); 2.454 +static void alc_destructor(void); 2.455 +__declspec(allocate(".CRT$XCU")) void (__cdecl* alc_constructor_)(void) = alc_constructor; 2.456 + 2.457 +static void alc_constructor(void) 2.458 +{ 2.459 + atexit(alc_destructor); 2.460 + alc_init(); 2.461 +} 2.462 + 2.463 +static void alc_destructor(void) 2.464 +{ 2.465 + alc_deinit(); 2.466 +} 2.467 +#elif defined(HAVE_GCC_DESTRUCTOR) 2.468 +static void alc_init(void) __attribute__((constructor)); 2.469 +static void alc_deinit(void) __attribute__((destructor)); 2.470 +#else 2.471 +#error "No static initialization available on this platform!" 2.472 +#endif 2.473 +#elif defined(HAVE_GCC_DESTRUCTOR) 2.474 +static void alc_init(void) __attribute__((constructor)); 2.475 +static void alc_deinit(void) __attribute__((destructor)); 2.476 +#else 2.477 +#error "No global initialization available on this platform!" 2.478 +#endif 2.479 + 2.480 +static void alc_init(void) 2.481 +{ 2.482 + const char *str; 2.483 + 2.484 + LogFile = stderr; 2.485 + 2.486 + str = getenv("__ALSOFT_HALF_ANGLE_CONES"); 2.487 + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) 2.488 + ConeScale = 1.0; 2.489 + 2.490 + str = getenv("__ALSOFT_REVERSE_Z"); 2.491 + if(str && (strcasecmp(str, "true") == 0 || strtol(str, NULL, 0) == 1)) 2.492 + ZScale = -1.0; 2.493 + 2.494 + tls_create(&LocalContext); 2.495 + InitializeCriticalSection(&ListLock); 2.496 + ThunkInit(); 2.497 +} 2.498 + 2.499 +static void alc_deinit_safe(void) 2.500 +{ 2.501 + ReleaseALC(ALC_FALSE); 2.502 + 2.503 + FreeALConfig(); 2.504 + 2.505 + ThunkExit(); 2.506 + DeleteCriticalSection(&ListLock); 2.507 + tls_delete(LocalContext); 2.508 + 2.509 + if(LogFile != stderr) 2.510 + fclose(LogFile); 2.511 + LogFile = NULL; 2.512 +} 2.513 + 2.514 +static void alc_deinit(void) 2.515 +{ 2.516 + int i; 2.517 + 2.518 + ReleaseALC(ALC_TRUE); 2.519 + 2.520 + memset(&PlaybackBackend, 0, sizeof(PlaybackBackend)); 2.521 + memset(&CaptureBackend, 0, sizeof(CaptureBackend)); 2.522 + 2.523 + for(i = 0;BackendList[i].Deinit;i++) 2.524 + BackendList[i].Deinit(); 2.525 + BackendLoopback.Deinit(); 2.526 + 2.527 + alc_deinit_safe(); 2.528 +} 2.529 + 2.530 +static void alc_initconfig(void) 2.531 +{ 2.532 + printf("OPENAL-AURELLEM: alc_init_config!!\n"); 2.533 + const char *devs, *str; 2.534 + int i, n; 2.535 + 2.536 + str = getenv("ALSOFT_LOGLEVEL"); 2.537 + if(str) 2.538 + { 2.539 + long lvl = strtol(str, NULL, 0); 2.540 + if(lvl >= NoLog && lvl <= LogTrace) 2.541 + LogLevel = lvl; 2.542 + } 2.543 + 2.544 + str = getenv("ALSOFT_LOGFILE"); 2.545 + if(str && str[0]) 2.546 + { 2.547 + FILE *logfile = fopen(str, "wat"); 2.548 + if(logfile) LogFile = logfile; 2.549 + else ERR("Failed to open log file '%s'\n", str); 2.550 + } 2.551 + 2.552 + ReadALConfig(); 2.553 + 2.554 + InitHrtf(); 2.555 + 2.556 +#ifdef _WIN32 2.557 + RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 1); 2.558 +#else 2.559 + RTPrioLevel = GetConfigValueInt(NULL, "rt-prio", 0); 2.560 +#endif 2.561 + 2.562 + DefaultResampler = GetConfigValueInt(NULL, "resampler", RESAMPLER_DEFAULT); 2.563 + if(DefaultResampler >= RESAMPLER_MAX || DefaultResampler <= RESAMPLER_MIN) 2.564 + DefaultResampler = RESAMPLER_DEFAULT; 2.565 + 2.566 + ReverbBoost *= aluPow(10.0f, GetConfigValueFloat("reverb", "boost", 0.0f) / 2.567 + 20.0f); 2.568 + EmulateEAXReverb = GetConfigValueBool("reverb", "emulate-eax", AL_FALSE); 2.569 + 2.570 + devs = GetConfigValue(NULL, "drivers", ""); 2.571 + //printf("these are the devices: %s\n", devs); 2.572 + 2.573 + if(devs[0]) 2.574 + { 2.575 + int n; 2.576 + size_t len; 2.577 + const char *next = devs; 2.578 + int endlist, delitem; 2.579 + 2.580 + i = 0; 2.581 + do { 2.582 + devs = next; 2.583 + //printf("AURELLEM: devs is %s\n",devs); 2.584 + next = strchr(devs, ','); 2.585 + 2.586 + delitem = (devs[0] == '-'); 2.587 + if(devs[0] == '-') devs++; 2.588 + 2.589 + if(!devs[0] || devs[0] == ',') 2.590 + { 2.591 + endlist = 0; 2.592 + continue; 2.593 + } 2.594 + endlist = 1; 2.595 + 2.596 + len = (next ? ((size_t)(next-devs)) : strlen(devs)); 2.597 + for(n = i;BackendList[n].Init;n++) 2.598 + { 2.599 + //printf("AURELLEM: device-name -- %s\n",BackendList[n].name); 2.600 + if(len == strlen(BackendList[n].name) && 2.601 + strncmp(BackendList[n].name, devs, len) == 0) 2.602 + { 2.603 + if(delitem) 2.604 + { 2.605 + do { 2.606 + BackendList[n] = BackendList[n+1]; 2.607 + ++n; 2.608 + } 2.609 + // this relies on the last entry being terminated by an 2.610 + // entry with all nulls. 2.611 + while(BackendList[n].Init); 2.612 + } 2.613 + else 2.614 + { 2.615 + struct BackendInfo Bkp = BackendList[n]; 2.616 + while(n > i) 2.617 + { 2.618 + BackendList[n] = BackendList[n-1]; 2.619 + --n; 2.620 + } 2.621 + BackendList[n] = Bkp; 2.622 + 2.623 + i++; 2.624 + } 2.625 + break; 2.626 + } 2.627 + } 2.628 + } while(next++); 2.629 + 2.630 + if(endlist) 2.631 + { 2.632 + BackendList[i].name = NULL; 2.633 + BackendList[i].Init = NULL; 2.634 + BackendList[i].Deinit = NULL; 2.635 + BackendList[i].Probe = NULL; 2.636 + } 2.637 + } 2.638 + 2.639 + for(i = 0;BackendList[i].Init && (!PlaybackBackend.name || !CaptureBackend.name);i++) 2.640 + { 2.641 + if(!BackendList[i].Init(&BackendList[i].Funcs)) 2.642 + { 2.643 + WARN("Failed to initialize backend \"%s\"\n", BackendList[i].name); 2.644 + continue; 2.645 + } 2.646 + 2.647 + TRACE("Initialized backend \"%s\"\n", BackendList[i].name); 2.648 + if(BackendList[i].Funcs.OpenPlayback && !PlaybackBackend.name) 2.649 + { 2.650 + PlaybackBackend = BackendList[i]; 2.651 + TRACE("Added \"%s\" for playback\n", PlaybackBackend.name); 2.652 + } 2.653 + if(BackendList[i].Funcs.OpenCapture && !CaptureBackend.name) 2.654 + { 2.655 + CaptureBackend = BackendList[i]; 2.656 + TRACE("Added \"%s\" for capture\n", CaptureBackend.name); 2.657 + } 2.658 + } 2.659 + BackendLoopback.Init(&BackendLoopback.Funcs); 2.660 + 2.661 + str = GetConfigValue(NULL, "excludefx", ""); 2.662 + if(str[0]) 2.663 + { 2.664 + size_t len; 2.665 + const char *next = str; 2.666 + 2.667 + do { 2.668 + str = next; 2.669 + next = strchr(str, ','); 2.670 + 2.671 + if(!str[0] || next == str) 2.672 + continue; 2.673 + 2.674 + len = (next ? ((size_t)(next-str)) : strlen(str)); 2.675 + for(n = 0;EffectList[n].name;n++) 2.676 + { 2.677 + if(len == strlen(EffectList[n].name) && 2.678 + strncmp(EffectList[n].name, str, len) == 0) 2.679 + DisabledEffects[EffectList[n].type] = AL_TRUE; 2.680 + } 2.681 + } while(next++); 2.682 + } 2.683 +} 2.684 + 2.685 + 2.686 +static void ProbeList(ALCchar **list, size_t *listsize, enum DevProbe type) 2.687 +{ 2.688 + free(*list); 2.689 + *list = NULL; 2.690 + *listsize = 0; 2.691 + 2.692 + DO_INITCONFIG(); 2.693 + if(type == CAPTURE_DEVICE_PROBE) 2.694 + CaptureBackend.Probe(type); 2.695 + else 2.696 + PlaybackBackend.Probe(type); 2.697 +} 2.698 + 2.699 +static void ProbeDeviceList(void) 2.700 +{ ProbeList(&alcDeviceList, &alcDeviceListSize, DEVICE_PROBE); } 2.701 +static void ProbeAllDeviceList(void) 2.702 +{ ProbeList(&alcAllDeviceList, &alcAllDeviceListSize, ALL_DEVICE_PROBE); } 2.703 +static void ProbeCaptureDeviceList(void) 2.704 +{ ProbeList(&alcCaptureDeviceList, &alcCaptureDeviceListSize, CAPTURE_DEVICE_PROBE); } 2.705 + 2.706 + 2.707 +static void AppendList(const ALCchar *name, ALCchar **List, size_t *ListSize) 2.708 +{ 2.709 + size_t len = strlen(name); 2.710 + void *temp; 2.711 + 2.712 + if(len == 0) 2.713 + return; 2.714 + 2.715 + temp = realloc(*List, (*ListSize) + len + 2); 2.716 + if(!temp) 2.717 + { 2.718 + ERR("Realloc failed to add %s!\n", name); 2.719 + return; 2.720 + } 2.721 + *List = temp; 2.722 + 2.723 + memcpy((*List)+(*ListSize), name, len+1); 2.724 + *ListSize += len+1; 2.725 + (*List)[*ListSize] = 0; 2.726 +} 2.727 + 2.728 +#define DECL_APPEND_LIST_FUNC(type) \ 2.729 +void Append##type##List(const ALCchar *name) \ 2.730 +{ AppendList(name, &alc##type##List, &alc##type##ListSize); } 2.731 + 2.732 +DECL_APPEND_LIST_FUNC(Device) 2.733 +DECL_APPEND_LIST_FUNC(AllDevice) 2.734 +DECL_APPEND_LIST_FUNC(CaptureDevice) 2.735 + 2.736 +#undef DECL_APPEND_LIST_FUNC 2.737 + 2.738 + 2.739 +/* Sets the default channel order used by most non-WaveFormatEx-based APIs */ 2.740 +void SetDefaultChannelOrder(ALCdevice *device) 2.741 +{ 2.742 + switch(device->FmtChans) 2.743 + { 2.744 + case DevFmtX51: device->DevChannels[0] = FRONT_LEFT; 2.745 + device->DevChannels[1] = FRONT_RIGHT; 2.746 + device->DevChannels[2] = BACK_LEFT; 2.747 + device->DevChannels[3] = BACK_RIGHT; 2.748 + device->DevChannels[4] = FRONT_CENTER; 2.749 + device->DevChannels[5] = LFE; 2.750 + return; 2.751 + 2.752 + case DevFmtX71: device->DevChannels[0] = FRONT_LEFT; 2.753 + device->DevChannels[1] = FRONT_RIGHT; 2.754 + device->DevChannels[2] = BACK_LEFT; 2.755 + device->DevChannels[3] = BACK_RIGHT; 2.756 + device->DevChannels[4] = FRONT_CENTER; 2.757 + device->DevChannels[5] = LFE; 2.758 + device->DevChannels[6] = SIDE_LEFT; 2.759 + device->DevChannels[7] = SIDE_RIGHT; 2.760 + return; 2.761 + 2.762 + /* Same as WFX order */ 2.763 + case DevFmtMono: 2.764 + case DevFmtStereo: 2.765 + case DevFmtQuad: 2.766 + case DevFmtX51Side: 2.767 + case DevFmtX61: 2.768 + break; 2.769 + } 2.770 + SetDefaultWFXChannelOrder(device); 2.771 +} 2.772 +/* Sets the default order used by WaveFormatEx */ 2.773 +void SetDefaultWFXChannelOrder(ALCdevice *device) 2.774 +{ 2.775 + switch(device->FmtChans) 2.776 + { 2.777 + case DevFmtMono: device->DevChannels[0] = FRONT_CENTER; break; 2.778 + 2.779 + case DevFmtStereo: device->DevChannels[0] = FRONT_LEFT; 2.780 + device->DevChannels[1] = FRONT_RIGHT; break; 2.781 + 2.782 + case DevFmtQuad: device->DevChannels[0] = FRONT_LEFT; 2.783 + device->DevChannels[1] = FRONT_RIGHT; 2.784 + device->DevChannels[2] = BACK_LEFT; 2.785 + device->DevChannels[3] = BACK_RIGHT; break; 2.786 + 2.787 + case DevFmtX51: device->DevChannels[0] = FRONT_LEFT; 2.788 + device->DevChannels[1] = FRONT_RIGHT; 2.789 + device->DevChannels[2] = FRONT_CENTER; 2.790 + device->DevChannels[3] = LFE; 2.791 + device->DevChannels[4] = BACK_LEFT; 2.792 + device->DevChannels[5] = BACK_RIGHT; break; 2.793 + 2.794 + case DevFmtX51Side: device->DevChannels[0] = FRONT_LEFT; 2.795 + device->DevChannels[1] = FRONT_RIGHT; 2.796 + device->DevChannels[2] = FRONT_CENTER; 2.797 + device->DevChannels[3] = LFE; 2.798 + device->DevChannels[4] = SIDE_LEFT; 2.799 + device->DevChannels[5] = SIDE_RIGHT; break; 2.800 + 2.801 + case DevFmtX61: device->DevChannels[0] = FRONT_LEFT; 2.802 + device->DevChannels[1] = FRONT_RIGHT; 2.803 + device->DevChannels[2] = FRONT_CENTER; 2.804 + device->DevChannels[3] = LFE; 2.805 + device->DevChannels[4] = BACK_CENTER; 2.806 + device->DevChannels[5] = SIDE_LEFT; 2.807 + device->DevChannels[6] = SIDE_RIGHT; break; 2.808 + 2.809 + case DevFmtX71: device->DevChannels[0] = FRONT_LEFT; 2.810 + device->DevChannels[1] = FRONT_RIGHT; 2.811 + device->DevChannels[2] = FRONT_CENTER; 2.812 + device->DevChannels[3] = LFE; 2.813 + device->DevChannels[4] = BACK_LEFT; 2.814 + device->DevChannels[5] = BACK_RIGHT; 2.815 + device->DevChannels[6] = SIDE_LEFT; 2.816 + device->DevChannels[7] = SIDE_RIGHT; break; 2.817 + } 2.818 +} 2.819 + 2.820 + 2.821 +const ALCchar *DevFmtTypeString(enum DevFmtType type) 2.822 +{ 2.823 + switch(type) 2.824 + { 2.825 + case DevFmtByte: return "Signed Byte"; 2.826 + case DevFmtUByte: return "Unsigned Byte"; 2.827 + case DevFmtShort: return "Signed Short"; 2.828 + case DevFmtUShort: return "Unsigned Short"; 2.829 + case DevFmtFloat: return "Float"; 2.830 + } 2.831 + return "(unknown type)"; 2.832 +} 2.833 +const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans) 2.834 +{ 2.835 + switch(chans) 2.836 + { 2.837 + case DevFmtMono: return "Mono"; 2.838 + case DevFmtStereo: return "Stereo"; 2.839 + case DevFmtQuad: return "Quadraphonic"; 2.840 + case DevFmtX51: return "5.1 Surround"; 2.841 + case DevFmtX51Side: return "5.1 Side"; 2.842 + case DevFmtX61: return "6.1 Surround"; 2.843 + case DevFmtX71: return "7.1 Surround"; 2.844 + } 2.845 + return "(unknown channels)"; 2.846 +} 2.847 + 2.848 +ALuint BytesFromDevFmt(enum DevFmtType type) 2.849 +{ 2.850 + switch(type) 2.851 + { 2.852 + case DevFmtByte: return sizeof(ALbyte); 2.853 + case DevFmtUByte: return sizeof(ALubyte); 2.854 + case DevFmtShort: return sizeof(ALshort); 2.855 + case DevFmtUShort: return sizeof(ALushort); 2.856 + case DevFmtFloat: return sizeof(ALfloat); 2.857 + } 2.858 + return 0; 2.859 +} 2.860 +ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) 2.861 +{ 2.862 + switch(chans) 2.863 + { 2.864 + case DevFmtMono: return 1; 2.865 + case DevFmtStereo: return 2; 2.866 + case DevFmtQuad: return 4; 2.867 + case DevFmtX51: return 6; 2.868 + case DevFmtX51Side: return 6; 2.869 + case DevFmtX61: return 7; 2.870 + case DevFmtX71: return 8; 2.871 + } 2.872 + return 0; 2.873 +} 2.874 +ALboolean DecomposeDevFormat(ALenum format, enum DevFmtChannels *chans, 2.875 + enum DevFmtType *type) 2.876 +{ 2.877 + switch(format) 2.878 + { 2.879 + case AL_FORMAT_MONO8: 2.880 + *chans = DevFmtMono; 2.881 + *type = DevFmtUByte; 2.882 + return AL_TRUE; 2.883 + case AL_FORMAT_MONO16: 2.884 + *chans = DevFmtMono; 2.885 + *type = DevFmtShort; 2.886 + return AL_TRUE; 2.887 + case AL_FORMAT_MONO_FLOAT32: 2.888 + *chans = DevFmtMono; 2.889 + *type = DevFmtFloat; 2.890 + return AL_TRUE; 2.891 + case AL_FORMAT_STEREO8: 2.892 + *chans = DevFmtStereo; 2.893 + *type = DevFmtUByte; 2.894 + return AL_TRUE; 2.895 + case AL_FORMAT_STEREO16: 2.896 + *chans = DevFmtStereo; 2.897 + *type = DevFmtShort; 2.898 + return AL_TRUE; 2.899 + case AL_FORMAT_STEREO_FLOAT32: 2.900 + *chans = DevFmtStereo; 2.901 + *type = DevFmtFloat; 2.902 + return AL_TRUE; 2.903 + case AL_FORMAT_QUAD8: 2.904 + *chans = DevFmtQuad; 2.905 + *type = DevFmtUByte; 2.906 + return AL_TRUE; 2.907 + case AL_FORMAT_QUAD16: 2.908 + *chans = DevFmtQuad; 2.909 + *type = DevFmtShort; 2.910 + return AL_TRUE; 2.911 + case AL_FORMAT_QUAD32: 2.912 + *chans = DevFmtQuad; 2.913 + *type = DevFmtFloat; 2.914 + return AL_TRUE; 2.915 + case AL_FORMAT_51CHN8: 2.916 + *chans = DevFmtX51; 2.917 + *type = DevFmtUByte; 2.918 + return AL_TRUE; 2.919 + case AL_FORMAT_51CHN16: 2.920 + *chans = DevFmtX51; 2.921 + *type = DevFmtShort; 2.922 + return AL_TRUE; 2.923 + case AL_FORMAT_51CHN32: 2.924 + *chans = DevFmtX51; 2.925 + *type = DevFmtFloat; 2.926 + return AL_TRUE; 2.927 + case AL_FORMAT_61CHN8: 2.928 + *chans = DevFmtX61; 2.929 + *type = DevFmtUByte; 2.930 + return AL_TRUE; 2.931 + case AL_FORMAT_61CHN16: 2.932 + *chans = DevFmtX61; 2.933 + *type = DevFmtShort; 2.934 + return AL_TRUE; 2.935 + case AL_FORMAT_61CHN32: 2.936 + *chans = DevFmtX61; 2.937 + *type = DevFmtFloat; 2.938 + return AL_TRUE; 2.939 + case AL_FORMAT_71CHN8: 2.940 + *chans = DevFmtX71; 2.941 + *type = DevFmtUByte; 2.942 + return AL_TRUE; 2.943 + case AL_FORMAT_71CHN16: 2.944 + *chans = DevFmtX71; 2.945 + *type = DevFmtShort; 2.946 + return AL_TRUE; 2.947 + case AL_FORMAT_71CHN32: 2.948 + *chans = DevFmtX71; 2.949 + *type = DevFmtFloat; 2.950 + return AL_TRUE; 2.951 + } 2.952 + return AL_FALSE; 2.953 +} 2.954 + 2.955 +static ALCboolean IsValidALCType(ALCenum type) 2.956 +{ 2.957 + switch(type) 2.958 + { 2.959 + case ALC_BYTE: 2.960 + case ALC_UNSIGNED_BYTE: 2.961 + case ALC_SHORT: 2.962 + case ALC_UNSIGNED_SHORT: 2.963 + case ALC_INT: 2.964 + case ALC_UNSIGNED_INT: 2.965 + case ALC_FLOAT: 2.966 + return ALC_TRUE; 2.967 + } 2.968 + return ALC_FALSE; 2.969 +} 2.970 + 2.971 +static ALCboolean IsValidALCChannels(ALCenum channels) 2.972 +{ 2.973 + switch(channels) 2.974 + { 2.975 + case ALC_MONO: 2.976 + case ALC_STEREO: 2.977 + case ALC_QUAD: 2.978 + case ALC_5POINT1: 2.979 + case ALC_6POINT1: 2.980 + case ALC_7POINT1: 2.981 + return ALC_TRUE; 2.982 + } 2.983 + return ALC_FALSE; 2.984 +} 2.985 + 2.986 + 2.987 +static void LockLists(void) 2.988 +{ 2.989 + EnterCriticalSection(&ListLock); 2.990 +} 2.991 + 2.992 +static void UnlockLists(void) 2.993 +{ 2.994 + LeaveCriticalSection(&ListLock); 2.995 +} 2.996 + 2.997 +/* 2.998 + IsDevice 2.999 + 2.1000 + Check pDevice is a valid Device pointer 2.1001 +*/ 2.1002 +static ALCboolean IsDevice(ALCdevice *pDevice) 2.1003 +{ 2.1004 + ALCdevice *pTempDevice; 2.1005 + 2.1006 + pTempDevice = g_pDeviceList; 2.1007 + while(pTempDevice && pTempDevice != pDevice) 2.1008 + pTempDevice = pTempDevice->next; 2.1009 + 2.1010 + return (pTempDevice ? ALC_TRUE : ALC_FALSE); 2.1011 +} 2.1012 + 2.1013 +/* 2.1014 + IsContext 2.1015 + 2.1016 + Check pContext is a valid Context pointer 2.1017 +*/ 2.1018 +static ALCboolean IsContext(ALCcontext *pContext) 2.1019 +{ 2.1020 + ALCcontext *pTempContext; 2.1021 + 2.1022 + pTempContext = g_pContextList; 2.1023 + while (pTempContext && pTempContext != pContext) 2.1024 + pTempContext = pTempContext->next; 2.1025 + 2.1026 + return (pTempContext ? ALC_TRUE : ALC_FALSE); 2.1027 +} 2.1028 + 2.1029 + 2.1030 +/* 2.1031 + alcSetError 2.1032 + 2.1033 + Store latest ALC Error 2.1034 +*/ 2.1035 +ALCvoid alcSetError(ALCdevice *device, ALenum errorCode) 2.1036 +{ 2.1037 + LockLists(); 2.1038 + if(IsDevice(device)) 2.1039 + device->LastError = errorCode; 2.1040 + else 2.1041 + g_eLastNullDeviceError = errorCode; 2.1042 + UnlockLists(); 2.1043 +} 2.1044 + 2.1045 + 2.1046 +/* UpdateDeviceParams: 2.1047 + * 2.1048 + * Updates device parameters according to the attribute list. 2.1049 + */ 2.1050 +static ALCboolean UpdateDeviceParams(ALCdevice *device, const ALCint *attrList) 2.1051 +{ 2.1052 + ALuint i; 2.1053 + 2.1054 + // Check for attributes 2.1055 + if(attrList && attrList[0]) 2.1056 + { 2.1057 + ALCuint freq, numMono, numStereo, numSends; 2.1058 + enum DevFmtChannels schans; 2.1059 + enum DevFmtType stype; 2.1060 + ALuint attrIdx; 2.1061 + 2.1062 + // If a context is already running on the device, stop playback so the 2.1063 + // device attributes can be updated 2.1064 + if((device->Flags&DEVICE_RUNNING)) 2.1065 + ALCdevice_StopPlayback(device); 2.1066 + device->Flags &= ~DEVICE_RUNNING; 2.1067 + 2.1068 + freq = device->Frequency; 2.1069 + schans = device->FmtChans; 2.1070 + stype = device->FmtType; 2.1071 + numMono = device->NumMonoSources; 2.1072 + numStereo = device->NumStereoSources; 2.1073 + numSends = device->NumAuxSends; 2.1074 + 2.1075 + freq = GetConfigValueInt(NULL, "frequency", freq); 2.1076 + if(freq < 8000) freq = 8000; 2.1077 + 2.1078 + attrIdx = 0; 2.1079 + while(attrList[attrIdx]) 2.1080 + { 2.1081 + if(attrList[attrIdx] == ALC_FORMAT_CHANNELS_SOFT && 2.1082 + device->IsLoopbackDevice) 2.1083 + { 2.1084 + ALCint val = attrList[attrIdx + 1]; 2.1085 + if(!IsValidALCChannels(val) || !ChannelsFromDevFmt(val)) 2.1086 + { 2.1087 + alcSetError(device, ALC_INVALID_VALUE); 2.1088 + return ALC_FALSE; 2.1089 + } 2.1090 + schans = val; 2.1091 + } 2.1092 + 2.1093 + if(attrList[attrIdx] == ALC_FORMAT_TYPE_SOFT && 2.1094 + device->IsLoopbackDevice) 2.1095 + { 2.1096 + ALCint val = attrList[attrIdx + 1]; 2.1097 + if(!IsValidALCType(val) || !BytesFromDevFmt(val)) 2.1098 + { 2.1099 + alcSetError(device, ALC_INVALID_VALUE); 2.1100 + return ALC_FALSE; 2.1101 + } 2.1102 + stype = val; 2.1103 + } 2.1104 + 2.1105 + if(attrList[attrIdx] == ALC_FREQUENCY) 2.1106 + { 2.1107 + if(device->IsLoopbackDevice) 2.1108 + { 2.1109 + freq = attrList[attrIdx + 1]; 2.1110 + if(freq < 8000) 2.1111 + { 2.1112 + alcSetError(device, ALC_INVALID_VALUE); 2.1113 + return ALC_FALSE; 2.1114 + } 2.1115 + } 2.1116 + else if(!ConfigValueExists(NULL, "frequency")) 2.1117 + { 2.1118 + freq = attrList[attrIdx + 1]; 2.1119 + if(freq < 8000) freq = 8000; 2.1120 + device->Flags |= DEVICE_FREQUENCY_REQUEST; 2.1121 + } 2.1122 + } 2.1123 + 2.1124 + if(attrList[attrIdx] == ALC_STEREO_SOURCES) 2.1125 + { 2.1126 + numStereo = attrList[attrIdx + 1]; 2.1127 + if(numStereo > device->MaxNoOfSources) 2.1128 + numStereo = device->MaxNoOfSources; 2.1129 + 2.1130 + numMono = device->MaxNoOfSources - numStereo; 2.1131 + } 2.1132 + 2.1133 + if(attrList[attrIdx] == ALC_MAX_AUXILIARY_SENDS && 2.1134 + !ConfigValueExists(NULL, "sends")) 2.1135 + { 2.1136 + numSends = attrList[attrIdx + 1]; 2.1137 + if(numSends > MAX_SENDS) 2.1138 + numSends = MAX_SENDS; 2.1139 + } 2.1140 + 2.1141 + attrIdx += 2; 2.1142 + } 2.1143 + 2.1144 + device->UpdateSize = (ALuint64)device->UpdateSize * freq / 2.1145 + device->Frequency; 2.1146 + 2.1147 + device->Frequency = freq; 2.1148 + device->FmtChans = schans; 2.1149 + device->FmtType = stype; 2.1150 + device->NumMonoSources = numMono; 2.1151 + device->NumStereoSources = numStereo; 2.1152 + device->NumAuxSends = numSends; 2.1153 + } 2.1154 + 2.1155 + if((device->Flags&DEVICE_RUNNING)) 2.1156 + return ALC_TRUE; 2.1157 + 2.1158 + LockDevice(device); 2.1159 + TRACE("Format pre-setup: %s%s, %s, %uhz%s, %u update size x%d\n", 2.1160 + DevFmtChannelsString(device->FmtChans), 2.1161 + (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"", 2.1162 + DevFmtTypeString(device->FmtType), device->Frequency, 2.1163 + (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"", 2.1164 + device->UpdateSize, device->NumUpdates); 2.1165 + if(ALCdevice_ResetPlayback(device) == ALC_FALSE) 2.1166 + { 2.1167 + UnlockDevice(device); 2.1168 + return ALC_FALSE; 2.1169 + } 2.1170 + device->Flags |= DEVICE_RUNNING; 2.1171 + TRACE("Format post-setup: %s%s, %s, %uhz%s, %u update size x%d\n", 2.1172 + DevFmtChannelsString(device->FmtChans), 2.1173 + (device->Flags&DEVICE_CHANNELS_REQUEST)?" (requested)":"", 2.1174 + DevFmtTypeString(device->FmtType), device->Frequency, 2.1175 + (device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"", 2.1176 + device->UpdateSize, device->NumUpdates); 2.1177 + 2.1178 + aluInitPanning(device); 2.1179 + 2.1180 + for(i = 0;i < MAXCHANNELS;i++) 2.1181 + { 2.1182 + device->ClickRemoval[i] = 0.0f; 2.1183 + device->PendingClicks[i] = 0.0f; 2.1184 + } 2.1185 + 2.1186 + if(!device->IsLoopbackDevice && GetConfigValueBool(NULL, "hrtf", AL_FALSE)) 2.1187 + device->Flags |= DEVICE_USE_HRTF; 2.1188 + if((device->Flags&DEVICE_USE_HRTF) && !IsHrtfCompatible(device)) 2.1189 + device->Flags &= ~DEVICE_USE_HRTF; 2.1190 + TRACE("HRTF %s\n", (device->Flags&DEVICE_USE_HRTF)?"enabled":"disabled"); 2.1191 + 2.1192 + if(!(device->Flags&DEVICE_USE_HRTF) && device->Bs2bLevel > 0 && device->Bs2bLevel <= 6) 2.1193 + { 2.1194 + if(!device->Bs2b) 2.1195 + { 2.1196 + device->Bs2b = calloc(1, sizeof(*device->Bs2b)); 2.1197 + bs2b_clear(device->Bs2b); 2.1198 + } 2.1199 + bs2b_set_srate(device->Bs2b, device->Frequency); 2.1200 + bs2b_set_level(device->Bs2b, device->Bs2bLevel); 2.1201 + TRACE("BS2B level %d\n", device->Bs2bLevel); 2.1202 + } 2.1203 + else 2.1204 + { 2.1205 + free(device->Bs2b); 2.1206 + device->Bs2b = NULL; 2.1207 + TRACE("BS2B disabled\n"); 2.1208 + } 2.1209 + 2.1210 + device->Flags &= ~DEVICE_DUPLICATE_STEREO; 2.1211 + switch(device->FmtChans) 2.1212 + { 2.1213 + case DevFmtMono: 2.1214 + case DevFmtStereo: 2.1215 + break; 2.1216 + case DevFmtQuad: 2.1217 + case DevFmtX51: 2.1218 + case DevFmtX51Side: 2.1219 + case DevFmtX61: 2.1220 + case DevFmtX71: 2.1221 + if(GetConfigValueBool(NULL, "stereodup", AL_TRUE)) 2.1222 + device->Flags |= DEVICE_DUPLICATE_STEREO; 2.1223 + break; 2.1224 + } 2.1225 + TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled"); 2.1226 + 2.1227 + for(i = 0;i < device->NumContexts;i++) 2.1228 + { 2.1229 + ALCcontext *context = device->Contexts[i]; 2.1230 + ALsizei pos; 2.1231 + 2.1232 + context->UpdateSources = AL_FALSE; 2.1233 + for(pos = 0;pos < context->EffectSlotMap.size;pos++) 2.1234 + { 2.1235 + ALeffectslot *slot = context->EffectSlotMap.array[pos].value; 2.1236 + 2.1237 + if(ALEffect_DeviceUpdate(slot->EffectState, device) == AL_FALSE) 2.1238 + { 2.1239 + UnlockDevice(device); 2.1240 + ALCdevice_StopPlayback(device); 2.1241 + device->Flags &= ~DEVICE_RUNNING; 2.1242 + return ALC_FALSE; 2.1243 + } 2.1244 + slot->NeedsUpdate = AL_FALSE; 2.1245 + ALEffect_Update(slot->EffectState, context, slot); 2.1246 + } 2.1247 + 2.1248 + for(pos = 0;pos < context->SourceMap.size;pos++) 2.1249 + { 2.1250 + ALsource *source = context->SourceMap.array[pos].value; 2.1251 + ALuint s = device->NumAuxSends; 2.1252 + while(s < MAX_SENDS) 2.1253 + { 2.1254 + if(source->Send[s].Slot) 2.1255 + source->Send[s].Slot->refcount--; 2.1256 + source->Send[s].Slot = NULL; 2.1257 + source->Send[s].WetFilter.type = 0; 2.1258 + source->Send[s].WetFilter.filter = 0; 2.1259 + s++; 2.1260 + } 2.1261 + source->NeedsUpdate = AL_FALSE; 2.1262 + ALsource_Update(source, context); 2.1263 + } 2.1264 + } 2.1265 + UnlockDevice(device); 2.1266 + 2.1267 + return ALC_TRUE; 2.1268 +} 2.1269 + 2.1270 + 2.1271 +ALCvoid LockDevice(ALCdevice *device) 2.1272 +{ 2.1273 + EnterCriticalSection(&device->Mutex); 2.1274 +} 2.1275 + 2.1276 +ALCvoid UnlockDevice(ALCdevice *device) 2.1277 +{ 2.1278 + LeaveCriticalSection(&device->Mutex); 2.1279 +} 2.1280 + 2.1281 +/* 2.1282 + LockContext 2.1283 + 2.1284 + Thread-safe entry 2.1285 +*/ 2.1286 +ALCvoid LockContext(ALCcontext *context) 2.1287 +{ 2.1288 + EnterCriticalSection(&context->Device->Mutex); 2.1289 +} 2.1290 + 2.1291 + 2.1292 +/* 2.1293 + UnlockContext 2.1294 + 2.1295 + Thread-safe exit 2.1296 +*/ 2.1297 +ALCvoid UnlockContext(ALCcontext *context) 2.1298 +{ 2.1299 + LeaveCriticalSection(&context->Device->Mutex); 2.1300 +} 2.1301 + 2.1302 + 2.1303 +/* 2.1304 + GetLockedContext 2.1305 + 2.1306 + Returns the currently active Context, in a locked state 2.1307 +*/ 2.1308 +ALCcontext *GetLockedContext(void) 2.1309 +{ 2.1310 + ALCcontext *pContext = NULL; 2.1311 + 2.1312 + LockLists(); 2.1313 + 2.1314 + pContext = tls_get(LocalContext); 2.1315 + if(pContext && !IsContext(pContext)) 2.1316 + { 2.1317 + tls_set(LocalContext, NULL); 2.1318 + pContext = NULL; 2.1319 + } 2.1320 + if(!pContext) 2.1321 + pContext = GlobalContext; 2.1322 + if(pContext) 2.1323 + LockContext(pContext); 2.1324 + 2.1325 + UnlockLists(); 2.1326 + 2.1327 + return pContext; 2.1328 +} 2.1329 + 2.1330 + 2.1331 +/* 2.1332 + InitContext 2.1333 + 2.1334 + Initialize Context variables 2.1335 +*/ 2.1336 +static ALvoid InitContext(ALCcontext *pContext) 2.1337 +{ 2.1338 + //Initialise listener 2.1339 + pContext->Listener.Gain = 1.0f; 2.1340 + pContext->Listener.MetersPerUnit = 1.0f; 2.1341 + pContext->Listener.Position[0] = 0.0f; 2.1342 + pContext->Listener.Position[1] = 0.0f; 2.1343 + pContext->Listener.Position[2] = 0.0f; 2.1344 + pContext->Listener.Velocity[0] = 0.0f; 2.1345 + pContext->Listener.Velocity[1] = 0.0f; 2.1346 + pContext->Listener.Velocity[2] = 0.0f; 2.1347 + pContext->Listener.Forward[0] = 0.0f; 2.1348 + pContext->Listener.Forward[1] = 0.0f; 2.1349 + pContext->Listener.Forward[2] = -1.0f; 2.1350 + pContext->Listener.Up[0] = 0.0f; 2.1351 + pContext->Listener.Up[1] = 1.0f; 2.1352 + pContext->Listener.Up[2] = 0.0f; 2.1353 + 2.1354 + //Validate pContext 2.1355 + pContext->LastError = AL_NO_ERROR; 2.1356 + pContext->UpdateSources = AL_FALSE; 2.1357 + pContext->ActiveSourceCount = 0; 2.1358 + InitUIntMap(&pContext->SourceMap); 2.1359 + InitUIntMap(&pContext->EffectSlotMap); 2.1360 + 2.1361 + //Set globals 2.1362 + pContext->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED; 2.1363 + pContext->SourceDistanceModel = AL_FALSE; 2.1364 + pContext->DopplerFactor = 1.0f; 2.1365 + pContext->DopplerVelocity = 1.0f; 2.1366 + pContext->flSpeedOfSound = SPEEDOFSOUNDMETRESPERSEC; 2.1367 + pContext->DeferUpdates = AL_FALSE; 2.1368 + 2.1369 + pContext->ExtensionList = alExtList; 2.1370 +} 2.1371 + 2.1372 + 2.1373 +/* 2.1374 + FreeContext 2.1375 + 2.1376 + Clean up Context, destroy any remaining Sources 2.1377 +*/ 2.1378 +static ALCvoid FreeContext(ALCcontext *context) 2.1379 +{ 2.1380 + //Invalidate context 2.1381 + memset(context, 0, sizeof(ALCcontext)); 2.1382 + free(context); 2.1383 +} 2.1384 + 2.1385 +/////////////////////////////////////////////////////// 2.1386 + 2.1387 + 2.1388 +/////////////////////////////////////////////////////// 2.1389 +// ALC Functions calls 2.1390 + 2.1391 + 2.1392 +// This should probably move to another c file but for now ... 2.1393 +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, ALCuint frequency, ALCenum format, ALCsizei SampleSize) 2.1394 +{ 2.1395 + ALCdevice *device = NULL; 2.1396 + 2.1397 + DO_INITCONFIG(); 2.1398 + 2.1399 + if(!CaptureBackend.name) 2.1400 + { 2.1401 + alcSetError(NULL, ALC_INVALID_VALUE); 2.1402 + return NULL; 2.1403 + } 2.1404 + 2.1405 + if(SampleSize <= 0) 2.1406 + { 2.1407 + alcSetError(NULL, ALC_INVALID_VALUE); 2.1408 + return NULL; 2.1409 + } 2.1410 + 2.1411 + if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0)) 2.1412 + deviceName = NULL; 2.1413 + 2.1414 + device = calloc(1, sizeof(ALCdevice)); 2.1415 + if(!device) 2.1416 + { 2.1417 + alcSetError(NULL, ALC_OUT_OF_MEMORY); 2.1418 + return NULL; 2.1419 + } 2.1420 + 2.1421 + //Validate device 2.1422 + device->Funcs = &CaptureBackend.Funcs; 2.1423 + device->Connected = ALC_TRUE; 2.1424 + device->IsCaptureDevice = AL_TRUE; 2.1425 + device->IsLoopbackDevice = AL_FALSE; 2.1426 + InitializeCriticalSection(&device->Mutex); 2.1427 + 2.1428 + device->szDeviceName = NULL; 2.1429 + 2.1430 + device->Flags |= DEVICE_FREQUENCY_REQUEST; 2.1431 + device->Frequency = frequency; 2.1432 + 2.1433 + device->Flags |= DEVICE_CHANNELS_REQUEST; 2.1434 + if(DecomposeDevFormat(format, &device->FmtChans, &device->FmtType) == AL_FALSE) 2.1435 + { 2.1436 + free(device); 2.1437 + alcSetError(NULL, ALC_INVALID_ENUM); 2.1438 + return NULL; 2.1439 + } 2.1440 + 2.1441 + device->UpdateSize = SampleSize; 2.1442 + device->NumUpdates = 1; 2.1443 + 2.1444 + LockLists(); 2.1445 + if(ALCdevice_OpenCapture(device, deviceName)) 2.1446 + { 2.1447 + device->next = g_pDeviceList; 2.1448 + g_pDeviceList = device; 2.1449 + g_ulDeviceCount++; 2.1450 + } 2.1451 + else 2.1452 + { 2.1453 + DeleteCriticalSection(&device->Mutex); 2.1454 + free(device); 2.1455 + device = NULL; 2.1456 + alcSetError(NULL, ALC_INVALID_VALUE); 2.1457 + } 2.1458 + UnlockLists(); 2.1459 + 2.1460 + return device; 2.1461 +} 2.1462 + 2.1463 +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *pDevice) 2.1464 +{ 2.1465 + ALCdevice **list; 2.1466 + 2.1467 + LockLists(); 2.1468 + list = &g_pDeviceList; 2.1469 + while(*list && *list != pDevice) 2.1470 + list = &(*list)->next; 2.1471 + 2.1472 + if(!*list || !(*list)->IsCaptureDevice) 2.1473 + { 2.1474 + alcSetError(*list, ALC_INVALID_DEVICE); 2.1475 + UnlockLists(); 2.1476 + return ALC_FALSE; 2.1477 + } 2.1478 + 2.1479 + *list = (*list)->next; 2.1480 + g_ulDeviceCount--; 2.1481 + 2.1482 + UnlockLists(); 2.1483 + 2.1484 + LockDevice(pDevice); 2.1485 + ALCdevice_CloseCapture(pDevice); 2.1486 + UnlockDevice(pDevice); 2.1487 + 2.1488 + free(pDevice->szDeviceName); 2.1489 + pDevice->szDeviceName = NULL; 2.1490 + 2.1491 + DeleteCriticalSection(&pDevice->Mutex); 2.1492 + 2.1493 + free(pDevice); 2.1494 + 2.1495 + return ALC_TRUE; 2.1496 +} 2.1497 + 2.1498 +ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) 2.1499 +{ 2.1500 + LockLists(); 2.1501 + if(!IsDevice(device) || !device->IsCaptureDevice) 2.1502 + { 2.1503 + alcSetError(device, ALC_INVALID_DEVICE); 2.1504 + UnlockLists(); 2.1505 + return; 2.1506 + } 2.1507 + LockDevice(device); 2.1508 + UnlockLists(); 2.1509 + if(device->Connected) 2.1510 + ALCdevice_StartCapture(device); 2.1511 + UnlockDevice(device); 2.1512 +} 2.1513 + 2.1514 +ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) 2.1515 +{ 2.1516 + LockLists(); 2.1517 + if(!IsDevice(device) || !device->IsCaptureDevice) 2.1518 + { 2.1519 + alcSetError(device, ALC_INVALID_DEVICE); 2.1520 + UnlockLists(); 2.1521 + return; 2.1522 + } 2.1523 + LockDevice(device); 2.1524 + UnlockLists(); 2.1525 + if(device->Connected) 2.1526 + ALCdevice_StopCapture(device); 2.1527 + UnlockDevice(device); 2.1528 +} 2.1529 + 2.1530 +ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) 2.1531 +{ 2.1532 + LockLists(); 2.1533 + if(!IsDevice(device) || !device->IsCaptureDevice) 2.1534 + { 2.1535 + alcSetError(device, ALC_INVALID_DEVICE); 2.1536 + UnlockLists(); 2.1537 + return; 2.1538 + } 2.1539 + LockDevice(device); 2.1540 + UnlockLists(); 2.1541 + if(device->Connected) 2.1542 + ALCdevice_CaptureSamples(device, buffer, samples); 2.1543 + UnlockDevice(device); 2.1544 +} 2.1545 + 2.1546 +/* 2.1547 + alcGetError 2.1548 + 2.1549 + Return last ALC generated error code 2.1550 +*/ 2.1551 +ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) 2.1552 +{ 2.1553 + ALCenum errorCode; 2.1554 + 2.1555 + LockLists(); 2.1556 + if(IsDevice(device)) 2.1557 + { 2.1558 + errorCode = device->LastError; 2.1559 + device->LastError = ALC_NO_ERROR; 2.1560 + } 2.1561 + else 2.1562 + { 2.1563 + errorCode = g_eLastNullDeviceError; 2.1564 + g_eLastNullDeviceError = ALC_NO_ERROR; 2.1565 + } 2.1566 + UnlockLists(); 2.1567 + return errorCode; 2.1568 +} 2.1569 + 2.1570 + 2.1571 +/* 2.1572 + alcSuspendContext 2.1573 + 2.1574 + Not functional 2.1575 +*/ 2.1576 +ALC_API ALCvoid ALC_APIENTRY alcSuspendContext(ALCcontext *Context) 2.1577 +{ 2.1578 + (void)Context; 2.1579 +} 2.1580 + 2.1581 + 2.1582 +/* 2.1583 + alcProcessContext 2.1584 + 2.1585 + Not functional 2.1586 +*/ 2.1587 +ALC_API ALCvoid ALC_APIENTRY alcProcessContext(ALCcontext *Context) 2.1588 +{ 2.1589 + (void)Context; 2.1590 +} 2.1591 + 2.1592 + 2.1593 +/* 2.1594 + alcGetString 2.1595 + 2.1596 + Returns information about the Device, and error strings 2.1597 +*/ 2.1598 +ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *pDevice,ALCenum param) 2.1599 +{ 2.1600 + const ALCchar *value = NULL; 2.1601 + 2.1602 + switch(param) 2.1603 + { 2.1604 + case ALC_NO_ERROR: 2.1605 + value = alcNoError; 2.1606 + break; 2.1607 + 2.1608 + case ALC_INVALID_ENUM: 2.1609 + value = alcErrInvalidEnum; 2.1610 + break; 2.1611 + 2.1612 + case ALC_INVALID_VALUE: 2.1613 + value = alcErrInvalidValue; 2.1614 + break; 2.1615 + 2.1616 + case ALC_INVALID_DEVICE: 2.1617 + value = alcErrInvalidDevice; 2.1618 + break; 2.1619 + 2.1620 + case ALC_INVALID_CONTEXT: 2.1621 + value = alcErrInvalidContext; 2.1622 + break; 2.1623 + 2.1624 + case ALC_OUT_OF_MEMORY: 2.1625 + value = alcErrOutOfMemory; 2.1626 + break; 2.1627 + 2.1628 + case ALC_DEVICE_SPECIFIER: 2.1629 + LockLists(); 2.1630 + if(IsDevice(pDevice)) 2.1631 + value = pDevice->szDeviceName; 2.1632 + else 2.1633 + { 2.1634 + ProbeDeviceList(); 2.1635 + value = alcDeviceList; 2.1636 + } 2.1637 + UnlockLists(); 2.1638 + break; 2.1639 + 2.1640 + case ALC_ALL_DEVICES_SPECIFIER: 2.1641 + ProbeAllDeviceList(); 2.1642 + value = alcAllDeviceList; 2.1643 + break; 2.1644 + 2.1645 + case ALC_CAPTURE_DEVICE_SPECIFIER: 2.1646 + LockLists(); 2.1647 + if(IsDevice(pDevice)) 2.1648 + value = pDevice->szDeviceName; 2.1649 + else 2.1650 + { 2.1651 + ProbeCaptureDeviceList(); 2.1652 + value = alcCaptureDeviceList; 2.1653 + } 2.1654 + UnlockLists(); 2.1655 + break; 2.1656 + 2.1657 + /* Default devices are always first in the list */ 2.1658 + case ALC_DEFAULT_DEVICE_SPECIFIER: 2.1659 + if(!alcDeviceList) 2.1660 + ProbeDeviceList(); 2.1661 + 2.1662 + free(alcDefaultDeviceSpecifier); 2.1663 + alcDefaultDeviceSpecifier = strdup(alcDeviceList ? alcDeviceList : ""); 2.1664 + if(!alcDefaultDeviceSpecifier) 2.1665 + alcSetError(pDevice, ALC_OUT_OF_MEMORY); 2.1666 + value = alcDefaultDeviceSpecifier; 2.1667 + break; 2.1668 + 2.1669 + case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: 2.1670 + if(!alcAllDeviceList) 2.1671 + ProbeAllDeviceList(); 2.1672 + 2.1673 + free(alcDefaultAllDeviceSpecifier); 2.1674 + alcDefaultAllDeviceSpecifier = strdup(alcAllDeviceList ? 2.1675 + alcAllDeviceList : ""); 2.1676 + if(!alcDefaultAllDeviceSpecifier) 2.1677 + alcSetError(pDevice, ALC_OUT_OF_MEMORY); 2.1678 + value = alcDefaultAllDeviceSpecifier; 2.1679 + break; 2.1680 + 2.1681 + case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: 2.1682 + if(!alcCaptureDeviceList) 2.1683 + ProbeCaptureDeviceList(); 2.1684 + 2.1685 + free(alcCaptureDefaultDeviceSpecifier); 2.1686 + alcCaptureDefaultDeviceSpecifier = strdup(alcCaptureDeviceList ? 2.1687 + alcCaptureDeviceList : ""); 2.1688 + if(!alcCaptureDefaultDeviceSpecifier) 2.1689 + alcSetError(pDevice, ALC_OUT_OF_MEMORY); 2.1690 + value = alcCaptureDefaultDeviceSpecifier; 2.1691 + break; 2.1692 + 2.1693 + case ALC_EXTENSIONS: 2.1694 + LockLists(); 2.1695 + if(IsDevice(pDevice)) 2.1696 + value = alcExtensionList; 2.1697 + else 2.1698 + value = alcNoDeviceExtList; 2.1699 + UnlockLists(); 2.1700 + break; 2.1701 + 2.1702 + default: 2.1703 + alcSetError(pDevice, ALC_INVALID_ENUM); 2.1704 + break; 2.1705 + } 2.1706 + 2.1707 + return value; 2.1708 +} 2.1709 + 2.1710 + 2.1711 +/* 2.1712 + alcGetIntegerv 2.1713 + 2.1714 + Returns information about the Device and the version of Open AL 2.1715 +*/ 2.1716 +ALC_API ALCvoid ALC_APIENTRY alcGetIntegerv(ALCdevice *device,ALCenum param,ALsizei size,ALCint *data) 2.1717 +{ 2.1718 + if(size == 0 || data == NULL) 2.1719 + { 2.1720 + alcSetError(device, ALC_INVALID_VALUE); 2.1721 + return; 2.1722 + } 2.1723 + 2.1724 + LockLists(); 2.1725 + if(!IsDevice(device)) 2.1726 + { 2.1727 + switch(param) 2.1728 + { 2.1729 + case ALC_MAJOR_VERSION: 2.1730 + *data = alcMajorVersion; 2.1731 + break; 2.1732 + case ALC_MINOR_VERSION: 2.1733 + *data = alcMinorVersion; 2.1734 + break; 2.1735 + 2.1736 + case ALC_ATTRIBUTES_SIZE: 2.1737 + case ALC_ALL_ATTRIBUTES: 2.1738 + case ALC_FREQUENCY: 2.1739 + case ALC_REFRESH: 2.1740 + case ALC_SYNC: 2.1741 + case ALC_MONO_SOURCES: 2.1742 + case ALC_STEREO_SOURCES: 2.1743 + case ALC_CAPTURE_SAMPLES: 2.1744 + case ALC_FORMAT_CHANNELS_SOFT: 2.1745 + case ALC_FORMAT_TYPE_SOFT: 2.1746 + alcSetError(NULL, ALC_INVALID_DEVICE); 2.1747 + break; 2.1748 + 2.1749 + default: 2.1750 + alcSetError(NULL, ALC_INVALID_ENUM); 2.1751 + break; 2.1752 + } 2.1753 + } 2.1754 + else if(device->IsCaptureDevice) 2.1755 + { 2.1756 + switch(param) 2.1757 + { 2.1758 + case ALC_CAPTURE_SAMPLES: 2.1759 + LockDevice(device); 2.1760 + *data = ALCdevice_AvailableSamples(device); 2.1761 + UnlockDevice(device); 2.1762 + break; 2.1763 + 2.1764 + case ALC_CONNECTED: 2.1765 + *data = device->Connected; 2.1766 + break; 2.1767 + 2.1768 + default: 2.1769 + alcSetError(device, ALC_INVALID_ENUM); 2.1770 + break; 2.1771 + } 2.1772 + } 2.1773 + else /* render device */ 2.1774 + { 2.1775 + switch(param) 2.1776 + { 2.1777 + case ALC_MAJOR_VERSION: 2.1778 + *data = alcMajorVersion; 2.1779 + break; 2.1780 + 2.1781 + case ALC_MINOR_VERSION: 2.1782 + *data = alcMinorVersion; 2.1783 + break; 2.1784 + 2.1785 + case ALC_EFX_MAJOR_VERSION: 2.1786 + *data = alcEFXMajorVersion; 2.1787 + break; 2.1788 + 2.1789 + case ALC_EFX_MINOR_VERSION: 2.1790 + *data = alcEFXMinorVersion; 2.1791 + break; 2.1792 + 2.1793 + case ALC_ATTRIBUTES_SIZE: 2.1794 + *data = 13; 2.1795 + break; 2.1796 + 2.1797 + case ALC_ALL_ATTRIBUTES: 2.1798 + if(size < 13) 2.1799 + alcSetError(device, ALC_INVALID_VALUE); 2.1800 + else 2.1801 + { 2.1802 + int i = 0; 2.1803 + 2.1804 + data[i++] = ALC_FREQUENCY; 2.1805 + data[i++] = device->Frequency; 2.1806 + 2.1807 + if(!device->IsLoopbackDevice) 2.1808 + { 2.1809 + data[i++] = ALC_REFRESH; 2.1810 + data[i++] = device->Frequency / device->UpdateSize; 2.1811 + 2.1812 + data[i++] = ALC_SYNC; 2.1813 + data[i++] = ALC_FALSE; 2.1814 + } 2.1815 + else 2.1816 + { 2.1817 + data[i++] = ALC_FORMAT_CHANNELS_SOFT; 2.1818 + data[i++] = device->FmtChans; 2.1819 + 2.1820 + data[i++] = ALC_FORMAT_TYPE_SOFT; 2.1821 + data[i++] = device->FmtType; 2.1822 + } 2.1823 + 2.1824 + data[i++] = ALC_MONO_SOURCES; 2.1825 + data[i++] = device->NumMonoSources; 2.1826 + 2.1827 + data[i++] = ALC_STEREO_SOURCES; 2.1828 + data[i++] = device->NumStereoSources; 2.1829 + 2.1830 + data[i++] = ALC_MAX_AUXILIARY_SENDS; 2.1831 + data[i++] = device->NumAuxSends; 2.1832 + 2.1833 + data[i++] = 0; 2.1834 + } 2.1835 + break; 2.1836 + 2.1837 + case ALC_FREQUENCY: 2.1838 + *data = device->Frequency; 2.1839 + break; 2.1840 + 2.1841 + case ALC_REFRESH: 2.1842 + if(device->IsLoopbackDevice) 2.1843 + alcSetError(device, ALC_INVALID_DEVICE); 2.1844 + else 2.1845 + *data = device->Frequency / device->UpdateSize; 2.1846 + break; 2.1847 + 2.1848 + case ALC_SYNC: 2.1849 + if(device->IsLoopbackDevice) 2.1850 + alcSetError(device, ALC_INVALID_DEVICE); 2.1851 + else 2.1852 + *data = ALC_FALSE; 2.1853 + break; 2.1854 + 2.1855 + case ALC_FORMAT_CHANNELS_SOFT: 2.1856 + if(!device->IsLoopbackDevice) 2.1857 + alcSetError(device, ALC_INVALID_DEVICE); 2.1858 + else 2.1859 + *data = device->FmtChans; 2.1860 + break; 2.1861 + 2.1862 + case ALC_FORMAT_TYPE_SOFT: 2.1863 + if(!device->IsLoopbackDevice) 2.1864 + alcSetError(device, ALC_INVALID_DEVICE); 2.1865 + else 2.1866 + *data = device->FmtType; 2.1867 + break; 2.1868 + 2.1869 + case ALC_MONO_SOURCES: 2.1870 + *data = device->NumMonoSources; 2.1871 + break; 2.1872 + 2.1873 + case ALC_STEREO_SOURCES: 2.1874 + *data = device->NumStereoSources; 2.1875 + break; 2.1876 + 2.1877 + case ALC_MAX_AUXILIARY_SENDS: 2.1878 + *data = device->NumAuxSends; 2.1879 + break; 2.1880 + 2.1881 + case ALC_CONNECTED: 2.1882 + *data = device->Connected; 2.1883 + break; 2.1884 + 2.1885 + default: 2.1886 + alcSetError(device, ALC_INVALID_ENUM); 2.1887 + break; 2.1888 + } 2.1889 + } 2.1890 + UnlockLists(); 2.1891 +} 2.1892 + 2.1893 + 2.1894 +/* 2.1895 + alcIsExtensionPresent 2.1896 + 2.1897 + Determines if there is support for a particular extension 2.1898 +*/ 2.1899 +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const ALCchar *extName) 2.1900 +{ 2.1901 + ALCboolean bResult = ALC_FALSE; 2.1902 + const char *ptr; 2.1903 + size_t len; 2.1904 + 2.1905 + if(!extName) 2.1906 + { 2.1907 + alcSetError(device, ALC_INVALID_VALUE); 2.1908 + return ALC_FALSE; 2.1909 + } 2.1910 + 2.1911 + len = strlen(extName); 2.1912 + LockLists(); 2.1913 + ptr = (IsDevice(device) ? alcExtensionList : alcNoDeviceExtList); 2.1914 + UnlockLists(); 2.1915 + while(ptr && *ptr) 2.1916 + { 2.1917 + if(strncasecmp(ptr, extName, len) == 0 && 2.1918 + (ptr[len] == '\0' || isspace(ptr[len]))) 2.1919 + { 2.1920 + bResult = ALC_TRUE; 2.1921 + break; 2.1922 + } 2.1923 + if((ptr=strchr(ptr, ' ')) != NULL) 2.1924 + { 2.1925 + do { 2.1926 + ++ptr; 2.1927 + } while(isspace(*ptr)); 2.1928 + } 2.1929 + } 2.1930 + 2.1931 + return bResult; 2.1932 +} 2.1933 + 2.1934 + 2.1935 +/* 2.1936 + alcGetProcAddress 2.1937 + 2.1938 + Retrieves the function address for a particular extension function 2.1939 +*/ 2.1940 +ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar *funcName) 2.1941 +{ 2.1942 + ALsizei i = 0; 2.1943 + 2.1944 + if(!funcName) 2.1945 + { 2.1946 + alcSetError(device, ALC_INVALID_VALUE); 2.1947 + return NULL; 2.1948 + } 2.1949 + 2.1950 + while(alcFunctions[i].funcName && strcmp(alcFunctions[i].funcName,funcName) != 0) 2.1951 + i++; 2.1952 + return alcFunctions[i].address; 2.1953 +} 2.1954 + 2.1955 + 2.1956 +/* 2.1957 + alcGetEnumValue 2.1958 + 2.1959 + Get the value for a particular ALC Enumerated Value 2.1960 +*/ 2.1961 +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *enumName) 2.1962 +{ 2.1963 + ALsizei i = 0; 2.1964 + 2.1965 + if(!enumName) 2.1966 + { 2.1967 + alcSetError(device, ALC_INVALID_VALUE); 2.1968 + return (ALCenum)0; 2.1969 + } 2.1970 + 2.1971 + while(enumeration[i].enumName && strcmp(enumeration[i].enumName,enumName) != 0) 2.1972 + i++; 2.1973 + return enumeration[i].value; 2.1974 +} 2.1975 + 2.1976 + 2.1977 +/* 2.1978 + alcCreateContext 2.1979 + 2.1980 + Create and attach a Context to a particular Device. 2.1981 +*/ 2.1982 +ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCint *attrList) 2.1983 +{ 2.1984 + ALCcontext *ALContext; 2.1985 + void *temp; 2.1986 + 2.1987 + LockLists(); 2.1988 + if(!IsDevice(device) || device->IsCaptureDevice || !device->Connected) 2.1989 + { 2.1990 + alcSetError(device, ALC_INVALID_DEVICE); 2.1991 + UnlockLists(); 2.1992 + return NULL; 2.1993 + } 2.1994 + 2.1995 + // Reset Context Last Error code 2.1996 + device->LastError = ALC_NO_ERROR; 2.1997 + 2.1998 + if(UpdateDeviceParams(device, attrList) == ALC_FALSE) 2.1999 + { 2.2000 + alcSetError(device, ALC_INVALID_DEVICE); 2.2001 + aluHandleDisconnect(device); 2.2002 + UnlockLists(); 2.2003 + return NULL; 2.2004 + } 2.2005 + 2.2006 + LockDevice(device); 2.2007 + ALContext = NULL; 2.2008 + temp = realloc(device->Contexts, (device->NumContexts+1) * sizeof(*device->Contexts)); 2.2009 + if(temp) 2.2010 + { 2.2011 + device->Contexts = temp; 2.2012 + 2.2013 + ALContext = calloc(1, sizeof(ALCcontext)); 2.2014 + if(ALContext) 2.2015 + { 2.2016 + ALContext->MaxActiveSources = 256; 2.2017 + ALContext->ActiveSources = malloc(sizeof(ALContext->ActiveSources[0]) * 2.2018 + ALContext->MaxActiveSources); 2.2019 + } 2.2020 + } 2.2021 + if(!ALContext || !ALContext->ActiveSources) 2.2022 + { 2.2023 + free(ALContext); 2.2024 + alcSetError(device, ALC_OUT_OF_MEMORY); 2.2025 + UnlockDevice(device); 2.2026 + if(device->NumContexts == 0) 2.2027 + { 2.2028 + ALCdevice_StopPlayback(device); 2.2029 + device->Flags &= ~DEVICE_RUNNING; 2.2030 + } 2.2031 + UnlockLists(); 2.2032 + return NULL; 2.2033 + } 2.2034 + 2.2035 + device->Contexts[device->NumContexts++] = ALContext; 2.2036 + ALContext->Device = device; 2.2037 + 2.2038 + InitContext(ALContext); 2.2039 + UnlockDevice(device); 2.2040 + 2.2041 + ALContext->next = g_pContextList; 2.2042 + g_pContextList = ALContext; 2.2043 + g_ulContextCount++; 2.2044 + 2.2045 + UnlockLists(); 2.2046 + 2.2047 + return ALContext; 2.2048 +} 2.2049 + 2.2050 + 2.2051 +/* 2.2052 + alcDestroyContext 2.2053 + 2.2054 + Remove a Context 2.2055 +*/ 2.2056 +ALC_API ALCvoid ALC_APIENTRY alcDestroyContext(ALCcontext *context) 2.2057 +{ 2.2058 + ALCdevice *Device; 2.2059 + ALCcontext **list; 2.2060 + ALuint i; 2.2061 + 2.2062 + LockLists(); 2.2063 + list = &g_pContextList; 2.2064 + while(*list && *list != context) 2.2065 + list = &(*list)->next; 2.2066 + 2.2067 + if(!*list) 2.2068 + { 2.2069 + alcSetError(NULL, ALC_INVALID_CONTEXT); 2.2070 + UnlockLists(); 2.2071 + return; 2.2072 + } 2.2073 + 2.2074 + *list = (*list)->next; 2.2075 + g_ulContextCount--; 2.2076 + 2.2077 + if(context == tls_get(LocalContext)) 2.2078 + tls_set(LocalContext, NULL); 2.2079 + if(context == GlobalContext) 2.2080 + GlobalContext = NULL; 2.2081 + 2.2082 + Device = context->Device; 2.2083 + LockDevice(Device); 2.2084 + for(i = 0;i < Device->NumContexts;i++) 2.2085 + { 2.2086 + if(Device->Contexts[i] == context) 2.2087 + { 2.2088 + Device->Contexts[i] = Device->Contexts[Device->NumContexts-1]; 2.2089 + Device->NumContexts--; 2.2090 + break; 2.2091 + } 2.2092 + } 2.2093 + UnlockDevice(Device); 2.2094 + 2.2095 + if(Device->NumContexts == 0) 2.2096 + { 2.2097 + ALCdevice_StopPlayback(Device); 2.2098 + Device->Flags &= ~DEVICE_RUNNING; 2.2099 + } 2.2100 + UnlockLists(); 2.2101 + 2.2102 + if(context->SourceMap.size > 0) 2.2103 + { 2.2104 + ERR("alcDestroyContext(): deleting %d Source(s)\n", context->SourceMap.size); 2.2105 + ReleaseALSources(context); 2.2106 + } 2.2107 + ResetUIntMap(&context->SourceMap); 2.2108 + 2.2109 + if(context->EffectSlotMap.size > 0) 2.2110 + { 2.2111 + ERR("alcDestroyContext(): deleting %d AuxiliaryEffectSlot(s)\n", context->EffectSlotMap.size); 2.2112 + ReleaseALAuxiliaryEffectSlots(context); 2.2113 + } 2.2114 + ResetUIntMap(&context->EffectSlotMap); 2.2115 + 2.2116 + free(context->ActiveSources); 2.2117 + context->ActiveSources = NULL; 2.2118 + context->MaxActiveSources = 0; 2.2119 + context->ActiveSourceCount = 0; 2.2120 + 2.2121 + FreeContext(context); 2.2122 +} 2.2123 + 2.2124 + 2.2125 +/* 2.2126 + alcGetCurrentContext 2.2127 + 2.2128 + Returns the currently active Context 2.2129 +*/ 2.2130 +ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(ALCvoid) 2.2131 +{ 2.2132 + ALCcontext *Context; 2.2133 + 2.2134 + LockLists(); 2.2135 + Context = tls_get(LocalContext); 2.2136 + if(Context && !IsContext(Context)) 2.2137 + { 2.2138 + tls_set(LocalContext, NULL); 2.2139 + Context = NULL; 2.2140 + } 2.2141 + if(!Context) 2.2142 + Context = GlobalContext; 2.2143 + UnlockLists(); 2.2144 + 2.2145 + return Context; 2.2146 +} 2.2147 + 2.2148 +/* 2.2149 + alcGetThreadContext 2.2150 + 2.2151 + Returns the currently active thread-local Context 2.2152 +*/ 2.2153 +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) 2.2154 +{ 2.2155 + ALCcontext *pContext = NULL; 2.2156 + 2.2157 + LockLists(); 2.2158 + 2.2159 + pContext = tls_get(LocalContext); 2.2160 + if(pContext && !IsContext(pContext)) 2.2161 + { 2.2162 + tls_set(LocalContext, NULL); 2.2163 + pContext = NULL; 2.2164 + } 2.2165 + 2.2166 + UnlockLists(); 2.2167 + 2.2168 + return pContext; 2.2169 +} 2.2170 + 2.2171 + 2.2172 +/* 2.2173 + alcGetContextsDevice 2.2174 + 2.2175 + Returns the Device that a particular Context is attached to 2.2176 +*/ 2.2177 +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice(ALCcontext *pContext) 2.2178 +{ 2.2179 + ALCdevice *pDevice = NULL; 2.2180 + 2.2181 + LockLists(); 2.2182 + if(IsContext(pContext)) 2.2183 + pDevice = pContext->Device; 2.2184 + else 2.2185 + alcSetError(NULL, ALC_INVALID_CONTEXT); 2.2186 + UnlockLists(); 2.2187 + 2.2188 + return pDevice; 2.2189 +} 2.2190 + 2.2191 + 2.2192 +/* 2.2193 + alcMakeContextCurrent 2.2194 + 2.2195 + Makes the given Context the active Context 2.2196 +*/ 2.2197 +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) 2.2198 +{ 2.2199 + ALboolean bReturn = AL_TRUE; 2.2200 + 2.2201 + LockLists(); 2.2202 + 2.2203 + // context must be a valid Context or NULL 2.2204 + if(context == NULL || IsContext(context)) 2.2205 + { 2.2206 + GlobalContext = context; 2.2207 + tls_set(LocalContext, NULL); 2.2208 + } 2.2209 + else 2.2210 + { 2.2211 + alcSetError(NULL, ALC_INVALID_CONTEXT); 2.2212 + bReturn = AL_FALSE; 2.2213 + } 2.2214 + 2.2215 + UnlockLists(); 2.2216 + 2.2217 + return bReturn; 2.2218 +} 2.2219 + 2.2220 +/* 2.2221 + alcSetThreadContext 2.2222 + 2.2223 + Makes the given Context the active Context for the current thread 2.2224 +*/ 2.2225 +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context) 2.2226 +{ 2.2227 + ALboolean bReturn = AL_TRUE; 2.2228 + 2.2229 + LockLists(); 2.2230 + 2.2231 + // context must be a valid Context or NULL 2.2232 + if(context == NULL || IsContext(context)) 2.2233 + tls_set(LocalContext, context); 2.2234 + else 2.2235 + { 2.2236 + alcSetError(NULL, ALC_INVALID_CONTEXT); 2.2237 + bReturn = AL_FALSE; 2.2238 + } 2.2239 + 2.2240 + UnlockLists(); 2.2241 + 2.2242 + return bReturn; 2.2243 +} 2.2244 + 2.2245 + 2.2246 +static void GetFormatFromString(const char *str, enum DevFmtChannels *chans, enum DevFmtType *type) 2.2247 +{ 2.2248 + if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) 2.2249 + { 2.2250 + *chans = DevFmtMono; 2.2251 + *type = DevFmtFloat; 2.2252 + return; 2.2253 + } 2.2254 + if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) 2.2255 + { 2.2256 + *chans = DevFmtStereo; 2.2257 + *type = DevFmtFloat; 2.2258 + return; 2.2259 + } 2.2260 + if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) 2.2261 + { 2.2262 + *chans = DevFmtQuad; 2.2263 + *type = DevFmtFloat; 2.2264 + return; 2.2265 + } 2.2266 + if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) 2.2267 + { 2.2268 + *chans = DevFmtX51; 2.2269 + *type = DevFmtFloat; 2.2270 + return; 2.2271 + } 2.2272 + if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) 2.2273 + { 2.2274 + *chans = DevFmtX61; 2.2275 + *type = DevFmtFloat; 2.2276 + return; 2.2277 + } 2.2278 + if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) 2.2279 + { 2.2280 + *chans = DevFmtX71; 2.2281 + *type = DevFmtFloat; 2.2282 + return; 2.2283 + } 2.2284 + 2.2285 + if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) 2.2286 + { 2.2287 + *chans = DevFmtMono; 2.2288 + *type = DevFmtShort; 2.2289 + return; 2.2290 + } 2.2291 + if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) 2.2292 + { 2.2293 + *chans = DevFmtStereo; 2.2294 + *type = DevFmtShort; 2.2295 + return; 2.2296 + } 2.2297 + if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) 2.2298 + { 2.2299 + *chans = DevFmtQuad; 2.2300 + *type = DevFmtShort; 2.2301 + return; 2.2302 + } 2.2303 + if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) 2.2304 + { 2.2305 + *chans = DevFmtX51; 2.2306 + *type = DevFmtShort; 2.2307 + return; 2.2308 + } 2.2309 + if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) 2.2310 + { 2.2311 + *chans = DevFmtX61; 2.2312 + *type = DevFmtShort; 2.2313 + return; 2.2314 + } 2.2315 + if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) 2.2316 + { 2.2317 + *chans = DevFmtX71; 2.2318 + *type = DevFmtShort; 2.2319 + return; 2.2320 + } 2.2321 + 2.2322 + if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) 2.2323 + { 2.2324 + *chans = DevFmtMono; 2.2325 + *type = DevFmtByte; 2.2326 + return; 2.2327 + } 2.2328 + if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) 2.2329 + { 2.2330 + *chans = DevFmtStereo; 2.2331 + *type = DevFmtByte; 2.2332 + return; 2.2333 + } 2.2334 + if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) 2.2335 + { 2.2336 + *chans = DevFmtQuad; 2.2337 + *type = DevFmtByte; 2.2338 + return; 2.2339 + } 2.2340 + if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) 2.2341 + { 2.2342 + *chans = DevFmtX51; 2.2343 + *type = DevFmtByte; 2.2344 + return; 2.2345 + } 2.2346 + if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) 2.2347 + { 2.2348 + *chans = DevFmtX61; 2.2349 + *type = DevFmtByte; 2.2350 + return; 2.2351 + } 2.2352 + if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) 2.2353 + { 2.2354 + *chans = DevFmtX71; 2.2355 + *type = DevFmtByte; 2.2356 + return; 2.2357 + } 2.2358 + 2.2359 + ERR("Unknown format: \"%s\"\n", str); 2.2360 + *chans = DevFmtStereo; 2.2361 + *type = DevFmtShort; 2.2362 +} 2.2363 + 2.2364 +/* 2.2365 + alcOpenDevice 2.2366 + 2.2367 + Open the Device specified. 2.2368 +*/ 2.2369 +ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) 2.2370 +{ 2.2371 + const ALCchar *fmt; 2.2372 + ALCdevice *device; 2.2373 + 2.2374 + DO_INITCONFIG(); 2.2375 + 2.2376 + if(!PlaybackBackend.name) 2.2377 + { 2.2378 + alcSetError(NULL, ALC_INVALID_VALUE); 2.2379 + return NULL; 2.2380 + } 2.2381 + 2.2382 + if(deviceName && (!deviceName[0] || strcasecmp(deviceName, "openal soft") == 0 || strcasecmp(deviceName, "openal-soft") == 0)) 2.2383 + deviceName = NULL; 2.2384 + 2.2385 + device = calloc(1, sizeof(ALCdevice)); 2.2386 + if(!device) 2.2387 + { 2.2388 + alcSetError(NULL, ALC_OUT_OF_MEMORY); 2.2389 + return NULL; 2.2390 + } 2.2391 + 2.2392 + //Validate device 2.2393 + device->Funcs = &PlaybackBackend.Funcs; 2.2394 + device->Connected = ALC_TRUE; 2.2395 + device->IsCaptureDevice = AL_FALSE; 2.2396 + device->IsLoopbackDevice = AL_FALSE; 2.2397 + InitializeCriticalSection(&device->Mutex); 2.2398 + device->LastError = ALC_NO_ERROR; 2.2399 + 2.2400 + device->Flags = 0; 2.2401 + device->Bs2b = NULL; 2.2402 + device->szDeviceName = NULL; 2.2403 + 2.2404 + device->Contexts = NULL; 2.2405 + device->NumContexts = 0; 2.2406 + 2.2407 + InitUIntMap(&device->BufferMap); 2.2408 + InitUIntMap(&device->EffectMap); 2.2409 + InitUIntMap(&device->FilterMap); 2.2410 + 2.2411 + //Set output format 2.2412 + if(ConfigValueExists(NULL, "frequency")) 2.2413 + device->Flags |= DEVICE_FREQUENCY_REQUEST; 2.2414 + device->Frequency = GetConfigValueInt(NULL, "frequency", DEFAULT_OUTPUT_RATE); 2.2415 + if(device->Frequency < 8000) 2.2416 + device->Frequency = 8000; 2.2417 + 2.2418 + if(ConfigValueExists(NULL, "format")) 2.2419 + device->Flags |= DEVICE_CHANNELS_REQUEST; 2.2420 + fmt = GetConfigValue(NULL, "format", "AL_FORMAT_STEREO16"); 2.2421 + GetFormatFromString(fmt, &device->FmtChans, &device->FmtType); 2.2422 + 2.2423 + device->NumUpdates = GetConfigValueInt(NULL, "periods", 4); 2.2424 + if(device->NumUpdates < 2) 2.2425 + device->NumUpdates = 4; 2.2426 + 2.2427 + device->UpdateSize = GetConfigValueInt(NULL, "period_size", 1024); 2.2428 + if(device->UpdateSize <= 0) 2.2429 + device->UpdateSize = 1024; 2.2430 + 2.2431 + device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256); 2.2432 + if(device->MaxNoOfSources <= 0) 2.2433 + device->MaxNoOfSources = 256; 2.2434 + 2.2435 + device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4); 2.2436 + if(device->AuxiliaryEffectSlotMax <= 0) 2.2437 + device->AuxiliaryEffectSlotMax = 4; 2.2438 + 2.2439 + device->NumStereoSources = 1; 2.2440 + device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources; 2.2441 + 2.2442 + device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS); 2.2443 + if(device->NumAuxSends > MAX_SENDS) 2.2444 + device->NumAuxSends = MAX_SENDS; 2.2445 + 2.2446 + device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0); 2.2447 + 2.2448 + // Find a playback device to open 2.2449 + LockLists(); 2.2450 + if(ALCdevice_OpenPlayback(device, deviceName)) 2.2451 + { 2.2452 + device->next = g_pDeviceList; 2.2453 + g_pDeviceList = device; 2.2454 + g_ulDeviceCount++; 2.2455 + } 2.2456 + else 2.2457 + { 2.2458 + // No suitable output device found 2.2459 + DeleteCriticalSection(&device->Mutex); 2.2460 + free(device); 2.2461 + device = NULL; 2.2462 + alcSetError(NULL, ALC_INVALID_VALUE); 2.2463 + } 2.2464 + UnlockLists(); 2.2465 + 2.2466 + return device; 2.2467 +} 2.2468 + 2.2469 + 2.2470 +/* 2.2471 + alcCloseDevice 2.2472 + 2.2473 + Close the specified Device 2.2474 +*/ 2.2475 +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *pDevice) 2.2476 +{ 2.2477 + ALCdevice **list; 2.2478 + 2.2479 + LockLists(); 2.2480 + list = &g_pDeviceList; 2.2481 + while(*list && *list != pDevice) 2.2482 + list = &(*list)->next; 2.2483 + 2.2484 + if(!*list || (*list)->IsCaptureDevice) 2.2485 + { 2.2486 + alcSetError(*list, ALC_INVALID_DEVICE); 2.2487 + UnlockLists(); 2.2488 + return ALC_FALSE; 2.2489 + } 2.2490 + 2.2491 + *list = (*list)->next; 2.2492 + g_ulDeviceCount--; 2.2493 + 2.2494 + UnlockLists(); 2.2495 + 2.2496 + if(pDevice->NumContexts > 0) 2.2497 + { 2.2498 + WARN("alcCloseDevice(): destroying %u Context(s)\n", pDevice->NumContexts); 2.2499 + while(pDevice->NumContexts > 0) 2.2500 + alcDestroyContext(pDevice->Contexts[0]); 2.2501 + } 2.2502 + ALCdevice_ClosePlayback(pDevice); 2.2503 + 2.2504 + if(pDevice->BufferMap.size > 0) 2.2505 + { 2.2506 + WARN("alcCloseDevice(): deleting %d Buffer(s)\n", pDevice->BufferMap.size); 2.2507 + ReleaseALBuffers(pDevice); 2.2508 + } 2.2509 + ResetUIntMap(&pDevice->BufferMap); 2.2510 + 2.2511 + if(pDevice->EffectMap.size > 0) 2.2512 + { 2.2513 + WARN("alcCloseDevice(): deleting %d Effect(s)\n", pDevice->EffectMap.size); 2.2514 + ReleaseALEffects(pDevice); 2.2515 + } 2.2516 + ResetUIntMap(&pDevice->EffectMap); 2.2517 + 2.2518 + if(pDevice->FilterMap.size > 0) 2.2519 + { 2.2520 + WARN("alcCloseDevice(): deleting %d Filter(s)\n", pDevice->FilterMap.size); 2.2521 + ReleaseALFilters(pDevice); 2.2522 + } 2.2523 + ResetUIntMap(&pDevice->FilterMap); 2.2524 + 2.2525 + free(pDevice->Bs2b); 2.2526 + pDevice->Bs2b = NULL; 2.2527 + 2.2528 + free(pDevice->szDeviceName); 2.2529 + pDevice->szDeviceName = NULL; 2.2530 + 2.2531 + free(pDevice->Contexts); 2.2532 + pDevice->Contexts = NULL; 2.2533 + 2.2534 + DeleteCriticalSection(&pDevice->Mutex); 2.2535 + 2.2536 + //Release device structure 2.2537 + memset(pDevice, 0, sizeof(ALCdevice)); 2.2538 + free(pDevice); 2.2539 + 2.2540 + return ALC_TRUE; 2.2541 +} 2.2542 + 2.2543 + 2.2544 +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void) 2.2545 +{ 2.2546 + ALCdevice *device; 2.2547 + 2.2548 + DO_INITCONFIG(); 2.2549 + 2.2550 + device = calloc(1, sizeof(ALCdevice)); 2.2551 + if(!device) 2.2552 + { 2.2553 + alcSetError(NULL, ALC_OUT_OF_MEMORY); 2.2554 + return NULL; 2.2555 + } 2.2556 + 2.2557 + //Validate device 2.2558 + device->Funcs = &BackendLoopback.Funcs; 2.2559 + device->Connected = ALC_TRUE; 2.2560 + device->IsCaptureDevice = AL_FALSE; 2.2561 + device->IsLoopbackDevice = AL_TRUE; 2.2562 + InitializeCriticalSection(&device->Mutex); 2.2563 + device->LastError = ALC_NO_ERROR; 2.2564 + 2.2565 + device->Flags = 0; 2.2566 + device->Bs2b = NULL; 2.2567 + device->szDeviceName = NULL; 2.2568 + 2.2569 + device->Contexts = NULL; 2.2570 + device->NumContexts = 0; 2.2571 + 2.2572 + InitUIntMap(&device->BufferMap); 2.2573 + InitUIntMap(&device->EffectMap); 2.2574 + InitUIntMap(&device->FilterMap); 2.2575 + 2.2576 + //Set output format 2.2577 + device->Frequency = 44100; 2.2578 + device->FmtChans = DevFmtStereo; 2.2579 + device->FmtType = DevFmtShort; 2.2580 + 2.2581 + device->NumUpdates = 0; 2.2582 + device->UpdateSize = 0; 2.2583 + 2.2584 + device->MaxNoOfSources = GetConfigValueInt(NULL, "sources", 256); 2.2585 + if(device->MaxNoOfSources <= 0) 2.2586 + device->MaxNoOfSources = 256; 2.2587 + 2.2588 + device->AuxiliaryEffectSlotMax = GetConfigValueInt(NULL, "slots", 4); 2.2589 + if(device->AuxiliaryEffectSlotMax <= 0) 2.2590 + device->AuxiliaryEffectSlotMax = 4; 2.2591 + 2.2592 + device->NumStereoSources = 1; 2.2593 + device->NumMonoSources = device->MaxNoOfSources - device->NumStereoSources; 2.2594 + 2.2595 + device->NumAuxSends = GetConfigValueInt(NULL, "sends", MAX_SENDS); 2.2596 + if(device->NumAuxSends > MAX_SENDS) 2.2597 + device->NumAuxSends = MAX_SENDS; 2.2598 + 2.2599 + device->Bs2bLevel = GetConfigValueInt(NULL, "cf_level", 0); 2.2600 + 2.2601 + // Open the "backend" 2.2602 + LockLists(); 2.2603 + ALCdevice_OpenPlayback(device, "Loopback"); 2.2604 + 2.2605 + device->next = g_pDeviceList; 2.2606 + g_pDeviceList = device; 2.2607 + g_ulDeviceCount++; 2.2608 + UnlockLists(); 2.2609 + 2.2610 + return device; 2.2611 +} 2.2612 + 2.2613 +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type) 2.2614 +{ 2.2615 + ALCboolean ret = ALC_FALSE; 2.2616 + 2.2617 + LockLists(); 2.2618 + if(!IsDevice(device) || !device->IsLoopbackDevice) 2.2619 + alcSetError(device, ALC_INVALID_DEVICE); 2.2620 + else if(freq <= 0) 2.2621 + alcSetError(device, ALC_INVALID_VALUE); 2.2622 + else if(!IsValidALCType(type) || !IsValidALCChannels(channels)) 2.2623 + alcSetError(device, ALC_INVALID_ENUM); 2.2624 + else 2.2625 + { 2.2626 + if(BytesFromDevFmt(type) > 0 && ChannelsFromDevFmt(channels) > 0 && 2.2627 + freq >= 8000) 2.2628 + ret = ALC_TRUE; 2.2629 + } 2.2630 + UnlockLists(); 2.2631 + 2.2632 + return ret; 2.2633 +} 2.2634 + 2.2635 +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) 2.2636 +{ 2.2637 + LockLists(); 2.2638 + if(!IsDevice(device) || !device->IsLoopbackDevice) 2.2639 + alcSetError(device, ALC_INVALID_DEVICE); 2.2640 + else if(samples < 0 || (samples > 0 && buffer == NULL)) 2.2641 + alcSetError(device, ALC_INVALID_VALUE); 2.2642 + else 2.2643 + aluMixData(device, buffer, samples); 2.2644 + UnlockLists(); 2.2645 +} 2.2646 + 2.2647 + 2.2648 +static void ReleaseALC(ALCboolean doclose) 2.2649 +{ 2.2650 + free(alcDeviceList); alcDeviceList = NULL; 2.2651 + alcDeviceListSize = 0; 2.2652 + free(alcAllDeviceList); alcAllDeviceList = NULL; 2.2653 + alcAllDeviceListSize = 0; 2.2654 + free(alcCaptureDeviceList); alcCaptureDeviceList = NULL; 2.2655 + alcCaptureDeviceListSize = 0; 2.2656 + 2.2657 + free(alcDefaultDeviceSpecifier); 2.2658 + alcDefaultDeviceSpecifier = NULL; 2.2659 + free(alcDefaultAllDeviceSpecifier); 2.2660 + alcDefaultAllDeviceSpecifier = NULL; 2.2661 + free(alcCaptureDefaultDeviceSpecifier); 2.2662 + alcCaptureDefaultDeviceSpecifier = NULL; 2.2663 + 2.2664 + if(doclose) 2.2665 + { 2.2666 + if(g_ulDeviceCount > 0) 2.2667 + WARN("ReleaseALC(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":""); 2.2668 + 2.2669 + while(g_pDeviceList) 2.2670 + { 2.2671 + if(g_pDeviceList->IsCaptureDevice) 2.2672 + alcCaptureCloseDevice(g_pDeviceList); 2.2673 + else 2.2674 + alcCloseDevice(g_pDeviceList); 2.2675 + } 2.2676 + } 2.2677 + else 2.2678 + { 2.2679 + if(g_ulDeviceCount > 0) 2.2680 + WARN("ReleaseALC(): %u Device%s not closed\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":""); 2.2681 + } 2.2682 +} 2.2683 + 2.2684 +///////////////////////////////////////////////////////
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/Alc/ALu.c Tue Oct 25 13:02:31 2011 -0700 3.3 @@ -0,0 +1,1168 @@ 3.4 +/** 3.5 + * OpenAL cross platform audio library 3.6 + * Copyright (C) 1999-2007 by authors. 3.7 + * This library is free software; you can redistribute it and/or 3.8 + * modify it under the terms of the GNU Library General Public 3.9 + * License as published by the Free Software Foundation; either 3.10 + * version 2 of the License, or (at your option) any later version. 3.11 + * 3.12 + * This library is distributed in the hope that it will be useful, 3.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 3.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 3.15 + * Library General Public License for more details. 3.16 + * 3.17 + * You should have received a copy of the GNU Library General Public 3.18 + * License along with this library; if not, write to the 3.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 3.20 + * Boston, MA 02111-1307, USA. 3.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 3.22 + */ 3.23 + 3.24 +#include "config.h" 3.25 + 3.26 +#include <math.h> 3.27 +#include <stdlib.h> 3.28 +#include <string.h> 3.29 +#include <ctype.h> 3.30 +#include <assert.h> 3.31 + 3.32 +#include "alMain.h" 3.33 +#include "AL/al.h" 3.34 +#include "AL/alc.h" 3.35 +#include "alSource.h" 3.36 +#include "alBuffer.h" 3.37 +#include "alListener.h" 3.38 +#include "alAuxEffectSlot.h" 3.39 +#include "alu.h" 3.40 +#include "bs2b.h" 3.41 + 3.42 + 3.43 +static __inline ALvoid aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector) 3.44 +{ 3.45 + outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1]; 3.46 + outVector[1] = inVector1[2]*inVector2[0] - inVector1[0]*inVector2[2]; 3.47 + outVector[2] = inVector1[0]*inVector2[1] - inVector1[1]*inVector2[0]; 3.48 +} 3.49 + 3.50 +static __inline ALfloat aluDotproduct(const ALfloat *inVector1, const ALfloat *inVector2) 3.51 +{ 3.52 + return inVector1[0]*inVector2[0] + inVector1[1]*inVector2[1] + 3.53 + inVector1[2]*inVector2[2]; 3.54 +} 3.55 + 3.56 +static __inline ALvoid aluNormalize(ALfloat *inVector) 3.57 +{ 3.58 + ALfloat length, inverse_length; 3.59 + 3.60 + length = aluSqrt(aluDotproduct(inVector, inVector)); 3.61 + if(length != 0.0f) 3.62 + { 3.63 + inverse_length = 1.0f/length; 3.64 + inVector[0] *= inverse_length; 3.65 + inVector[1] *= inverse_length; 3.66 + inVector[2] *= inverse_length; 3.67 + } 3.68 +} 3.69 + 3.70 +static __inline ALvoid aluMatrixVector(ALfloat *vector,ALfloat w,ALfloat matrix[4][4]) 3.71 +{ 3.72 + ALfloat temp[4] = { 3.73 + vector[0], vector[1], vector[2], w 3.74 + }; 3.75 + 3.76 + vector[0] = temp[0]*matrix[0][0] + temp[1]*matrix[1][0] + temp[2]*matrix[2][0] + temp[3]*matrix[3][0]; 3.77 + vector[1] = temp[0]*matrix[0][1] + temp[1]*matrix[1][1] + temp[2]*matrix[2][1] + temp[3]*matrix[3][1]; 3.78 + vector[2] = temp[0]*matrix[0][2] + temp[1]*matrix[1][2] + temp[2]*matrix[2][2] + temp[3]*matrix[3][2]; 3.79 +} 3.80 + 3.81 + 3.82 +ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) 3.83 +{ 3.84 + static const ALfloat angles_Mono[1] = { 0.0f }; 3.85 + static const ALfloat angles_Stereo[2] = { -30.0f, 30.0f }; 3.86 + static const ALfloat angles_Rear[2] = { -150.0f, 150.0f }; 3.87 + static const ALfloat angles_Quad[4] = { -45.0f, 45.0f, -135.0f, 135.0f }; 3.88 + static const ALfloat angles_X51[6] = { -30.0f, 30.0f, 0.0f, 0.0f, 3.89 + -110.0f, 110.0f }; 3.90 + static const ALfloat angles_X61[7] = { -30.0f, 30.0f, 0.0f, 0.0f, 3.91 + 180.0f, -90.0f, 90.0f }; 3.92 + static const ALfloat angles_X71[8] = { -30.0f, 30.0f, 0.0f, 0.0f, 3.93 + -110.0f, 110.0f, -90.0f, 90.0f }; 3.94 + 3.95 + static const enum Channel chans_Mono[1] = { FRONT_CENTER }; 3.96 + static const enum Channel chans_Stereo[2] = { FRONT_LEFT, FRONT_RIGHT }; 3.97 + static const enum Channel chans_Rear[2] = { BACK_LEFT, BACK_RIGHT }; 3.98 + static const enum Channel chans_Quad[4] = { FRONT_LEFT, FRONT_RIGHT, 3.99 + BACK_LEFT, BACK_RIGHT }; 3.100 + static const enum Channel chans_X51[6] = { FRONT_LEFT, FRONT_RIGHT, 3.101 + FRONT_CENTER, LFE, 3.102 + BACK_LEFT, BACK_RIGHT }; 3.103 + static const enum Channel chans_X61[7] = { FRONT_LEFT, FRONT_RIGHT, 3.104 + FRONT_CENTER, LFE, BACK_CENTER, 3.105 + SIDE_LEFT, SIDE_RIGHT }; 3.106 + static const enum Channel chans_X71[8] = { FRONT_LEFT, FRONT_RIGHT, 3.107 + FRONT_CENTER, LFE, 3.108 + BACK_LEFT, BACK_RIGHT, 3.109 + SIDE_LEFT, SIDE_RIGHT }; 3.110 + 3.111 + ALCdevice *Device = ALContext->Device; 3.112 + ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume; 3.113 + ALbufferlistitem *BufferListItem; 3.114 + enum DevFmtChannels DevChans; 3.115 + enum FmtChannels Channels; 3.116 + ALfloat (*SrcMatrix)[MAXCHANNELS]; 3.117 + ALfloat DryGain, DryGainHF; 3.118 + ALfloat WetGain[MAX_SENDS]; 3.119 + ALfloat WetGainHF[MAX_SENDS]; 3.120 + ALint NumSends, Frequency; 3.121 + const ALfloat *SpeakerGain; 3.122 + const ALfloat *angles = NULL; 3.123 + const enum Channel *chans = NULL; 3.124 + enum Resampler Resampler; 3.125 + ALint num_channels = 0; 3.126 + ALboolean VirtualChannels; 3.127 + ALfloat Pitch; 3.128 + ALfloat cw; 3.129 + ALuint pos; 3.130 + ALint i, c; 3.131 + 3.132 + /* Get device properties */ 3.133 + DevChans = ALContext->Device->FmtChans; 3.134 + NumSends = ALContext->Device->NumAuxSends; 3.135 + Frequency = ALContext->Device->Frequency; 3.136 + 3.137 + /* Get listener properties */ 3.138 + ListenerGain = ALContext->Listener.Gain; 3.139 + 3.140 + /* Get source properties */ 3.141 + SourceVolume = ALSource->flGain; 3.142 + MinVolume = ALSource->flMinGain; 3.143 + MaxVolume = ALSource->flMaxGain; 3.144 + Pitch = ALSource->flPitch; 3.145 + Resampler = ALSource->Resampler; 3.146 + VirtualChannels = ALSource->VirtualChannels; 3.147 + 3.148 + /* Calculate the stepping value */ 3.149 + Channels = FmtMono; 3.150 + BufferListItem = ALSource->queue; 3.151 + while(BufferListItem != NULL) 3.152 + { 3.153 + ALbuffer *ALBuffer; 3.154 + if((ALBuffer=BufferListItem->buffer) != NULL) 3.155 + { 3.156 + ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels / 3.157 + ALSource->SampleSize; 3.158 + maxstep -= ResamplerPadding[Resampler] + 3.159 + ResamplerPrePadding[Resampler] + 1; 3.160 + maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS); 3.161 + 3.162 + Pitch = Pitch * ALBuffer->Frequency / Frequency; 3.163 + if(Pitch > (ALfloat)maxstep) 3.164 + ALSource->Params.Step = maxstep<<FRACTIONBITS; 3.165 + else 3.166 + { 3.167 + ALSource->Params.Step = Pitch*FRACTIONONE; 3.168 + if(ALSource->Params.Step == 0) 3.169 + ALSource->Params.Step = 1; 3.170 + } 3.171 + 3.172 + Channels = ALBuffer->FmtChannels; 3.173 + 3.174 + if(ALSource->VirtualChannels && (Device->Flags&DEVICE_USE_HRTF)) 3.175 + ALSource->Params.DoMix = SelectHrtfMixer(ALBuffer, 3.176 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 3.177 + Resampler); 3.178 + else 3.179 + ALSource->Params.DoMix = SelectMixer(ALBuffer, 3.180 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 3.181 + Resampler); 3.182 + break; 3.183 + } 3.184 + BufferListItem = BufferListItem->next; 3.185 + } 3.186 + 3.187 + /* Calculate gains */ 3.188 + DryGain = clampf(SourceVolume, MinVolume, MaxVolume); 3.189 + DryGainHF = 1.0f; 3.190 + switch(ALSource->DirectFilter.type) 3.191 + { 3.192 + case AL_FILTER_LOWPASS: 3.193 + DryGain *= ALSource->DirectFilter.Gain; 3.194 + DryGainHF *= ALSource->DirectFilter.GainHF; 3.195 + break; 3.196 + } 3.197 + for(i = 0;i < NumSends;i++) 3.198 + { 3.199 + WetGain[i] = clampf(SourceVolume, MinVolume, MaxVolume); 3.200 + WetGainHF[i] = 1.0f; 3.201 + switch(ALSource->Send[i].WetFilter.type) 3.202 + { 3.203 + case AL_FILTER_LOWPASS: 3.204 + WetGain[i] *= ALSource->Send[i].WetFilter.Gain; 3.205 + WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; 3.206 + break; 3.207 + } 3.208 + } 3.209 + 3.210 + SrcMatrix = ALSource->Params.DryGains; 3.211 + for(i = 0;i < MAXCHANNELS;i++) 3.212 + { 3.213 + for(c = 0;c < MAXCHANNELS;c++) 3.214 + SrcMatrix[i][c] = 0.0f; 3.215 + } 3.216 + switch(Channels) 3.217 + { 3.218 + case FmtMono: 3.219 + angles = angles_Mono; 3.220 + chans = chans_Mono; 3.221 + num_channels = 1; 3.222 + break; 3.223 + case FmtStereo: 3.224 + if(VirtualChannels && (ALContext->Device->Flags&DEVICE_DUPLICATE_STEREO)) 3.225 + { 3.226 + DryGain *= aluSqrt(2.0f/4.0f); 3.227 + for(c = 0;c < 2;c++) 3.228 + { 3.229 + pos = aluCart2LUTpos(cos(angles_Rear[c] * (M_PI/180.0)), 3.230 + sin(angles_Rear[c] * (M_PI/180.0))); 3.231 + SpeakerGain = Device->PanningLUT[pos]; 3.232 + 3.233 + for(i = 0;i < (ALint)Device->NumChan;i++) 3.234 + { 3.235 + enum Channel chan = Device->Speaker2Chan[i]; 3.236 + SrcMatrix[c][chan] += DryGain * ListenerGain * 3.237 + SpeakerGain[chan]; 3.238 + } 3.239 + } 3.240 + } 3.241 + angles = angles_Stereo; 3.242 + chans = chans_Stereo; 3.243 + num_channels = 2; 3.244 + break; 3.245 + 3.246 + case FmtRear: 3.247 + angles = angles_Rear; 3.248 + chans = chans_Rear; 3.249 + num_channels = 2; 3.250 + break; 3.251 + 3.252 + case FmtQuad: 3.253 + angles = angles_Quad; 3.254 + chans = chans_Quad; 3.255 + num_channels = 4; 3.256 + break; 3.257 + 3.258 + case FmtX51: 3.259 + angles = angles_X51; 3.260 + chans = chans_X51; 3.261 + num_channels = 6; 3.262 + break; 3.263 + 3.264 + case FmtX61: 3.265 + angles = angles_X61; 3.266 + chans = chans_X61; 3.267 + num_channels = 7; 3.268 + break; 3.269 + 3.270 + case FmtX71: 3.271 + angles = angles_X71; 3.272 + chans = chans_X71; 3.273 + num_channels = 8; 3.274 + break; 3.275 + } 3.276 + 3.277 + if(VirtualChannels == AL_FALSE) 3.278 + { 3.279 + for(c = 0;c < num_channels;c++) 3.280 + SrcMatrix[c][chans[c]] += DryGain * ListenerGain; 3.281 + } 3.282 + else if((Device->Flags&DEVICE_USE_HRTF)) 3.283 + { 3.284 + for(c = 0;c < num_channels;c++) 3.285 + { 3.286 + if(chans[c] == LFE) 3.287 + { 3.288 + /* Skip LFE */ 3.289 + ALSource->Params.HrtfDelay[c][0] = 0; 3.290 + ALSource->Params.HrtfDelay[c][1] = 0; 3.291 + for(i = 0;i < HRIR_LENGTH;i++) 3.292 + { 3.293 + ALSource->Params.HrtfCoeffs[c][i][0] = 0.0f; 3.294 + ALSource->Params.HrtfCoeffs[c][i][1] = 0.0f; 3.295 + } 3.296 + } 3.297 + else 3.298 + { 3.299 + /* Get the static HRIR coefficients and delays for this 3.300 + * channel. */ 3.301 + GetLerpedHrtfCoeffs(0.0, angles[c] * (M_PI/180.0), 3.302 + DryGain*ListenerGain, 3.303 + ALSource->Params.HrtfCoeffs[c], 3.304 + ALSource->Params.HrtfDelay[c]); 3.305 + } 3.306 + ALSource->HrtfCounter = 0; 3.307 + } 3.308 + } 3.309 + else 3.310 + { 3.311 + for(c = 0;c < num_channels;c++) 3.312 + { 3.313 + if(chans[c] == LFE) /* Special-case LFE */ 3.314 + { 3.315 + SrcMatrix[c][LFE] += DryGain * ListenerGain; 3.316 + continue; 3.317 + } 3.318 + pos = aluCart2LUTpos(cos(angles[c] * (M_PI/180.0)), 3.319 + sin(angles[c] * (M_PI/180.0))); 3.320 + SpeakerGain = Device->PanningLUT[pos]; 3.321 + 3.322 + for(i = 0;i < (ALint)Device->NumChan;i++) 3.323 + { 3.324 + enum Channel chan = Device->Speaker2Chan[i]; 3.325 + SrcMatrix[c][chan] += DryGain * ListenerGain * 3.326 + SpeakerGain[chan]; 3.327 + } 3.328 + } 3.329 + } 3.330 + for(i = 0;i < NumSends;i++) 3.331 + { 3.332 + ALSource->Params.Send[i].Slot = ALSource->Send[i].Slot; 3.333 + ALSource->Params.Send[i].WetGain = WetGain[i] * ListenerGain; 3.334 + } 3.335 + 3.336 + /* Update filter coefficients. Calculations based on the I3DL2 3.337 + * spec. */ 3.338 + cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency); 3.339 + 3.340 + /* We use two chained one-pole filters, so we need to take the 3.341 + * square root of the squared gain, which is the same as the base 3.342 + * gain. */ 3.343 + ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw); 3.344 + for(i = 0;i < NumSends;i++) 3.345 + { 3.346 + /* We use a one-pole filter, so we need to take the squared gain */ 3.347 + ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw); 3.348 + ALSource->Params.Send[i].iirFilter.coeff = a; 3.349 + } 3.350 +} 3.351 + 3.352 +ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) 3.353 +{ 3.354 + const ALCdevice *Device = ALContext->Device; 3.355 + ALfloat InnerAngle,OuterAngle,Angle,Distance,ClampedDist; 3.356 + ALfloat Direction[3],Position[3],SourceToListener[3]; 3.357 + ALfloat Velocity[3],ListenerVel[3]; 3.358 + ALfloat MinVolume,MaxVolume,MinDist,MaxDist,Rolloff; 3.359 + ALfloat ConeVolume,ConeHF,SourceVolume,ListenerGain; 3.360 + ALfloat DopplerFactor, DopplerVelocity, SpeedOfSound; 3.361 + ALfloat AirAbsorptionFactor; 3.362 + ALfloat RoomAirAbsorption[MAX_SENDS]; 3.363 + ALbufferlistitem *BufferListItem; 3.364 + ALfloat Attenuation, EffectiveDist; 3.365 + ALfloat RoomAttenuation[MAX_SENDS]; 3.366 + ALfloat MetersPerUnit; 3.367 + ALfloat RoomRolloffBase; 3.368 + ALfloat RoomRolloff[MAX_SENDS]; 3.369 + ALfloat DecayDistance[MAX_SENDS]; 3.370 + ALfloat DryGain; 3.371 + ALfloat DryGainHF; 3.372 + ALboolean DryGainHFAuto; 3.373 + ALfloat WetGain[MAX_SENDS]; 3.374 + ALfloat WetGainHF[MAX_SENDS]; 3.375 + ALboolean WetGainAuto; 3.376 + ALboolean WetGainHFAuto; 3.377 + enum Resampler Resampler; 3.378 + ALfloat Pitch; 3.379 + ALuint Frequency; 3.380 + ALint NumSends; 3.381 + ALfloat cw; 3.382 + ALint i; 3.383 + 3.384 + DryGainHF = 1.0f; 3.385 + for(i = 0;i < MAX_SENDS;i++) 3.386 + WetGainHF[i] = 1.0f; 3.387 + 3.388 + //Get context properties 3.389 + DopplerFactor = ALContext->DopplerFactor * ALSource->DopplerFactor; 3.390 + DopplerVelocity = ALContext->DopplerVelocity; 3.391 + SpeedOfSound = ALContext->flSpeedOfSound; 3.392 + NumSends = Device->NumAuxSends; 3.393 + Frequency = Device->Frequency; 3.394 + 3.395 + //Get listener properties 3.396 + ListenerGain = ALContext->Listener.Gain; 3.397 + MetersPerUnit = ALContext->Listener.MetersPerUnit; 3.398 + memcpy(ListenerVel, ALContext->Listener.Velocity, sizeof(ALContext->Listener.Velocity)); 3.399 + 3.400 + //Get source properties 3.401 + SourceVolume = ALSource->flGain; 3.402 + MinVolume = ALSource->flMinGain; 3.403 + MaxVolume = ALSource->flMaxGain; 3.404 + Pitch = ALSource->flPitch; 3.405 + Resampler = ALSource->Resampler; 3.406 + memcpy(Position, ALSource->vPosition, sizeof(ALSource->vPosition)); 3.407 + memcpy(Direction, ALSource->vOrientation, sizeof(ALSource->vOrientation)); 3.408 + memcpy(Velocity, ALSource->vVelocity, sizeof(ALSource->vVelocity)); 3.409 + MinDist = ALSource->flRefDistance; 3.410 + MaxDist = ALSource->flMaxDistance; 3.411 + Rolloff = ALSource->flRollOffFactor; 3.412 + InnerAngle = ALSource->flInnerAngle * ConeScale; 3.413 + OuterAngle = ALSource->flOuterAngle * ConeScale; 3.414 + AirAbsorptionFactor = ALSource->AirAbsorptionFactor; 3.415 + DryGainHFAuto = ALSource->DryGainHFAuto; 3.416 + WetGainAuto = ALSource->WetGainAuto; 3.417 + WetGainHFAuto = ALSource->WetGainHFAuto; 3.418 + RoomRolloffBase = ALSource->RoomRolloffFactor; 3.419 + for(i = 0;i < NumSends;i++) 3.420 + { 3.421 + ALeffectslot *Slot = ALSource->Send[i].Slot; 3.422 + 3.423 + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) 3.424 + { 3.425 + RoomRolloff[i] = 0.0f; 3.426 + DecayDistance[i] = 0.0f; 3.427 + RoomAirAbsorption[i] = 1.0f; 3.428 + } 3.429 + else if(Slot->AuxSendAuto) 3.430 + { 3.431 + RoomRolloff[i] = RoomRolloffBase; 3.432 + if(IsReverbEffect(Slot->effect.type)) 3.433 + { 3.434 + RoomRolloff[i] += Slot->effect.Params.Reverb.RoomRolloffFactor; 3.435 + DecayDistance[i] = Slot->effect.Params.Reverb.DecayTime * 3.436 + SPEEDOFSOUNDMETRESPERSEC; 3.437 + RoomAirAbsorption[i] = Slot->effect.Params.Reverb.AirAbsorptionGainHF; 3.438 + } 3.439 + else 3.440 + { 3.441 + DecayDistance[i] = 0.0f; 3.442 + RoomAirAbsorption[i] = 1.0f; 3.443 + } 3.444 + } 3.445 + else 3.446 + { 3.447 + /* If the slot's auxiliary send auto is off, the data sent to the 3.448 + * effect slot is the same as the dry path, sans filter effects */ 3.449 + RoomRolloff[i] = Rolloff; 3.450 + DecayDistance[i] = 0.0f; 3.451 + RoomAirAbsorption[i] = AIRABSORBGAINHF; 3.452 + } 3.453 + 3.454 + ALSource->Params.Send[i].Slot = Slot; 3.455 + } 3.456 + 3.457 + //1. Translate Listener to origin (convert to head relative) 3.458 + if(ALSource->bHeadRelative == AL_FALSE) 3.459 + { 3.460 + ALfloat U[3],V[3],N[3]; 3.461 + ALfloat Matrix[4][4]; 3.462 + 3.463 + // Build transform matrix 3.464 + memcpy(N, ALContext->Listener.Forward, sizeof(N)); // At-vector 3.465 + aluNormalize(N); // Normalized At-vector 3.466 + memcpy(V, ALContext->Listener.Up, sizeof(V)); // Up-vector 3.467 + aluNormalize(V); // Normalized Up-vector 3.468 + aluCrossproduct(N, V, U); // Right-vector 3.469 + aluNormalize(U); // Normalized Right-vector 3.470 + Matrix[0][0] = U[0]; Matrix[0][1] = V[0]; Matrix[0][2] = -N[0]; Matrix[0][3] = 0.0f; 3.471 + Matrix[1][0] = U[1]; Matrix[1][1] = V[1]; Matrix[1][2] = -N[1]; Matrix[1][3] = 0.0f; 3.472 + Matrix[2][0] = U[2]; Matrix[2][1] = V[2]; Matrix[2][2] = -N[2]; Matrix[2][3] = 0.0f; 3.473 + Matrix[3][0] = 0.0f; Matrix[3][1] = 0.0f; Matrix[3][2] = 0.0f; Matrix[3][3] = 1.0f; 3.474 + 3.475 + // Translate position 3.476 + Position[0] -= ALContext->Listener.Position[0]; 3.477 + Position[1] -= ALContext->Listener.Position[1]; 3.478 + Position[2] -= ALContext->Listener.Position[2]; 3.479 + 3.480 + // Transform source position and direction into listener space 3.481 + aluMatrixVector(Position, 1.0f, Matrix); 3.482 + aluMatrixVector(Direction, 0.0f, Matrix); 3.483 + // Transform source and listener velocity into listener space 3.484 + aluMatrixVector(Velocity, 0.0f, Matrix); 3.485 + aluMatrixVector(ListenerVel, 0.0f, Matrix); 3.486 + } 3.487 + else 3.488 + ListenerVel[0] = ListenerVel[1] = ListenerVel[2] = 0.0f; 3.489 + 3.490 + SourceToListener[0] = -Position[0]; 3.491 + SourceToListener[1] = -Position[1]; 3.492 + SourceToListener[2] = -Position[2]; 3.493 + aluNormalize(SourceToListener); 3.494 + aluNormalize(Direction); 3.495 + 3.496 + //2. Calculate distance attenuation 3.497 + Distance = aluSqrt(aluDotproduct(Position, Position)); 3.498 + ClampedDist = Distance; 3.499 + 3.500 + Attenuation = 1.0f; 3.501 + for(i = 0;i < NumSends;i++) 3.502 + RoomAttenuation[i] = 1.0f; 3.503 + switch(ALContext->SourceDistanceModel ? ALSource->DistanceModel : 3.504 + ALContext->DistanceModel) 3.505 + { 3.506 + case InverseDistanceClamped: 3.507 + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); 3.508 + if(MaxDist < MinDist) 3.509 + break; 3.510 + //fall-through 3.511 + case InverseDistance: 3.512 + if(MinDist > 0.0f) 3.513 + { 3.514 + if((MinDist + (Rolloff * (ClampedDist - MinDist))) > 0.0f) 3.515 + Attenuation = MinDist / (MinDist + (Rolloff * (ClampedDist - MinDist))); 3.516 + for(i = 0;i < NumSends;i++) 3.517 + { 3.518 + if((MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))) > 0.0f) 3.519 + RoomAttenuation[i] = MinDist / (MinDist + (RoomRolloff[i] * (ClampedDist - MinDist))); 3.520 + } 3.521 + } 3.522 + break; 3.523 + 3.524 + case LinearDistanceClamped: 3.525 + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); 3.526 + if(MaxDist < MinDist) 3.527 + break; 3.528 + //fall-through 3.529 + case LinearDistance: 3.530 + if(MaxDist != MinDist) 3.531 + { 3.532 + Attenuation = 1.0f - (Rolloff*(ClampedDist-MinDist)/(MaxDist - MinDist)); 3.533 + Attenuation = maxf(Attenuation, 0.0f); 3.534 + for(i = 0;i < NumSends;i++) 3.535 + { 3.536 + RoomAttenuation[i] = 1.0f - (RoomRolloff[i]*(ClampedDist-MinDist)/(MaxDist - MinDist)); 3.537 + RoomAttenuation[i] = maxf(RoomAttenuation[i], 0.0f); 3.538 + } 3.539 + } 3.540 + break; 3.541 + 3.542 + case ExponentDistanceClamped: 3.543 + ClampedDist = clampf(ClampedDist, MinDist, MaxDist); 3.544 + if(MaxDist < MinDist) 3.545 + break; 3.546 + //fall-through 3.547 + case ExponentDistance: 3.548 + if(ClampedDist > 0.0f && MinDist > 0.0f) 3.549 + { 3.550 + Attenuation = aluPow(ClampedDist/MinDist, -Rolloff); 3.551 + for(i = 0;i < NumSends;i++) 3.552 + RoomAttenuation[i] = aluPow(ClampedDist/MinDist, -RoomRolloff[i]); 3.553 + } 3.554 + break; 3.555 + 3.556 + case DisableDistance: 3.557 + break; 3.558 + } 3.559 + 3.560 + // Source Gain + Attenuation 3.561 + DryGain = SourceVolume * Attenuation; 3.562 + for(i = 0;i < NumSends;i++) 3.563 + WetGain[i] = SourceVolume * RoomAttenuation[i]; 3.564 + 3.565 + // Distance-based air absorption 3.566 + EffectiveDist = 0.0f; 3.567 + if(MinDist > 0.0f && Attenuation < 1.0f) 3.568 + EffectiveDist = (MinDist/Attenuation - MinDist)*MetersPerUnit; 3.569 + if(AirAbsorptionFactor > 0.0f && EffectiveDist > 0.0f) 3.570 + { 3.571 + DryGainHF *= aluPow(AIRABSORBGAINHF, AirAbsorptionFactor*EffectiveDist); 3.572 + for(i = 0;i < NumSends;i++) 3.573 + WetGainHF[i] *= aluPow(RoomAirAbsorption[i], 3.574 + AirAbsorptionFactor*EffectiveDist); 3.575 + } 3.576 + 3.577 + //3. Apply directional soundcones 3.578 + Angle = aluAcos(aluDotproduct(Direction,SourceToListener)) * (180.0/M_PI); 3.579 + if(Angle >= InnerAngle && Angle <= OuterAngle) 3.580 + { 3.581 + ALfloat scale = (Angle-InnerAngle) / (OuterAngle-InnerAngle); 3.582 + ConeVolume = lerp(1.0, ALSource->flOuterGain, scale); 3.583 + ConeHF = lerp(1.0, ALSource->OuterGainHF, scale); 3.584 + } 3.585 + else if(Angle > OuterAngle) 3.586 + { 3.587 + ConeVolume = ALSource->flOuterGain; 3.588 + ConeHF = ALSource->OuterGainHF; 3.589 + } 3.590 + else 3.591 + { 3.592 + ConeVolume = 1.0f; 3.593 + ConeHF = 1.0f; 3.594 + } 3.595 + 3.596 + DryGain *= ConeVolume; 3.597 + if(WetGainAuto) 3.598 + { 3.599 + for(i = 0;i < NumSends;i++) 3.600 + WetGain[i] *= ConeVolume; 3.601 + } 3.602 + if(DryGainHFAuto) 3.603 + DryGainHF *= ConeHF; 3.604 + if(WetGainHFAuto) 3.605 + { 3.606 + for(i = 0;i < NumSends;i++) 3.607 + WetGainHF[i] *= ConeHF; 3.608 + } 3.609 + 3.610 + // Clamp to Min/Max Gain 3.611 + DryGain = clampf(DryGain, MinVolume, MaxVolume); 3.612 + for(i = 0;i < NumSends;i++) 3.613 + WetGain[i] = clampf(WetGain[i], MinVolume, MaxVolume); 3.614 + 3.615 + // Apply filter gains and filters 3.616 + switch(ALSource->DirectFilter.type) 3.617 + { 3.618 + case AL_FILTER_LOWPASS: 3.619 + DryGain *= ALSource->DirectFilter.Gain; 3.620 + DryGainHF *= ALSource->DirectFilter.GainHF; 3.621 + break; 3.622 + } 3.623 + DryGain *= ListenerGain; 3.624 + for(i = 0;i < NumSends;i++) 3.625 + { 3.626 + switch(ALSource->Send[i].WetFilter.type) 3.627 + { 3.628 + case AL_FILTER_LOWPASS: 3.629 + WetGain[i] *= ALSource->Send[i].WetFilter.Gain; 3.630 + WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; 3.631 + break; 3.632 + } 3.633 + WetGain[i] *= ListenerGain; 3.634 + } 3.635 + 3.636 + if(WetGainAuto) 3.637 + { 3.638 + /* Apply a decay-time transformation to the wet path, based on the 3.639 + * attenuation of the dry path. 3.640 + * 3.641 + * Using the approximate (effective) source to listener distance, the 3.642 + * initial decay of the reverb effect is calculated and applied to the 3.643 + * wet path. 3.644 + */ 3.645 + for(i = 0;i < NumSends;i++) 3.646 + { 3.647 + if(DecayDistance[i] > 0.0f) 3.648 + WetGain[i] *= aluPow(0.001f /* -60dB */, 3.649 + EffectiveDist / DecayDistance[i]); 3.650 + } 3.651 + } 3.652 + 3.653 + // Calculate Velocity 3.654 + if(DopplerFactor != 0.0f) 3.655 + { 3.656 + ALfloat VSS, VLS; 3.657 + ALfloat MaxVelocity = (SpeedOfSound*DopplerVelocity) / 3.658 + DopplerFactor; 3.659 + 3.660 + VSS = aluDotproduct(Velocity, SourceToListener); 3.661 + if(VSS >= MaxVelocity) 3.662 + VSS = (MaxVelocity - 1.0f); 3.663 + else if(VSS <= -MaxVelocity) 3.664 + VSS = -MaxVelocity + 1.0f; 3.665 + 3.666 + VLS = aluDotproduct(ListenerVel, SourceToListener); 3.667 + if(VLS >= MaxVelocity) 3.668 + VLS = (MaxVelocity - 1.0f); 3.669 + else if(VLS <= -MaxVelocity) 3.670 + VLS = -MaxVelocity + 1.0f; 3.671 + 3.672 + Pitch *= ((SpeedOfSound*DopplerVelocity) - (DopplerFactor*VLS)) / 3.673 + ((SpeedOfSound*DopplerVelocity) - (DopplerFactor*VSS)); 3.674 + } 3.675 + 3.676 + BufferListItem = ALSource->queue; 3.677 + while(BufferListItem != NULL) 3.678 + { 3.679 + ALbuffer *ALBuffer; 3.680 + if((ALBuffer=BufferListItem->buffer) != NULL) 3.681 + { 3.682 + ALint maxstep = STACK_DATA_SIZE / ALSource->NumChannels / 3.683 + ALSource->SampleSize; 3.684 + maxstep -= ResamplerPadding[Resampler] + 3.685 + ResamplerPrePadding[Resampler] + 1; 3.686 + maxstep = mini(maxstep, INT_MAX>>FRACTIONBITS); 3.687 + 3.688 + Pitch = Pitch * ALBuffer->Frequency / Frequency; 3.689 + if(Pitch > (ALfloat)maxstep) 3.690 + ALSource->Params.Step = maxstep<<FRACTIONBITS; 3.691 + else 3.692 + { 3.693 + ALSource->Params.Step = Pitch*FRACTIONONE; 3.694 + if(ALSource->Params.Step == 0) 3.695 + ALSource->Params.Step = 1; 3.696 + } 3.697 + 3.698 + if((Device->Flags&DEVICE_USE_HRTF)) 3.699 + ALSource->Params.DoMix = SelectHrtfMixer(ALBuffer, 3.700 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 3.701 + Resampler); 3.702 + else 3.703 + ALSource->Params.DoMix = SelectMixer(ALBuffer, 3.704 + (ALSource->Params.Step==FRACTIONONE) ? POINT_RESAMPLER : 3.705 + Resampler); 3.706 + break; 3.707 + } 3.708 + BufferListItem = BufferListItem->next; 3.709 + } 3.710 + 3.711 + if((Device->Flags&DEVICE_USE_HRTF)) 3.712 + { 3.713 + // Use a binaural HRTF algorithm for stereo headphone playback 3.714 + ALfloat delta, ev = 0.0f, az = 0.0f; 3.715 + 3.716 + if(Distance > 0.0f) 3.717 + { 3.718 + ALfloat invlen = 1.0f/Distance; 3.719 + Position[0] *= invlen; 3.720 + Position[1] *= invlen; 3.721 + Position[2] *= invlen; 3.722 + 3.723 + // Calculate elevation and azimuth only when the source is not at 3.724 + // the listener. This prevents +0 and -0 Z from producing 3.725 + // inconsistent panning. 3.726 + ev = asin(Position[1]); 3.727 + az = atan2(Position[0], -Position[2]*ZScale); 3.728 + } 3.729 + 3.730 + // Check to see if the HRIR is already moving. 3.731 + if(ALSource->HrtfMoving) 3.732 + { 3.733 + // Calculate the normalized HRTF transition factor (delta). 3.734 + delta = CalcHrtfDelta(ALSource->Params.HrtfGain, DryGain, 3.735 + ALSource->Params.HrtfDir, Position); 3.736 + // If the delta is large enough, get the moving HRIR target 3.737 + // coefficients, target delays, steppping values, and counter. 3.738 + if(delta > 0.001f) 3.739 + { 3.740 + ALSource->HrtfCounter = GetMovingHrtfCoeffs(ev, az, DryGain, 3.741 + delta, ALSource->HrtfCounter, 3.742 + ALSource->Params.HrtfCoeffs[0], 3.743 + ALSource->Params.HrtfDelay[0], 3.744 + ALSource->Params.HrtfCoeffStep, 3.745 + ALSource->Params.HrtfDelayStep); 3.746 + ALSource->Params.HrtfGain = DryGain; 3.747 + ALSource->Params.HrtfDir[0] = Position[0]; 3.748 + ALSource->Params.HrtfDir[1] = Position[1]; 3.749 + ALSource->Params.HrtfDir[2] = Position[2]; 3.750 + } 3.751 + } 3.752 + else 3.753 + { 3.754 + // Get the initial (static) HRIR coefficients and delays. 3.755 + GetLerpedHrtfCoeffs(ev, az, DryGain, 3.756 + ALSource->Params.HrtfCoeffs[0], 3.757 + ALSource->Params.HrtfDelay[0]); 3.758 + ALSource->HrtfCounter = 0; 3.759 + ALSource->Params.HrtfGain = DryGain; 3.760 + ALSource->Params.HrtfDir[0] = Position[0]; 3.761 + ALSource->Params.HrtfDir[1] = Position[1]; 3.762 + ALSource->Params.HrtfDir[2] = Position[2]; 3.763 + } 3.764 + } 3.765 + else 3.766 + { 3.767 + // Use energy-preserving panning algorithm for multi-speaker playback 3.768 + ALfloat DirGain, AmbientGain; 3.769 + const ALfloat *SpeakerGain; 3.770 + ALfloat length; 3.771 + ALint pos; 3.772 + 3.773 + length = maxf(Distance, MinDist); 3.774 + if(length > 0.0f) 3.775 + { 3.776 + ALfloat invlen = 1.0f/length; 3.777 + Position[0] *= invlen; 3.778 + Position[1] *= invlen; 3.779 + Position[2] *= invlen; 3.780 + } 3.781 + 3.782 + pos = aluCart2LUTpos(-Position[2]*ZScale, Position[0]); 3.783 + SpeakerGain = Device->PanningLUT[pos]; 3.784 + 3.785 + DirGain = aluSqrt(Position[0]*Position[0] + Position[2]*Position[2]); 3.786 + // elevation adjustment for directional gain. this sucks, but 3.787 + // has low complexity 3.788 + AmbientGain = aluSqrt(1.0/Device->NumChan); 3.789 + for(i = 0;i < MAXCHANNELS;i++) 3.790 + { 3.791 + ALuint i2; 3.792 + for(i2 = 0;i2 < MAXCHANNELS;i2++) 3.793 + ALSource->Params.DryGains[i][i2] = 0.0f; 3.794 + } 3.795 + for(i = 0;i < (ALint)Device->NumChan;i++) 3.796 + { 3.797 + enum Channel chan = Device->Speaker2Chan[i]; 3.798 + ALfloat gain = lerp(AmbientGain, SpeakerGain[chan], DirGain); 3.799 + ALSource->Params.DryGains[0][chan] = DryGain * gain; 3.800 + } 3.801 + } 3.802 + for(i = 0;i < NumSends;i++) 3.803 + ALSource->Params.Send[i].WetGain = WetGain[i]; 3.804 + 3.805 + /* Update filter coefficients. */ 3.806 + cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency); 3.807 + 3.808 + ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw); 3.809 + for(i = 0;i < NumSends;i++) 3.810 + { 3.811 + ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw); 3.812 + ALSource->Params.Send[i].iirFilter.coeff = a; 3.813 + } 3.814 +} 3.815 + 3.816 + 3.817 +static __inline ALfloat aluF2F(ALfloat val) 3.818 +{ return val; } 3.819 +static __inline ALshort aluF2S(ALfloat val) 3.820 +{ 3.821 + if(val > 1.0f) return 32767; 3.822 + if(val < -1.0f) return -32768; 3.823 + return (ALint)(val*32767.0f); 3.824 +} 3.825 +static __inline ALushort aluF2US(ALfloat val) 3.826 +{ return aluF2S(val)+32768; } 3.827 +static __inline ALbyte aluF2B(ALfloat val) 3.828 +{ return aluF2S(val)>>8; } 3.829 +static __inline ALubyte aluF2UB(ALfloat val) 3.830 +{ return aluF2US(val)>>8; } 3.831 + 3.832 +#define DECL_TEMPLATE(T, N, func) \ 3.833 +static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \ 3.834 + ALuint SamplesToDo) \ 3.835 +{ \ 3.836 + ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS] = device->DryBuffer; \ 3.837 + const enum Channel *ChanMap = device->DevChannels; \ 3.838 + ALuint i, j; \ 3.839 + \ 3.840 + for(i = 0;i < SamplesToDo;i++) \ 3.841 + { \ 3.842 + for(j = 0;j < N;j++) \ 3.843 + *(buffer++) = func(DryBuffer[i][ChanMap[j]]); \ 3.844 + } \ 3.845 +} 3.846 + 3.847 +DECL_TEMPLATE(ALfloat, 1, aluF2F) 3.848 +DECL_TEMPLATE(ALfloat, 4, aluF2F) 3.849 +DECL_TEMPLATE(ALfloat, 6, aluF2F) 3.850 +DECL_TEMPLATE(ALfloat, 7, aluF2F) 3.851 +DECL_TEMPLATE(ALfloat, 8, aluF2F) 3.852 + 3.853 +DECL_TEMPLATE(ALushort, 1, aluF2US) 3.854 +DECL_TEMPLATE(ALushort, 4, aluF2US) 3.855 +DECL_TEMPLATE(ALushort, 6, aluF2US) 3.856 +DECL_TEMPLATE(ALushort, 7, aluF2US) 3.857 +DECL_TEMPLATE(ALushort, 8, aluF2US) 3.858 + 3.859 +DECL_TEMPLATE(ALshort, 1, aluF2S) 3.860 +DECL_TEMPLATE(ALshort, 4, aluF2S) 3.861 +DECL_TEMPLATE(ALshort, 6, aluF2S) 3.862 +DECL_TEMPLATE(ALshort, 7, aluF2S) 3.863 +DECL_TEMPLATE(ALshort, 8, aluF2S) 3.864 + 3.865 +DECL_TEMPLATE(ALubyte, 1, aluF2UB) 3.866 +DECL_TEMPLATE(ALubyte, 4, aluF2UB) 3.867 +DECL_TEMPLATE(ALubyte, 6, aluF2UB) 3.868 +DECL_TEMPLATE(ALubyte, 7, aluF2UB) 3.869 +DECL_TEMPLATE(ALubyte, 8, aluF2UB) 3.870 + 3.871 +DECL_TEMPLATE(ALbyte, 1, aluF2B) 3.872 +DECL_TEMPLATE(ALbyte, 4, aluF2B) 3.873 +DECL_TEMPLATE(ALbyte, 6, aluF2B) 3.874 +DECL_TEMPLATE(ALbyte, 7, aluF2B) 3.875 +DECL_TEMPLATE(ALbyte, 8, aluF2B) 3.876 + 3.877 +#undef DECL_TEMPLATE 3.878 + 3.879 +#define DECL_TEMPLATE(T, N, func) \ 3.880 +static void Write_##T##_##N(ALCdevice *device, T *RESTRICT buffer, \ 3.881 + ALuint SamplesToDo) \ 3.882 +{ \ 3.883 + ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS] = device->DryBuffer; \ 3.884 + const enum Channel *ChanMap = device->DevChannels; \ 3.885 + ALuint i, j; \ 3.886 + \ 3.887 + if(device->Bs2b) \ 3.888 + { \ 3.889 + for(i = 0;i < SamplesToDo;i++) \ 3.890 + { \ 3.891 + float samples[2]; \ 3.892 + samples[0] = DryBuffer[i][ChanMap[0]]; \ 3.893 + samples[1] = DryBuffer[i][ChanMap[1]]; \ 3.894 + bs2b_cross_feed(device->Bs2b, samples); \ 3.895 + *(buffer++) = func(samples[0]); \ 3.896 + *(buffer++) = func(samples[1]); \ 3.897 + } \ 3.898 + } \ 3.899 + else \ 3.900 + { \ 3.901 + for(i = 0;i < SamplesToDo;i++) \ 3.902 + { \ 3.903 + for(j = 0;j < N;j++) \ 3.904 + *(buffer++) = func(DryBuffer[i][ChanMap[j]]); \ 3.905 + } \ 3.906 + } \ 3.907 +} 3.908 + 3.909 +DECL_TEMPLATE(ALfloat, 2, aluF2F) 3.910 +DECL_TEMPLATE(ALushort, 2, aluF2US) 3.911 +DECL_TEMPLATE(ALshort, 2, aluF2S) 3.912 +DECL_TEMPLATE(ALubyte, 2, aluF2UB) 3.913 +DECL_TEMPLATE(ALbyte, 2, aluF2B) 3.914 + 3.915 +#undef DECL_TEMPLATE 3.916 + 3.917 +#define DECL_TEMPLATE(T) \ 3.918 +static void Write_##T(ALCdevice *device, T *buffer, ALuint SamplesToDo) \ 3.919 +{ \ 3.920 + switch(device->FmtChans) \ 3.921 + { \ 3.922 + case DevFmtMono: \ 3.923 + Write_##T##_1(device, buffer, SamplesToDo); \ 3.924 + break; \ 3.925 + case DevFmtStereo: \ 3.926 + Write_##T##_2(device, buffer, SamplesToDo); \ 3.927 + break; \ 3.928 + case DevFmtQuad: \ 3.929 + Write_##T##_4(device, buffer, SamplesToDo); \ 3.930 + break; \ 3.931 + case DevFmtX51: \ 3.932 + case DevFmtX51Side: \ 3.933 + Write_##T##_6(device, buffer, SamplesToDo); \ 3.934 + break; \ 3.935 + case DevFmtX61: \ 3.936 + Write_##T##_7(device, buffer, SamplesToDo); \ 3.937 + break; \ 3.938 + case DevFmtX71: \ 3.939 + Write_##T##_8(device, buffer, SamplesToDo); \ 3.940 + break; \ 3.941 + } \ 3.942 +} 3.943 + 3.944 +DECL_TEMPLATE(ALfloat) 3.945 +DECL_TEMPLATE(ALushort) 3.946 +DECL_TEMPLATE(ALshort) 3.947 +DECL_TEMPLATE(ALubyte) 3.948 +DECL_TEMPLATE(ALbyte) 3.949 + 3.950 +#undef DECL_TEMPLATE 3.951 + 3.952 +ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) 3.953 +{ 3.954 + ALuint SamplesToDo; 3.955 + ALeffectslot *ALEffectSlot; 3.956 + ALCcontext **ctx, **ctx_end; 3.957 + ALsource **src, **src_end; 3.958 + int fpuState; 3.959 + ALuint i, c; 3.960 + ALsizei e; 3.961 + 3.962 +#if defined(HAVE_FESETROUND) 3.963 + fpuState = fegetround(); 3.964 + fesetround(FE_TOWARDZERO); 3.965 +#elif defined(HAVE__CONTROLFP) 3.966 + fpuState = _controlfp(0, 0); 3.967 + (void)_controlfp(_RC_CHOP, _MCW_RC); 3.968 +#else 3.969 + (void)fpuState; 3.970 +#endif 3.971 + 3.972 + while(size > 0) 3.973 + { 3.974 + /* Setup variables */ 3.975 + SamplesToDo = minu(size, BUFFERSIZE); 3.976 + 3.977 + /* Clear mixing buffer */ 3.978 + memset(device->DryBuffer, 0, SamplesToDo*MAXCHANNELS*sizeof(ALfloat)); 3.979 + 3.980 + LockDevice(device); 3.981 + ctx = device->Contexts; 3.982 + ctx_end = ctx + device->NumContexts; 3.983 + //printf("Contexts: %d\n", device->NumContexts); 3.984 + int context_number = 0; 3.985 + while(ctx != ctx_end) 3.986 + { 3.987 + //printf("Context %d:\n", context_number++); 3.988 + ALboolean DeferUpdates = (*ctx)->DeferUpdates; 3.989 + ALboolean UpdateSources = AL_FALSE; 3.990 + 3.991 + if(!DeferUpdates) 3.992 + { 3.993 + //printf("NOT deferring updates, whatever that means\n"); 3.994 + UpdateSources = (*ctx)->UpdateSources; 3.995 + //printf("update sources is set to %d\n", UpdateSources); 3.996 + (*ctx)->UpdateSources = AL_FALSE; 3.997 + } 3.998 + 3.999 + src = (*ctx)->ActiveSources; 3.1000 + src_end = src + (*ctx)->ActiveSourceCount; 3.1001 + //printf("number of active sources are %d\n", (*ctx)->ActiveSourceCount); 3.1002 + while(src != src_end) 3.1003 + { 3.1004 + 3.1005 + if((*src)->state != AL_PLAYING) 3.1006 + { 3.1007 + --((*ctx)->ActiveSourceCount); 3.1008 + *src = *(--src_end); 3.1009 + continue; 3.1010 + } 3.1011 + 3.1012 + if(!DeferUpdates && ((*src)->NeedsUpdate || UpdateSources)) 3.1013 + { 3.1014 + (*src)->NeedsUpdate = AL_FALSE; 3.1015 + ALsource_Update(*src, *ctx); 3.1016 + } 3.1017 + //printf("calling MixSource!\n"); 3.1018 + MixSource(*src, device, SamplesToDo); 3.1019 + src++; 3.1020 + } 3.1021 + 3.1022 + /* effect slot processing */ 3.1023 + for(e = 0;e < (*ctx)->EffectSlotMap.size;e++) 3.1024 + { 3.1025 + ALEffectSlot = (*ctx)->EffectSlotMap.array[e].value; 3.1026 + 3.1027 + for(i = 0;i < SamplesToDo;i++) 3.1028 + { 3.1029 + // RLM: remove click-removal 3.1030 + ALEffectSlot->WetBuffer[i] += ALEffectSlot->ClickRemoval[0]; 3.1031 + ALEffectSlot->ClickRemoval[0] -= ALEffectSlot->ClickRemoval[0] / 256.0f; 3.1032 + } 3.1033 + for(i = 0;i < 1;i++) 3.1034 + { 3.1035 + // RLM: remove click-removal 3.1036 + ALEffectSlot->ClickRemoval[i] += ALEffectSlot->PendingClicks[i]; 3.1037 + ALEffectSlot->PendingClicks[i] = 0.0f; 3.1038 + } 3.1039 + 3.1040 + if(!DeferUpdates && ALEffectSlot->NeedsUpdate) 3.1041 + { 3.1042 + ALEffectSlot->NeedsUpdate = AL_FALSE; 3.1043 + ALEffect_Update(ALEffectSlot->EffectState, *ctx, ALEffectSlot); 3.1044 + } 3.1045 + 3.1046 + ALEffect_Process(ALEffectSlot->EffectState, ALEffectSlot, 3.1047 + SamplesToDo, ALEffectSlot->WetBuffer, 3.1048 + device->DryBuffer); 3.1049 + 3.1050 + for(i = 0;i < SamplesToDo;i++) 3.1051 + ALEffectSlot->WetBuffer[i] = 0.0f; 3.1052 + } 3.1053 + 3.1054 + ctx++; 3.1055 + } 3.1056 + UnlockDevice(device); 3.1057 + 3.1058 + //Post processing loop 3.1059 + if(device->FmtChans == DevFmtMono) 3.1060 + { 3.1061 + for(i = 0;i < SamplesToDo;i++) 3.1062 + { 3.1063 + // RLM: remove click-removal 3.1064 + device->DryBuffer[i][FRONT_CENTER] += device->ClickRemoval[FRONT_CENTER]; 3.1065 + device->ClickRemoval[FRONT_CENTER] -= device->ClickRemoval[FRONT_CENTER] / 256.0f; 3.1066 + } 3.1067 + // RLM: remove click-removal 3.1068 + device->ClickRemoval[FRONT_CENTER] += device->PendingClicks[FRONT_CENTER]; 3.1069 + device->PendingClicks[FRONT_CENTER] = 0.0f; 3.1070 + } 3.1071 + else if(device->FmtChans == DevFmtStereo) 3.1072 + { 3.1073 + /* Assumes the first two channels are FRONT_LEFT and FRONT_RIGHT */ 3.1074 + for(i = 0;i < SamplesToDo;i++) 3.1075 + { 3.1076 + for(c = 0;c < 2;c++) 3.1077 + { 3.1078 + // RLM: remove click-removal 3.1079 + device->DryBuffer[i][c] += device->ClickRemoval[c]; 3.1080 + device->ClickRemoval[c] -= device->ClickRemoval[c] / 256.0f; 3.1081 + } 3.1082 + } 3.1083 + for(c = 0;c < 2;c++) 3.1084 + { 3.1085 + // RLM: remove click-removal 3.1086 + device->ClickRemoval[c] += device->PendingClicks[c]; 3.1087 + device->PendingClicks[c] = 0.0f; 3.1088 + } 3.1089 + } 3.1090 + else 3.1091 + { 3.1092 + for(i = 0;i < SamplesToDo;i++) 3.1093 + { 3.1094 + for(c = 0;c < MAXCHANNELS;c++) 3.1095 + { 3.1096 + // RLM: remove click-removal 3.1097 + device->DryBuffer[i][c] += device->ClickRemoval[c]; 3.1098 + device->ClickRemoval[c] -= device->ClickRemoval[c] / 256.0f; 3.1099 + } 3.1100 + } 3.1101 + for(c = 0;c < MAXCHANNELS;c++) 3.1102 + { 3.1103 + // RLM: remove click-removal 3.1104 + device->ClickRemoval[c] += device->PendingClicks[c]; 3.1105 + device->PendingClicks[c] = 0.0f; 3.1106 + } 3.1107 + } 3.1108 + 3.1109 + if(buffer) 3.1110 + { 3.1111 + switch(device->FmtType) 3.1112 + { 3.1113 + case DevFmtByte: 3.1114 + Write_ALbyte(device, buffer, SamplesToDo); 3.1115 + break; 3.1116 + case DevFmtUByte: 3.1117 + Write_ALubyte(device, buffer, SamplesToDo); 3.1118 + break; 3.1119 + case DevFmtShort: 3.1120 + Write_ALshort(device, buffer, SamplesToDo); 3.1121 + break; 3.1122 + case DevFmtUShort: 3.1123 + Write_ALushort(device, buffer, SamplesToDo); 3.1124 + break; 3.1125 + case DevFmtFloat: 3.1126 + Write_ALfloat(device, buffer, SamplesToDo); 3.1127 + break; 3.1128 + } 3.1129 + } 3.1130 + 3.1131 + size -= SamplesToDo; 3.1132 + } 3.1133 + 3.1134 +#if defined(HAVE_FESETROUND) 3.1135 + fesetround(fpuState); 3.1136 +#elif defined(HAVE__CONTROLFP) 3.1137 + _controlfp(fpuState, _MCW_RC); 3.1138 +#endif 3.1139 +} 3.1140 + 3.1141 + 3.1142 + 3.1143 + 3.1144 + 3.1145 +ALvoid aluHandleDisconnect(ALCdevice *device) 3.1146 +{ 3.1147 + ALuint i; 3.1148 + 3.1149 + LockDevice(device); 3.1150 + for(i = 0;i < device->NumContexts;i++) 3.1151 + { 3.1152 + ALCcontext *Context = device->Contexts[i]; 3.1153 + ALsource *source; 3.1154 + ALsizei pos; 3.1155 + 3.1156 + for(pos = 0;pos < Context->SourceMap.size;pos++) 3.1157 + { 3.1158 + source = Context->SourceMap.array[pos].value; 3.1159 + if(source->state == AL_PLAYING) 3.1160 + { 3.1161 + source->state = AL_STOPPED; 3.1162 + source->BuffersPlayed = source->BuffersInQueue; 3.1163 + source->position = 0; 3.1164 + source->position_fraction = 0; 3.1165 + } 3.1166 + } 3.1167 + } 3.1168 + 3.1169 + device->Connected = ALC_FALSE; 3.1170 + UnlockDevice(device); 3.1171 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/Alc/alcConfig.c Tue Oct 25 13:02:31 2011 -0700 4.3 @@ -0,0 +1,342 @@ 4.4 +/** 4.5 + * OpenAL cross platform audio library 4.6 + * Copyright (C) 1999-2007 by authors. 4.7 + * This library is free software; you can redistribute it and/or 4.8 + * modify it under the terms of the GNU Library General Public 4.9 + * License as published by the Free Software Foundation; either 4.10 + * version 2 of the License, or (at your option) any later version. 4.11 + * 4.12 + * This library is distributed in the hope that it will be useful, 4.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 4.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4.15 + * Library General Public License for more details. 4.16 + * 4.17 + * You should have received a copy of the GNU Library General Public 4.18 + * License along with this library; if not, write to the 4.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 4.20 + * Boston, MA 02111-1307, USA. 4.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 4.22 + */ 4.23 + 4.24 +#ifdef _WIN32 4.25 +#ifdef __MINGW64__ 4.26 +#define _WIN32_IE 0x501 4.27 +#else 4.28 +#define _WIN32_IE 0x400 4.29 +#endif 4.30 +#endif 4.31 + 4.32 +#include "config.h" 4.33 + 4.34 +#include <stdlib.h> 4.35 +#include <stdio.h> 4.36 +#include <ctype.h> 4.37 +#include <string.h> 4.38 + 4.39 +#include "alMain.h" 4.40 + 4.41 +#ifdef _WIN32_IE 4.42 +#include <shlobj.h> 4.43 +#endif 4.44 + 4.45 +typedef struct ConfigEntry { 4.46 + char *key; 4.47 + char *value; 4.48 +} ConfigEntry; 4.49 + 4.50 +typedef struct ConfigBlock { 4.51 + char *name; 4.52 + ConfigEntry *entries; 4.53 + size_t entryCount; 4.54 +} ConfigBlock; 4.55 + 4.56 +static ConfigBlock *cfgBlocks; 4.57 +static size_t cfgCount; 4.58 + 4.59 +static char buffer[1024]; 4.60 + 4.61 +static void LoadConfigFromFile(FILE *f) 4.62 +{ 4.63 + ConfigBlock *curBlock = cfgBlocks; 4.64 + ConfigEntry *ent; 4.65 + 4.66 + while(fgets(buffer, sizeof(buffer), f)) 4.67 + { 4.68 + size_t i = 0; 4.69 + 4.70 + while(isspace(buffer[i])) 4.71 + i++; 4.72 + if(!buffer[i] || buffer[i] == '#') 4.73 + continue; 4.74 + 4.75 + memmove(buffer, buffer+i, strlen(buffer+i)+1); 4.76 + 4.77 + if(buffer[0] == '[') 4.78 + { 4.79 + ConfigBlock *nextBlock; 4.80 + 4.81 + i = 1; 4.82 + while(buffer[i] && buffer[i] != ']') 4.83 + i++; 4.84 + 4.85 + if(!buffer[i]) 4.86 + { 4.87 + ERR("config parse error: bad line \"%s\"\n", buffer); 4.88 + continue; 4.89 + } 4.90 + buffer[i] = 0; 4.91 + 4.92 + do { 4.93 + i++; 4.94 + if(buffer[i] && !isspace(buffer[i])) 4.95 + { 4.96 + if(buffer[i] != '#') 4.97 + WARN("config warning: extra data after block: \"%s\"\n", buffer+i); 4.98 + break; 4.99 + } 4.100 + } while(buffer[i]); 4.101 + 4.102 + nextBlock = NULL; 4.103 + for(i = 0;i < cfgCount;i++) 4.104 + { 4.105 + if(strcasecmp(cfgBlocks[i].name, buffer+1) == 0) 4.106 + { 4.107 + nextBlock = cfgBlocks+i; 4.108 + TRACE("found block '%s'\n", nextBlock->name); 4.109 + break; 4.110 + } 4.111 + } 4.112 + 4.113 + if(!nextBlock) 4.114 + { 4.115 + nextBlock = realloc(cfgBlocks, (cfgCount+1)*sizeof(ConfigBlock)); 4.116 + if(!nextBlock) 4.117 + { 4.118 + ERR("config parse error: error reallocating config blocks\n"); 4.119 + continue; 4.120 + } 4.121 + cfgBlocks = nextBlock; 4.122 + nextBlock = cfgBlocks+cfgCount; 4.123 + cfgCount++; 4.124 + 4.125 + nextBlock->name = strdup(buffer+1); 4.126 + nextBlock->entries = NULL; 4.127 + nextBlock->entryCount = 0; 4.128 + 4.129 + TRACE("found new block '%s'\n", nextBlock->name); 4.130 + } 4.131 + curBlock = nextBlock; 4.132 + continue; 4.133 + } 4.134 + 4.135 + /* Look for the option name */ 4.136 + i = 0; 4.137 + while(buffer[i] && buffer[i] != '#' && buffer[i] != '=' && 4.138 + !isspace(buffer[i])) 4.139 + i++; 4.140 + 4.141 + if(!buffer[i] || buffer[i] == '#' || i == 0) 4.142 + { 4.143 + ERR("config parse error: malformed option line: \"%s\"\n", buffer); 4.144 + continue; 4.145 + } 4.146 + 4.147 + /* Seperate the option */ 4.148 + if(buffer[i] != '=') 4.149 + { 4.150 + buffer[i++] = 0; 4.151 + 4.152 + while(isspace(buffer[i])) 4.153 + i++; 4.154 + if(buffer[i] != '=') 4.155 + { 4.156 + ERR("config parse error: option without a value: \"%s\"\n", buffer); 4.157 + continue; 4.158 + } 4.159 + } 4.160 + /* Find the start of the value */ 4.161 + buffer[i++] = 0; 4.162 + while(isspace(buffer[i])) 4.163 + i++; 4.164 + 4.165 + /* Check if we already have this option set */ 4.166 + ent = curBlock->entries; 4.167 + while((size_t)(ent-curBlock->entries) < curBlock->entryCount) 4.168 + { 4.169 + if(strcasecmp(ent->key, buffer) == 0) 4.170 + break; 4.171 + ent++; 4.172 + } 4.173 + 4.174 + if((size_t)(ent-curBlock->entries) >= curBlock->entryCount) 4.175 + { 4.176 + /* Allocate a new option entry */ 4.177 + ent = realloc(curBlock->entries, (curBlock->entryCount+1)*sizeof(ConfigEntry)); 4.178 + if(!ent) 4.179 + { 4.180 + ERR("config parse error: error reallocating config entries\n"); 4.181 + continue; 4.182 + } 4.183 + curBlock->entries = ent; 4.184 + ent = curBlock->entries + curBlock->entryCount; 4.185 + curBlock->entryCount++; 4.186 + 4.187 + ent->key = strdup(buffer); 4.188 + ent->value = NULL; 4.189 + } 4.190 + 4.191 + /* Look for the end of the line (Null term, new-line, or #-symbol) and 4.192 + eat up the trailing whitespace */ 4.193 + memmove(buffer, buffer+i, strlen(buffer+i)+1); 4.194 + 4.195 + i = 0; 4.196 + while(buffer[i] && buffer[i] != '#' && buffer[i] != '\n') 4.197 + i++; 4.198 + do { 4.199 + i--; 4.200 + } while(isspace(buffer[i])); 4.201 + buffer[++i] = 0; 4.202 + 4.203 + free(ent->value); 4.204 + ent->value = strdup(buffer); 4.205 + 4.206 + TRACE("found '%s' = '%s'\n", ent->key, ent->value); 4.207 + } 4.208 +} 4.209 + 4.210 +void ReadALConfig(void) 4.211 +{ 4.212 + const char *str; 4.213 + FILE *f; 4.214 + 4.215 + cfgBlocks = calloc(1, sizeof(ConfigBlock)); 4.216 + cfgBlocks->name = strdup("general"); 4.217 + cfgCount = 1; 4.218 + 4.219 +#ifdef _WIN32 4.220 + if(SHGetSpecialFolderPathA(NULL, buffer, CSIDL_APPDATA, FALSE) != FALSE) 4.221 + { 4.222 + size_t p = strlen(buffer); 4.223 + snprintf(buffer+p, sizeof(buffer)-p, "\\alsoft.ini"); 4.224 + f = fopen(buffer, "rt"); 4.225 + if(f) 4.226 + { 4.227 + LoadConfigFromFile(f); 4.228 + fclose(f); 4.229 + } 4.230 + } 4.231 +#else 4.232 + f = fopen("/etc/openal/alsoft.conf", "r"); 4.233 + if(f) 4.234 + { 4.235 + LoadConfigFromFile(f); 4.236 + fclose(f); 4.237 + } 4.238 + if((str=getenv("HOME")) != NULL && *str) 4.239 + { 4.240 + snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", str); 4.241 + f = fopen(buffer, "r"); 4.242 + if(f) 4.243 + { 4.244 + LoadConfigFromFile(f); 4.245 + fclose(f); 4.246 + } 4.247 + } 4.248 +#endif 4.249 + if((str=getenv("ALSOFT_CONF")) != NULL && *str) 4.250 + { 4.251 + f = fopen(str, "r"); 4.252 + if(f) 4.253 + { 4.254 + LoadConfigFromFile(f); 4.255 + fclose(f); 4.256 + } 4.257 + } 4.258 +} 4.259 + 4.260 +void FreeALConfig(void) 4.261 +{ 4.262 + size_t i; 4.263 + 4.264 + for(i = 0;i < cfgCount;i++) 4.265 + { 4.266 + size_t j; 4.267 + for(j = 0;j < cfgBlocks[i].entryCount;j++) 4.268 + { 4.269 + free(cfgBlocks[i].entries[j].key); 4.270 + free(cfgBlocks[i].entries[j].value); 4.271 + } 4.272 + free(cfgBlocks[i].entries); 4.273 + free(cfgBlocks[i].name); 4.274 + } 4.275 + free(cfgBlocks); 4.276 + cfgBlocks = NULL; 4.277 + cfgCount = 0; 4.278 +} 4.279 + 4.280 +const char *GetConfigValue(const char *blockName, const char *keyName, const char *def) 4.281 +{ 4.282 + size_t i, j; 4.283 + 4.284 + if(!keyName) 4.285 + return def; 4.286 + 4.287 + if(!blockName) 4.288 + blockName = "general"; 4.289 + 4.290 + for(i = 0;i < cfgCount;i++) 4.291 + { 4.292 + if(strcasecmp(cfgBlocks[i].name, blockName) != 0) 4.293 + continue; 4.294 + 4.295 + for(j = 0;j < cfgBlocks[i].entryCount;j++) 4.296 + { 4.297 + if(strcasecmp(cfgBlocks[i].entries[j].key, keyName) == 0) 4.298 + { 4.299 + TRACE("Found %s:%s = \"%s\"\n", blockName, keyName, 4.300 + cfgBlocks[i].entries[j].value); 4.301 + if(cfgBlocks[i].entries[j].value[0]) 4.302 + return cfgBlocks[i].entries[j].value; 4.303 + return def; 4.304 + } 4.305 + } 4.306 + } 4.307 + 4.308 + TRACE("Key %s:%s not found\n", blockName, keyName); 4.309 + return def; 4.310 +} 4.311 + 4.312 +int ConfigValueExists(const char *blockName, const char *keyName) 4.313 +{ 4.314 + const char *val = GetConfigValue(blockName, keyName, ""); 4.315 + return !!val[0]; 4.316 +} 4.317 + 4.318 +int GetConfigValueInt(const char *blockName, const char *keyName, int def) 4.319 +{ 4.320 + const char *val = GetConfigValue(blockName, keyName, ""); 4.321 + 4.322 + if(!val[0]) return def; 4.323 + return strtol(val, NULL, 0); 4.324 +} 4.325 + 4.326 +float GetConfigValueFloat(const char *blockName, const char *keyName, float def) 4.327 +{ 4.328 + const char *val = GetConfigValue(blockName, keyName, ""); 4.329 + 4.330 + if(!val[0]) return def; 4.331 +#ifdef HAVE_STRTOF 4.332 + return strtof(val, NULL); 4.333 +#else 4.334 + return (float)strtod(val, NULL); 4.335 +#endif 4.336 +} 4.337 + 4.338 +int GetConfigValueBool(const char *blockName, const char *keyName, int def) 4.339 +{ 4.340 + const char *val = GetConfigValue(blockName, keyName, ""); 4.341 + 4.342 + if(!val[0]) return !!def; 4.343 + return (strcasecmp(val, "true") == 0 || strcasecmp(val, "yes") == 0 || 4.344 + strcasecmp(val, "on") == 0 || atoi(val) != 0); 4.345 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/Alc/alcDedicated.c Tue Oct 25 13:02:31 2011 -0700 5.3 @@ -0,0 +1,138 @@ 5.4 +/** 5.5 + * OpenAL cross platform audio library 5.6 + * Copyright (C) 2011 by Chris Robinson. 5.7 + * This library is free software; you can redistribute it and/or 5.8 + * modify it under the terms of the GNU Library General Public 5.9 + * License as published by the Free Software Foundation; either 5.10 + * version 2 of the License, or (at your option) any later version. 5.11 + * 5.12 + * This library is distributed in the hope that it will be useful, 5.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 5.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 5.15 + * Library General Public License for more details. 5.16 + * 5.17 + * You should have received a copy of the GNU Library General Public 5.18 + * License along with this library; if not, write to the 5.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 5.20 + * Boston, MA 02111-1307, USA. 5.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 5.22 + */ 5.23 + 5.24 +#include "config.h" 5.25 + 5.26 +#include <stdlib.h> 5.27 + 5.28 +#include "alMain.h" 5.29 +#include "alFilter.h" 5.30 +#include "alAuxEffectSlot.h" 5.31 +#include "alError.h" 5.32 +#include "alu.h" 5.33 + 5.34 + 5.35 +typedef struct ALdedicatedState { 5.36 + // Must be first in all effects! 5.37 + ALeffectState state; 5.38 + 5.39 + ALfloat gains[MAXCHANNELS]; 5.40 +} ALdedicatedState; 5.41 + 5.42 + 5.43 +static ALvoid DedicatedDestroy(ALeffectState *effect) 5.44 +{ 5.45 + ALdedicatedState *state = (ALdedicatedState*)effect; 5.46 + free(state); 5.47 +} 5.48 + 5.49 +static ALboolean DedicatedDeviceUpdate(ALeffectState *effect, ALCdevice *Device) 5.50 +{ 5.51 + (void)effect; 5.52 + (void)Device; 5.53 + return AL_TRUE; 5.54 +} 5.55 + 5.56 +static ALvoid DedicatedDLGUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) 5.57 +{ 5.58 + ALdedicatedState *state = (ALdedicatedState*)effect; 5.59 + ALCdevice *device = Context->Device; 5.60 + const ALfloat *SpeakerGain; 5.61 + ALfloat Gain; 5.62 + ALint pos; 5.63 + ALsizei s; 5.64 + 5.65 + pos = aluCart2LUTpos(1.0f, 0.0f); 5.66 + SpeakerGain = device->PanningLUT[pos]; 5.67 + 5.68 + Gain = Slot->Gain * Slot->effect.Params.Dedicated.Gain; 5.69 + for(s = 0;s < MAXCHANNELS;s++) 5.70 + state->gains[s] = SpeakerGain[s] * Gain; 5.71 +} 5.72 + 5.73 +static ALvoid DedicatedLFEUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) 5.74 +{ 5.75 + ALdedicatedState *state = (ALdedicatedState*)effect; 5.76 + ALfloat Gain; 5.77 + ALsizei s; 5.78 + (void)Context; 5.79 + 5.80 + Gain = Slot->Gain * Slot->effect.Params.Dedicated.Gain; 5.81 + for(s = 0;s < MAXCHANNELS;s++) 5.82 + state->gains[s] = 0.0f; 5.83 + state->gains[LFE] = Gain; 5.84 +} 5.85 + 5.86 +static ALvoid DedicatedProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 5.87 +{ 5.88 + ALdedicatedState *state = (ALdedicatedState*)effect; 5.89 + const ALfloat *gains = state->gains; 5.90 + ALuint i, s; 5.91 + (void)Slot; 5.92 + 5.93 + for(i = 0;i < SamplesToDo;i++) 5.94 + { 5.95 + ALfloat sample; 5.96 + 5.97 + sample = SamplesIn[i]; 5.98 + for(s = 0;s < MAXCHANNELS;s++) 5.99 + SamplesOut[i][s] = sample * gains[s]; 5.100 + } 5.101 +} 5.102 + 5.103 +ALeffectState *DedicatedDLGCreate(void) 5.104 +{ 5.105 + ALdedicatedState *state; 5.106 + ALsizei s; 5.107 + 5.108 + state = malloc(sizeof(*state)); 5.109 + if(!state) 5.110 + return NULL; 5.111 + 5.112 + state->state.Destroy = DedicatedDestroy; 5.113 + state->state.DeviceUpdate = DedicatedDeviceUpdate; 5.114 + state->state.Update = DedicatedDLGUpdate; 5.115 + state->state.Process = DedicatedProcess; 5.116 + 5.117 + for(s = 0;s < MAXCHANNELS;s++) 5.118 + state->gains[s] = 0.0f; 5.119 + 5.120 + return &state->state; 5.121 +} 5.122 + 5.123 +ALeffectState *DedicatedLFECreate(void) 5.124 +{ 5.125 + ALdedicatedState *state; 5.126 + ALsizei s; 5.127 + 5.128 + state = malloc(sizeof(*state)); 5.129 + if(!state) 5.130 + return NULL; 5.131 + 5.132 + state->state.Destroy = DedicatedDestroy; 5.133 + state->state.DeviceUpdate = DedicatedDeviceUpdate; 5.134 + state->state.Update = DedicatedLFEUpdate; 5.135 + state->state.Process = DedicatedProcess; 5.136 + 5.137 + for(s = 0;s < MAXCHANNELS;s++) 5.138 + state->gains[s] = 0.0f; 5.139 + 5.140 + return &state->state; 5.141 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/Alc/alcEcho.c Tue Oct 25 13:02:31 2011 -0700 6.3 @@ -0,0 +1,192 @@ 6.4 +/** 6.5 + * OpenAL cross platform audio library 6.6 + * Copyright (C) 2009 by Chris Robinson. 6.7 + * This library is free software; you can redistribute it and/or 6.8 + * modify it under the terms of the GNU Library General Public 6.9 + * License as published by the Free Software Foundation; either 6.10 + * version 2 of the License, or (at your option) any later version. 6.11 + * 6.12 + * This library is distributed in the hope that it will be useful, 6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 6.15 + * Library General Public License for more details. 6.16 + * 6.17 + * You should have received a copy of the GNU Library General Public 6.18 + * License along with this library; if not, write to the 6.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 6.20 + * Boston, MA 02111-1307, USA. 6.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 6.22 + */ 6.23 + 6.24 +#include "config.h" 6.25 + 6.26 +#include <math.h> 6.27 +#include <stdlib.h> 6.28 + 6.29 +#include "alMain.h" 6.30 +#include "alFilter.h" 6.31 +#include "alAuxEffectSlot.h" 6.32 +#include "alError.h" 6.33 +#include "alu.h" 6.34 + 6.35 + 6.36 +typedef struct ALechoState { 6.37 + // Must be first in all effects! 6.38 + ALeffectState state; 6.39 + 6.40 + ALfloat *SampleBuffer; 6.41 + ALuint BufferLength; 6.42 + 6.43 + // The echo is two tap. The delay is the number of samples from before the 6.44 + // current offset 6.45 + struct { 6.46 + ALuint delay; 6.47 + } Tap[2]; 6.48 + ALuint Offset; 6.49 + // The LR gains for the first tap. The second tap uses the reverse 6.50 + ALfloat GainL; 6.51 + ALfloat GainR; 6.52 + 6.53 + ALfloat FeedGain; 6.54 + 6.55 + ALfloat Gain[MAXCHANNELS]; 6.56 + 6.57 + FILTER iirFilter; 6.58 + ALfloat history[2]; 6.59 +} ALechoState; 6.60 + 6.61 +static ALvoid EchoDestroy(ALeffectState *effect) 6.62 +{ 6.63 + ALechoState *state = (ALechoState*)effect; 6.64 + if(state) 6.65 + { 6.66 + free(state->SampleBuffer); 6.67 + state->SampleBuffer = NULL; 6.68 + free(state); 6.69 + } 6.70 +} 6.71 + 6.72 +static ALboolean EchoDeviceUpdate(ALeffectState *effect, ALCdevice *Device) 6.73 +{ 6.74 + ALechoState *state = (ALechoState*)effect; 6.75 + ALuint maxlen, i; 6.76 + 6.77 + // Use the next power of 2 for the buffer length, so the tap offsets can be 6.78 + // wrapped using a mask instead of a modulo 6.79 + maxlen = (ALuint)(AL_ECHO_MAX_DELAY * Device->Frequency) + 1; 6.80 + maxlen += (ALuint)(AL_ECHO_MAX_LRDELAY * Device->Frequency) + 1; 6.81 + maxlen = NextPowerOf2(maxlen); 6.82 + 6.83 + if(maxlen != state->BufferLength) 6.84 + { 6.85 + void *temp; 6.86 + 6.87 + temp = realloc(state->SampleBuffer, maxlen * sizeof(ALfloat)); 6.88 + if(!temp) 6.89 + return AL_FALSE; 6.90 + state->SampleBuffer = temp; 6.91 + state->BufferLength = maxlen; 6.92 + } 6.93 + for(i = 0;i < state->BufferLength;i++) 6.94 + state->SampleBuffer[i] = 0.0f; 6.95 + 6.96 + return AL_TRUE; 6.97 +} 6.98 + 6.99 +static ALvoid EchoUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) 6.100 +{ 6.101 + ALechoState *state = (ALechoState*)effect; 6.102 + ALCdevice *Device = Context->Device; 6.103 + ALuint frequency = Device->Frequency; 6.104 + ALfloat lrpan, cw, g, gain; 6.105 + ALuint i; 6.106 + 6.107 + state->Tap[0].delay = (ALuint)(Slot->effect.Params.Echo.Delay * frequency) + 1; 6.108 + state->Tap[1].delay = (ALuint)(Slot->effect.Params.Echo.LRDelay * frequency); 6.109 + state->Tap[1].delay += state->Tap[0].delay; 6.110 + 6.111 + lrpan = Slot->effect.Params.Echo.Spread*0.5f + 0.5f; 6.112 + state->GainL = aluSqrt( lrpan); 6.113 + state->GainR = aluSqrt(1.0f-lrpan); 6.114 + 6.115 + state->FeedGain = Slot->effect.Params.Echo.Feedback; 6.116 + 6.117 + cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / frequency); 6.118 + g = 1.0f - Slot->effect.Params.Echo.Damping; 6.119 + state->iirFilter.coeff = lpCoeffCalc(g, cw); 6.120 + 6.121 + gain = Slot->Gain; 6.122 + for(i = 0;i < MAXCHANNELS;i++) 6.123 + state->Gain[i] = 0.0f; 6.124 + for(i = 0;i < Device->NumChan;i++) 6.125 + { 6.126 + enum Channel chan = Device->Speaker2Chan[i]; 6.127 + state->Gain[chan] = gain; 6.128 + } 6.129 +} 6.130 + 6.131 +static ALvoid EchoProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 6.132 +{ 6.133 + ALechoState *state = (ALechoState*)effect; 6.134 + const ALuint mask = state->BufferLength-1; 6.135 + const ALuint tap1 = state->Tap[0].delay; 6.136 + const ALuint tap2 = state->Tap[1].delay; 6.137 + ALuint offset = state->Offset; 6.138 + ALfloat samp[2], smp; 6.139 + ALuint i; 6.140 + (void)Slot; 6.141 + 6.142 + for(i = 0;i < SamplesToDo;i++,offset++) 6.143 + { 6.144 + // Sample first tap 6.145 + smp = state->SampleBuffer[(offset-tap1) & mask]; 6.146 + samp[0] = smp * state->GainL; 6.147 + samp[1] = smp * state->GainR; 6.148 + // Sample second tap. Reverse LR panning 6.149 + smp = state->SampleBuffer[(offset-tap2) & mask]; 6.150 + samp[0] += smp * state->GainR; 6.151 + samp[1] += smp * state->GainL; 6.152 + 6.153 + // Apply damping and feedback gain to the second tap, and mix in the 6.154 + // new sample 6.155 + smp = lpFilter2P(&state->iirFilter, 0, smp+SamplesIn[i]); 6.156 + state->SampleBuffer[offset&mask] = smp * state->FeedGain; 6.157 + 6.158 + SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp[0]; 6.159 + SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp[1]; 6.160 + SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp[0]; 6.161 + SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp[1]; 6.162 + SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp[0]; 6.163 + SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp[1]; 6.164 + } 6.165 + state->Offset = offset; 6.166 +} 6.167 + 6.168 +ALeffectState *EchoCreate(void) 6.169 +{ 6.170 + ALechoState *state; 6.171 + 6.172 + state = malloc(sizeof(*state)); 6.173 + if(!state) 6.174 + return NULL; 6.175 + 6.176 + state->state.Destroy = EchoDestroy; 6.177 + state->state.DeviceUpdate = EchoDeviceUpdate; 6.178 + state->state.Update = EchoUpdate; 6.179 + state->state.Process = EchoProcess; 6.180 + 6.181 + state->BufferLength = 0; 6.182 + state->SampleBuffer = NULL; 6.183 + 6.184 + state->Tap[0].delay = 0; 6.185 + state->Tap[1].delay = 0; 6.186 + state->Offset = 0; 6.187 + state->GainL = 0.0f; 6.188 + state->GainR = 0.0f; 6.189 + 6.190 + state->iirFilter.coeff = 0.0f; 6.191 + state->iirFilter.history[0] = 0.0f; 6.192 + state->iirFilter.history[1] = 0.0f; 6.193 + 6.194 + return &state->state; 6.195 +}
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 7.2 +++ b/Alc/alcModulator.c Tue Oct 25 13:02:31 2011 -0700 7.3 @@ -0,0 +1,210 @@ 7.4 +/** 7.5 + * OpenAL cross platform audio library 7.6 + * Copyright (C) 2009 by Chris Robinson. 7.7 + * This library is free software; you can redistribute it and/or 7.8 + * modify it under the terms of the GNU Library General Public 7.9 + * License as published by the Free Software Foundation; either 7.10 + * version 2 of the License, or (at your option) any later version. 7.11 + * 7.12 + * This library is distributed in the hope that it will be useful, 7.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 7.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 7.15 + * Library General Public License for more details. 7.16 + * 7.17 + * You should have received a copy of the GNU Library General Public 7.18 + * License along with this library; if not, write to the 7.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 7.20 + * Boston, MA 02111-1307, USA. 7.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 7.22 + */ 7.23 + 7.24 +#include "config.h" 7.25 + 7.26 +#include <math.h> 7.27 +#include <stdlib.h> 7.28 + 7.29 +#include "alMain.h" 7.30 +#include "alFilter.h" 7.31 +#include "alAuxEffectSlot.h" 7.32 +#include "alError.h" 7.33 +#include "alu.h" 7.34 + 7.35 + 7.36 +typedef struct ALmodulatorState { 7.37 + // Must be first in all effects! 7.38 + ALeffectState state; 7.39 + 7.40 + enum { 7.41 + SINUSOID, 7.42 + SAWTOOTH, 7.43 + SQUARE 7.44 + } Waveform; 7.45 + 7.46 + ALuint index; 7.47 + ALuint step; 7.48 + 7.49 + ALfloat Gain[MAXCHANNELS]; 7.50 + 7.51 + FILTER iirFilter; 7.52 + ALfloat history[1]; 7.53 +} ALmodulatorState; 7.54 + 7.55 +#define WAVEFORM_FRACBITS 16 7.56 +#define WAVEFORM_FRACMASK ((1<<WAVEFORM_FRACBITS)-1) 7.57 + 7.58 +static __inline ALdouble Sin(ALuint index) 7.59 +{ 7.60 + return sin(index * (M_PI*2.0 / (1<<WAVEFORM_FRACBITS))); 7.61 +} 7.62 + 7.63 +static __inline ALdouble Saw(ALuint index) 7.64 +{ 7.65 + return index*(2.0/(1<<WAVEFORM_FRACBITS)) - 1.0; 7.66 +} 7.67 + 7.68 +static __inline ALdouble Square(ALuint index) 7.69 +{ 7.70 + return (index&(1<<(WAVEFORM_FRACBITS-1))) ? -1.0 : 1.0; 7.71 +} 7.72 + 7.73 + 7.74 +static __inline ALfloat hpFilter1P(FILTER *iir, ALuint offset, ALfloat input) 7.75 +{ 7.76 + ALfloat *history = &iir->history[offset]; 7.77 + ALfloat a = iir->coeff; 7.78 + ALfloat output = input; 7.79 + 7.80 + output = output + (history[0]-output)*a; 7.81 + history[0] = output; 7.82 + 7.83 + return input - output; 7.84 +} 7.85 + 7.86 + 7.87 +#define DECL_TEMPLATE(func) \ 7.88 +static void Process##func(ALmodulatorState *state, ALuint SamplesToDo, \ 7.89 + const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) \ 7.90 +{ \ 7.91 + const ALuint step = state->step; \ 7.92 + ALuint index = state->index; \ 7.93 + ALfloat samp; \ 7.94 + ALuint i; \ 7.95 + \ 7.96 + for(i = 0;i < SamplesToDo;i++) \ 7.97 + { \ 7.98 + samp = SamplesIn[i]; \ 7.99 + \ 7.100 + index += step; \ 7.101 + index &= WAVEFORM_FRACMASK; \ 7.102 + samp *= func(index); \ 7.103 + \ 7.104 + samp = hpFilter1P(&state->iirFilter, 0, samp); \ 7.105 + \ 7.106 + SamplesOut[i][FRONT_LEFT] += state->Gain[FRONT_LEFT] * samp; \ 7.107 + SamplesOut[i][FRONT_RIGHT] += state->Gain[FRONT_RIGHT] * samp; \ 7.108 + SamplesOut[i][FRONT_CENTER] += state->Gain[FRONT_CENTER] * samp; \ 7.109 + SamplesOut[i][SIDE_LEFT] += state->Gain[SIDE_LEFT] * samp; \ 7.110 + SamplesOut[i][SIDE_RIGHT] += state->Gain[SIDE_RIGHT] * samp; \ 7.111 + SamplesOut[i][BACK_LEFT] += state->Gain[BACK_LEFT] * samp; \ 7.112 + SamplesOut[i][BACK_RIGHT] += state->Gain[BACK_RIGHT] * samp; \ 7.113 + SamplesOut[i][BACK_CENTER] += state->Gain[BACK_CENTER] * samp; \ 7.114 + } \ 7.115 + state->index = index; \ 7.116 +} 7.117 + 7.118 +DECL_TEMPLATE(Sin) 7.119 +DECL_TEMPLATE(Saw) 7.120 +DECL_TEMPLATE(Square) 7.121 + 7.122 +#undef DECL_TEMPLATE 7.123 + 7.124 + 7.125 +static ALvoid ModulatorDestroy(ALeffectState *effect) 7.126 +{ 7.127 + ALmodulatorState *state = (ALmodulatorState*)effect; 7.128 + free(state); 7.129 +} 7.130 + 7.131 +static ALboolean ModulatorDeviceUpdate(ALeffectState *effect, ALCdevice *Device) 7.132 +{ 7.133 + return AL_TRUE; 7.134 + (void)effect; 7.135 + (void)Device; 7.136 +} 7.137 + 7.138 +static ALvoid ModulatorUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) 7.139 +{ 7.140 + ALmodulatorState *state = (ALmodulatorState*)effect; 7.141 + ALCdevice *Device = Context->Device; 7.142 + ALfloat gain, cw, a = 0.0f; 7.143 + ALuint index; 7.144 + 7.145 + if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SINUSOID) 7.146 + state->Waveform = SINUSOID; 7.147 + else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SAWTOOTH) 7.148 + state->Waveform = SAWTOOTH; 7.149 + else if(Slot->effect.Params.Modulator.Waveform == AL_RING_MODULATOR_SQUARE) 7.150 + state->Waveform = SQUARE; 7.151 + 7.152 + state->step = Slot->effect.Params.Modulator.Frequency*(1<<WAVEFORM_FRACBITS) / 7.153 + Device->Frequency; 7.154 + if(!state->step) 7.155 + state->step = 1; 7.156 + 7.157 + cw = cos(2.0*M_PI * Slot->effect.Params.Modulator.HighPassCutoff / 7.158 + Device->Frequency); 7.159 + a = (2.0f-cw) - aluSqrt(aluPow(2.0f-cw, 2.0f) - 1.0f); 7.160 + state->iirFilter.coeff = a; 7.161 + 7.162 + gain = Slot->Gain; 7.163 + for(index = 0;index < MAXCHANNELS;index++) 7.164 + state->Gain[index] = 0.0f; 7.165 + for(index = 0;index < Device->NumChan;index++) 7.166 + { 7.167 + enum Channel chan = Device->Speaker2Chan[index]; 7.168 + state->Gain[chan] = gain; 7.169 + } 7.170 +} 7.171 + 7.172 +static ALvoid ModulatorProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 7.173 +{ 7.174 + ALmodulatorState *state = (ALmodulatorState*)effect; 7.175 + (void)Slot; 7.176 + 7.177 + switch(state->Waveform) 7.178 + { 7.179 + case SINUSOID: 7.180 + ProcessSin(state, SamplesToDo, SamplesIn, SamplesOut); 7.181 + break; 7.182 + 7.183 + case SAWTOOTH: 7.184 + ProcessSaw(state, SamplesToDo, SamplesIn, SamplesOut); 7.185 + break; 7.186 + 7.187 + case SQUARE: 7.188 + ProcessSquare(state, SamplesToDo, SamplesIn, SamplesOut); 7.189 + break; 7.190 + } 7.191 +} 7.192 + 7.193 +ALeffectState *ModulatorCreate(void) 7.194 +{ 7.195 + ALmodulatorState *state; 7.196 + 7.197 + state = malloc(sizeof(*state)); 7.198 + if(!state) 7.199 + return NULL; 7.200 + 7.201 + state->state.Destroy = ModulatorDestroy; 7.202 + state->state.DeviceUpdate = ModulatorDeviceUpdate; 7.203 + state->state.Update = ModulatorUpdate; 7.204 + state->state.Process = ModulatorProcess; 7.205 + 7.206 + state->index = 0.0f; 7.207 + state->step = 1.0f; 7.208 + 7.209 + state->iirFilter.coeff = 0.0f; 7.210 + state->iirFilter.history[0] = 0.0f; 7.211 + 7.212 + return &state->state; 7.213 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 8.2 +++ b/Alc/alcReverb.c Tue Oct 25 13:02:31 2011 -0700 8.3 @@ -0,0 +1,1374 @@ 8.4 +/** 8.5 + * Reverb for the OpenAL cross platform audio library 8.6 + * Copyright (C) 2008-2009 by Christopher Fitzgerald. 8.7 + * This library is free software; you can redistribute it and/or 8.8 + * modify it under the terms of the GNU Library General Public 8.9 + * License as published by the Free Software Foundation; either 8.10 + * version 2 of the License, or (at your option) any later version. 8.11 + * 8.12 + * This library is distributed in the hope that it will be useful, 8.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 8.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 8.15 + * Library General Public License for more details. 8.16 + * 8.17 + * You should have received a copy of the GNU Library General Public 8.18 + * License along with this library; if not, write to the 8.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 8.20 + * Boston, MA 02111-1307, USA. 8.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 8.22 + */ 8.23 + 8.24 +#include "config.h" 8.25 + 8.26 +#include <stdio.h> 8.27 +#include <stdlib.h> 8.28 +#include <math.h> 8.29 + 8.30 +#include "AL/al.h" 8.31 +#include "AL/alc.h" 8.32 +#include "alMain.h" 8.33 +#include "alAuxEffectSlot.h" 8.34 +#include "alEffect.h" 8.35 +#include "alError.h" 8.36 +#include "alu.h" 8.37 + 8.38 +typedef struct DelayLine 8.39 +{ 8.40 + // The delay lines use sample lengths that are powers of 2 to allow the 8.41 + // use of bit-masking instead of a modulus for wrapping. 8.42 + ALuint Mask; 8.43 + ALfloat *Line; 8.44 +} DelayLine; 8.45 + 8.46 +typedef struct ALverbState { 8.47 + // Must be first in all effects! 8.48 + ALeffectState state; 8.49 + 8.50 + // All delay lines are allocated as a single buffer to reduce memory 8.51 + // fragmentation and management code. 8.52 + ALfloat *SampleBuffer; 8.53 + ALuint TotalSamples; 8.54 + // Master effect low-pass filter (2 chained 1-pole filters). 8.55 + FILTER LpFilter; 8.56 + ALfloat LpHistory[2]; 8.57 + struct { 8.58 + // Modulator delay line. 8.59 + DelayLine Delay; 8.60 + // The vibrato time is tracked with an index over a modulus-wrapped 8.61 + // range (in samples). 8.62 + ALuint Index; 8.63 + ALuint Range; 8.64 + // The depth of frequency change (also in samples) and its filter. 8.65 + ALfloat Depth; 8.66 + ALfloat Coeff; 8.67 + ALfloat Filter; 8.68 + } Mod; 8.69 + // Initial effect delay. 8.70 + DelayLine Delay; 8.71 + // The tap points for the initial delay. First tap goes to early 8.72 + // reflections, the last to late reverb. 8.73 + ALuint DelayTap[2]; 8.74 + struct { 8.75 + // Output gain for early reflections. 8.76 + ALfloat Gain; 8.77 + // Early reflections are done with 4 delay lines. 8.78 + ALfloat Coeff[4]; 8.79 + DelayLine Delay[4]; 8.80 + ALuint Offset[4]; 8.81 + // The gain for each output channel based on 3D panning (only for the 8.82 + // EAX path). 8.83 + ALfloat PanGain[MAXCHANNELS]; 8.84 + } Early; 8.85 + // Decorrelator delay line. 8.86 + DelayLine Decorrelator; 8.87 + // There are actually 4 decorrelator taps, but the first occurs at the 8.88 + // initial sample. 8.89 + ALuint DecoTap[3]; 8.90 + struct { 8.91 + // Output gain for late reverb. 8.92 + ALfloat Gain; 8.93 + // Attenuation to compensate for the modal density and decay rate of 8.94 + // the late lines. 8.95 + ALfloat DensityGain; 8.96 + // The feed-back and feed-forward all-pass coefficient. 8.97 + ALfloat ApFeedCoeff; 8.98 + // Mixing matrix coefficient. 8.99 + ALfloat MixCoeff; 8.100 + // Late reverb has 4 parallel all-pass filters. 8.101 + ALfloat ApCoeff[4]; 8.102 + DelayLine ApDelay[4]; 8.103 + ALuint ApOffset[4]; 8.104 + // In addition to 4 cyclical delay lines. 8.105 + ALfloat Coeff[4]; 8.106 + DelayLine Delay[4]; 8.107 + ALuint Offset[4]; 8.108 + // The cyclical delay lines are 1-pole low-pass filtered. 8.109 + ALfloat LpCoeff[4]; 8.110 + ALfloat LpSample[4]; 8.111 + // The gain for each output channel based on 3D panning (only for the 8.112 + // EAX path). 8.113 + ALfloat PanGain[MAXCHANNELS]; 8.114 + } Late; 8.115 + struct { 8.116 + // Attenuation to compensate for the modal density and decay rate of 8.117 + // the echo line. 8.118 + ALfloat DensityGain; 8.119 + // Echo delay and all-pass lines. 8.120 + DelayLine Delay; 8.121 + DelayLine ApDelay; 8.122 + ALfloat Coeff; 8.123 + ALfloat ApFeedCoeff; 8.124 + ALfloat ApCoeff; 8.125 + ALuint Offset; 8.126 + ALuint ApOffset; 8.127 + // The echo line is 1-pole low-pass filtered. 8.128 + ALfloat LpCoeff; 8.129 + ALfloat LpSample; 8.130 + // Echo mixing coefficients. 8.131 + ALfloat MixCoeff[2]; 8.132 + } Echo; 8.133 + // The current read offset for all delay lines. 8.134 + ALuint Offset; 8.135 + 8.136 + // The gain for each output channel (non-EAX path only; aliased from 8.137 + // Late.PanGain) 8.138 + ALfloat *Gain; 8.139 +} ALverbState; 8.140 + 8.141 +/* This is a user config option for modifying the overall output of the reverb 8.142 + * effect. 8.143 + */ 8.144 +ALfloat ReverbBoost = 1.0f; 8.145 + 8.146 +/* Specifies whether to use a standard reverb effect in place of EAX reverb */ 8.147 +ALboolean EmulateEAXReverb = AL_FALSE; 8.148 + 8.149 +/* This coefficient is used to define the maximum frequency range controlled 8.150 + * by the modulation depth. The current value of 0.1 will allow it to swing 8.151 + * from 0.9x to 1.1x. This value must be below 1. At 1 it will cause the 8.152 + * sampler to stall on the downswing, and above 1 it will cause it to sample 8.153 + * backwards. 8.154 + */ 8.155 +static const ALfloat MODULATION_DEPTH_COEFF = 0.1f; 8.156 + 8.157 +/* A filter is used to avoid the terrible distortion caused by changing 8.158 + * modulation time and/or depth. To be consistent across different sample 8.159 + * rates, the coefficient must be raised to a constant divided by the sample 8.160 + * rate: coeff^(constant / rate). 8.161 + */ 8.162 +static const ALfloat MODULATION_FILTER_COEFF = 0.048f; 8.163 +static const ALfloat MODULATION_FILTER_CONST = 100000.0f; 8.164 + 8.165 +// When diffusion is above 0, an all-pass filter is used to take the edge off 8.166 +// the echo effect. It uses the following line length (in seconds). 8.167 +static const ALfloat ECHO_ALLPASS_LENGTH = 0.0133f; 8.168 + 8.169 +// Input into the late reverb is decorrelated between four channels. Their 8.170 +// timings are dependent on a fraction and multiplier. See the 8.171 +// UpdateDecorrelator() routine for the calculations involved. 8.172 +static const ALfloat DECO_FRACTION = 0.15f; 8.173 +static const ALfloat DECO_MULTIPLIER = 2.0f; 8.174 + 8.175 +// All delay line lengths are specified in seconds. 8.176 + 8.177 +// The lengths of the early delay lines. 8.178 +static const ALfloat EARLY_LINE_LENGTH[4] = 8.179 +{ 8.180 + 0.0015f, 0.0045f, 0.0135f, 0.0405f 8.181 +}; 8.182 + 8.183 +// The lengths of the late all-pass delay lines. 8.184 +static const ALfloat ALLPASS_LINE_LENGTH[4] = 8.185 +{ 8.186 + 0.0151f, 0.0167f, 0.0183f, 0.0200f, 8.187 +}; 8.188 + 8.189 +// The lengths of the late cyclical delay lines. 8.190 +static const ALfloat LATE_LINE_LENGTH[4] = 8.191 +{ 8.192 + 0.0211f, 0.0311f, 0.0461f, 0.0680f 8.193 +}; 8.194 + 8.195 +// The late cyclical delay lines have a variable length dependent on the 8.196 +// effect's density parameter (inverted for some reason) and this multiplier. 8.197 +static const ALfloat LATE_LINE_MULTIPLIER = 4.0f; 8.198 + 8.199 +// Calculate the length of a delay line and store its mask and offset. 8.200 +static ALuint CalcLineLength(ALfloat length, ALintptrEXT offset, ALuint frequency, DelayLine *Delay) 8.201 +{ 8.202 + ALuint samples; 8.203 + 8.204 + // All line lengths are powers of 2, calculated from their lengths, with 8.205 + // an additional sample in case of rounding errors. 8.206 + samples = NextPowerOf2((ALuint)(length * frequency) + 1); 8.207 + // All lines share a single sample buffer. 8.208 + Delay->Mask = samples - 1; 8.209 + Delay->Line = (ALfloat*)offset; 8.210 + // Return the sample count for accumulation. 8.211 + return samples; 8.212 +} 8.213 + 8.214 +// Given the allocated sample buffer, this function updates each delay line 8.215 +// offset. 8.216 +static __inline ALvoid RealizeLineOffset(ALfloat * sampleBuffer, DelayLine *Delay) 8.217 +{ 8.218 + Delay->Line = &sampleBuffer[(ALintptrEXT)Delay->Line]; 8.219 +} 8.220 + 8.221 +/* Calculates the delay line metrics and allocates the shared sample buffer 8.222 + * for all lines given a flag indicating whether or not to allocate the EAX- 8.223 + * related delays (eaxFlag) and the sample rate (frequency). If an 8.224 + * allocation failure occurs, it returns AL_FALSE. 8.225 + */ 8.226 +static ALboolean AllocLines(ALboolean eaxFlag, ALuint frequency, ALverbState *State) 8.227 +{ 8.228 + ALuint totalSamples, index; 8.229 + ALfloat length; 8.230 + ALfloat *newBuffer = NULL; 8.231 + 8.232 + // All delay line lengths are calculated to accomodate the full range of 8.233 + // lengths given their respective paramters. 8.234 + totalSamples = 0; 8.235 + if(eaxFlag) 8.236 + { 8.237 + /* The modulator's line length is calculated from the maximum 8.238 + * modulation time and depth coefficient, and halfed for the low-to- 8.239 + * high frequency swing. An additional sample is added to keep it 8.240 + * stable when there is no modulation. 8.241 + */ 8.242 + length = (AL_EAXREVERB_MAX_MODULATION_TIME * MODULATION_DEPTH_COEFF / 8.243 + 2.0f) + (1.0f / frequency); 8.244 + totalSamples += CalcLineLength(length, totalSamples, frequency, 8.245 + &State->Mod.Delay); 8.246 + } 8.247 + 8.248 + // The initial delay is the sum of the reflections and late reverb 8.249 + // delays. 8.250 + if(eaxFlag) 8.251 + length = AL_EAXREVERB_MAX_REFLECTIONS_DELAY + 8.252 + AL_EAXREVERB_MAX_LATE_REVERB_DELAY; 8.253 + else 8.254 + length = AL_REVERB_MAX_REFLECTIONS_DELAY + 8.255 + AL_REVERB_MAX_LATE_REVERB_DELAY; 8.256 + totalSamples += CalcLineLength(length, totalSamples, frequency, 8.257 + &State->Delay); 8.258 + 8.259 + // The early reflection lines. 8.260 + for(index = 0;index < 4;index++) 8.261 + totalSamples += CalcLineLength(EARLY_LINE_LENGTH[index], totalSamples, 8.262 + frequency, &State->Early.Delay[index]); 8.263 + 8.264 + // The decorrelator line is calculated from the lowest reverb density (a 8.265 + // parameter value of 1). 8.266 + length = (DECO_FRACTION * DECO_MULTIPLIER * DECO_MULTIPLIER) * 8.267 + LATE_LINE_LENGTH[0] * (1.0f + LATE_LINE_MULTIPLIER); 8.268 + totalSamples += CalcLineLength(length, totalSamples, frequency, 8.269 + &State->Decorrelator); 8.270 + 8.271 + // The late all-pass lines. 8.272 + for(index = 0;index < 4;index++) 8.273 + totalSamples += CalcLineLength(ALLPASS_LINE_LENGTH[index], totalSamples, 8.274 + frequency, &State->Late.ApDelay[index]); 8.275 + 8.276 + // The late delay lines are calculated from the lowest reverb density. 8.277 + for(index = 0;index < 4;index++) 8.278 + { 8.279 + length = LATE_LINE_LENGTH[index] * (1.0f + LATE_LINE_MULTIPLIER); 8.280 + totalSamples += CalcLineLength(length, totalSamples, frequency, 8.281 + &State->Late.Delay[index]); 8.282 + } 8.283 + 8.284 + if(eaxFlag) 8.285 + { 8.286 + // The echo all-pass and delay lines. 8.287 + totalSamples += CalcLineLength(ECHO_ALLPASS_LENGTH, totalSamples, 8.288 + frequency, &State->Echo.ApDelay); 8.289 + totalSamples += CalcLineLength(AL_EAXREVERB_MAX_ECHO_TIME, totalSamples, 8.290 + frequency, &State->Echo.Delay); 8.291 + } 8.292 + 8.293 + if(totalSamples != State->TotalSamples) 8.294 + { 8.295 + newBuffer = realloc(State->SampleBuffer, sizeof(ALfloat) * totalSamples); 8.296 + if(newBuffer == NULL) 8.297 + return AL_FALSE; 8.298 + State->SampleBuffer = newBuffer; 8.299 + State->TotalSamples = totalSamples; 8.300 + } 8.301 + 8.302 + // Update all delays to reflect the new sample buffer. 8.303 + RealizeLineOffset(State->SampleBuffer, &State->Delay); 8.304 + RealizeLineOffset(State->SampleBuffer, &State->Decorrelator); 8.305 + for(index = 0;index < 4;index++) 8.306 + { 8.307 + RealizeLineOffset(State->SampleBuffer, &State->Early.Delay[index]); 8.308 + RealizeLineOffset(State->SampleBuffer, &State->Late.ApDelay[index]); 8.309 + RealizeLineOffset(State->SampleBuffer, &State->Late.Delay[index]); 8.310 + } 8.311 + if(eaxFlag) 8.312 + { 8.313 + RealizeLineOffset(State->SampleBuffer, &State->Mod.Delay); 8.314 + RealizeLineOffset(State->SampleBuffer, &State->Echo.ApDelay); 8.315 + RealizeLineOffset(State->SampleBuffer, &State->Echo.Delay); 8.316 + } 8.317 + 8.318 + // Clear the sample buffer. 8.319 + for(index = 0;index < State->TotalSamples;index++) 8.320 + State->SampleBuffer[index] = 0.0f; 8.321 + 8.322 + return AL_TRUE; 8.323 +} 8.324 + 8.325 +// Calculate a decay coefficient given the length of each cycle and the time 8.326 +// until the decay reaches -60 dB. 8.327 +static __inline ALfloat CalcDecayCoeff(ALfloat length, ALfloat decayTime) 8.328 +{ 8.329 + return aluPow(0.001f/*-60 dB*/, length/decayTime); 8.330 +} 8.331 + 8.332 +// Calculate a decay length from a coefficient and the time until the decay 8.333 +// reaches -60 dB. 8.334 +static __inline ALfloat CalcDecayLength(ALfloat coeff, ALfloat decayTime) 8.335 +{ 8.336 + return log10(coeff) * decayTime / -3.0f/*log10(0.001)*/; 8.337 +} 8.338 + 8.339 +// Calculate the high frequency parameter for the I3DL2 coefficient 8.340 +// calculation. 8.341 +static __inline ALfloat CalcI3DL2HFreq(ALfloat hfRef, ALuint frequency) 8.342 +{ 8.343 + return cos(2.0f * M_PI * hfRef / frequency); 8.344 +} 8.345 + 8.346 +// Calculate an attenuation to be applied to the input of any echo models to 8.347 +// compensate for modal density and decay time. 8.348 +static __inline ALfloat CalcDensityGain(ALfloat a) 8.349 +{ 8.350 + /* The energy of a signal can be obtained by finding the area under the 8.351 + * squared signal. This takes the form of Sum(x_n^2), where x is the 8.352 + * amplitude for the sample n. 8.353 + * 8.354 + * Decaying feedback matches exponential decay of the form Sum(a^n), 8.355 + * where a is the attenuation coefficient, and n is the sample. The area 8.356 + * under this decay curve can be calculated as: 1 / (1 - a). 8.357 + * 8.358 + * Modifying the above equation to find the squared area under the curve 8.359 + * (for energy) yields: 1 / (1 - a^2). Input attenuation can then be 8.360 + * calculated by inverting the square root of this approximation, 8.361 + * yielding: 1 / sqrt(1 / (1 - a^2)), simplified to: sqrt(1 - a^2). 8.362 + */ 8.363 + return aluSqrt(1.0f - (a * a)); 8.364 +} 8.365 + 8.366 +// Calculate the mixing matrix coefficients given a diffusion factor. 8.367 +static __inline ALvoid CalcMatrixCoeffs(ALfloat diffusion, ALfloat *x, ALfloat *y) 8.368 +{ 8.369 + ALfloat n, t; 8.370 + 8.371 + // The matrix is of order 4, so n is sqrt (4 - 1). 8.372 + n = aluSqrt(3.0f); 8.373 + t = diffusion * atan(n); 8.374 + 8.375 + // Calculate the first mixing matrix coefficient. 8.376 + *x = cos(t); 8.377 + // Calculate the second mixing matrix coefficient. 8.378 + *y = sin(t) / n; 8.379 +} 8.380 + 8.381 +// Calculate the limited HF ratio for use with the late reverb low-pass 8.382 +// filters. 8.383 +static ALfloat CalcLimitedHfRatio(ALfloat hfRatio, ALfloat airAbsorptionGainHF, ALfloat decayTime) 8.384 +{ 8.385 + ALfloat limitRatio; 8.386 + 8.387 + /* Find the attenuation due to air absorption in dB (converting delay 8.388 + * time to meters using the speed of sound). Then reversing the decay 8.389 + * equation, solve for HF ratio. The delay length is cancelled out of 8.390 + * the equation, so it can be calculated once for all lines. 8.391 + */ 8.392 + limitRatio = 1.0f / (CalcDecayLength(airAbsorptionGainHF, decayTime) * 8.393 + SPEEDOFSOUNDMETRESPERSEC); 8.394 + /* Using the limit calculated above, apply the upper bound to the HF 8.395 + * ratio. Also need to limit the result to a minimum of 0.1, just like the 8.396 + * HF ratio parameter. */ 8.397 + return clampf(limitRatio, 0.1f, hfRatio); 8.398 +} 8.399 + 8.400 +// Calculate the coefficient for a HF (and eventually LF) decay damping 8.401 +// filter. 8.402 +static __inline ALfloat CalcDampingCoeff(ALfloat hfRatio, ALfloat length, ALfloat decayTime, ALfloat decayCoeff, ALfloat cw) 8.403 +{ 8.404 + ALfloat coeff, g; 8.405 + 8.406 + // Eventually this should boost the high frequencies when the ratio 8.407 + // exceeds 1. 8.408 + coeff = 0.0f; 8.409 + if (hfRatio < 1.0f) 8.410 + { 8.411 + // Calculate the low-pass coefficient by dividing the HF decay 8.412 + // coefficient by the full decay coefficient. 8.413 + g = CalcDecayCoeff(length, decayTime * hfRatio) / decayCoeff; 8.414 + 8.415 + // Damping is done with a 1-pole filter, so g needs to be squared. 8.416 + g *= g; 8.417 + coeff = lpCoeffCalc(g, cw); 8.418 + 8.419 + // Very low decay times will produce minimal output, so apply an 8.420 + // upper bound to the coefficient. 8.421 + coeff = minf(coeff, 0.98f); 8.422 + } 8.423 + return coeff; 8.424 +} 8.425 + 8.426 +// Update the EAX modulation index, range, and depth. Keep in mind that this 8.427 +// kind of vibrato is additive and not multiplicative as one may expect. The 8.428 +// downswing will sound stronger than the upswing. 8.429 +static ALvoid UpdateModulator(ALfloat modTime, ALfloat modDepth, ALuint frequency, ALverbState *State) 8.430 +{ 8.431 + ALfloat length; 8.432 + 8.433 + /* Modulation is calculated in two parts. 8.434 + * 8.435 + * The modulation time effects the sinus applied to the change in 8.436 + * frequency. An index out of the current time range (both in samples) 8.437 + * is incremented each sample. The range is bound to a reasonable 8.438 + * minimum (1 sample) and when the timing changes, the index is rescaled 8.439 + * to the new range (to keep the sinus consistent). 8.440 + */ 8.441 + length = modTime * frequency; 8.442 + if (length >= 1.0f) { 8.443 + State->Mod.Index = (ALuint)(State->Mod.Index * length / 8.444 + State->Mod.Range); 8.445 + State->Mod.Range = (ALuint)length; 8.446 + } else { 8.447 + State->Mod.Index = 0; 8.448 + State->Mod.Range = 1; 8.449 + } 8.450 + 8.451 + /* The modulation depth effects the amount of frequency change over the 8.452 + * range of the sinus. It needs to be scaled by the modulation time so 8.453 + * that a given depth produces a consistent change in frequency over all 8.454 + * ranges of time. Since the depth is applied to a sinus value, it needs 8.455 + * to be halfed once for the sinus range and again for the sinus swing 8.456 + * in time (half of it is spent decreasing the frequency, half is spent 8.457 + * increasing it). 8.458 + */ 8.459 + State->Mod.Depth = modDepth * MODULATION_DEPTH_COEFF * modTime / 2.0f / 8.460 + 2.0f * frequency; 8.461 +} 8.462 + 8.463 +// Update the offsets for the initial effect delay line. 8.464 +static ALvoid UpdateDelayLine(ALfloat earlyDelay, ALfloat lateDelay, ALuint frequency, ALverbState *State) 8.465 +{ 8.466 + // Calculate the initial delay taps. 8.467 + State->DelayTap[0] = (ALuint)(earlyDelay * frequency); 8.468 + State->DelayTap[1] = (ALuint)((earlyDelay + lateDelay) * frequency); 8.469 +} 8.470 + 8.471 +// Update the early reflections gain and line coefficients. 8.472 +static ALvoid UpdateEarlyLines(ALfloat reverbGain, ALfloat earlyGain, ALfloat lateDelay, ALverbState *State) 8.473 +{ 8.474 + ALuint index; 8.475 + 8.476 + // Calculate the early reflections gain (from the master effect gain, and 8.477 + // reflections gain parameters) with a constant attenuation of 0.5. 8.478 + State->Early.Gain = 0.5f * reverbGain * earlyGain; 8.479 + 8.480 + // Calculate the gain (coefficient) for each early delay line using the 8.481 + // late delay time. This expands the early reflections to the start of 8.482 + // the late reverb. 8.483 + for(index = 0;index < 4;index++) 8.484 + State->Early.Coeff[index] = CalcDecayCoeff(EARLY_LINE_LENGTH[index], 8.485 + lateDelay); 8.486 +} 8.487 + 8.488 +// Update the offsets for the decorrelator line. 8.489 +static ALvoid UpdateDecorrelator(ALfloat density, ALuint frequency, ALverbState *State) 8.490 +{ 8.491 + ALuint index; 8.492 + ALfloat length; 8.493 + 8.494 + /* The late reverb inputs are decorrelated to smooth the reverb tail and 8.495 + * reduce harsh echos. The first tap occurs immediately, while the 8.496 + * remaining taps are delayed by multiples of a fraction of the smallest 8.497 + * cyclical delay time. 8.498 + * 8.499 + * offset[index] = (FRACTION (MULTIPLIER^index)) smallest_delay 8.500 + */ 8.501 + for(index = 0;index < 3;index++) 8.502 + { 8.503 + length = (DECO_FRACTION * aluPow(DECO_MULTIPLIER, (ALfloat)index)) * 8.504 + LATE_LINE_LENGTH[0] * (1.0f + (density * LATE_LINE_MULTIPLIER)); 8.505 + State->DecoTap[index] = (ALuint)(length * frequency); 8.506 + } 8.507 +} 8.508 + 8.509 +// Update the late reverb gains, line lengths, and line coefficients. 8.510 +static ALvoid UpdateLateLines(ALfloat reverbGain, ALfloat lateGain, ALfloat xMix, ALfloat density, ALfloat decayTime, ALfloat diffusion, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State) 8.511 +{ 8.512 + ALfloat length; 8.513 + ALuint index; 8.514 + 8.515 + /* Calculate the late reverb gain (from the master effect gain, and late 8.516 + * reverb gain parameters). Since the output is tapped prior to the 8.517 + * application of the next delay line coefficients, this gain needs to be 8.518 + * attenuated by the 'x' mixing matrix coefficient as well. 8.519 + */ 8.520 + State->Late.Gain = reverbGain * lateGain * xMix; 8.521 + 8.522 + /* To compensate for changes in modal density and decay time of the late 8.523 + * reverb signal, the input is attenuated based on the maximal energy of 8.524 + * the outgoing signal. This approximation is used to keep the apparent 8.525 + * energy of the signal equal for all ranges of density and decay time. 8.526 + * 8.527 + * The average length of the cyclcical delay lines is used to calculate 8.528 + * the attenuation coefficient. 8.529 + */ 8.530 + length = (LATE_LINE_LENGTH[0] + LATE_LINE_LENGTH[1] + 8.531 + LATE_LINE_LENGTH[2] + LATE_LINE_LENGTH[3]) / 4.0f; 8.532 + length *= 1.0f + (density * LATE_LINE_MULTIPLIER); 8.533 + State->Late.DensityGain = CalcDensityGain(CalcDecayCoeff(length, 8.534 + decayTime)); 8.535 + 8.536 + // Calculate the all-pass feed-back and feed-forward coefficient. 8.537 + State->Late.ApFeedCoeff = 0.5f * aluPow(diffusion, 2.0f); 8.538 + 8.539 + for(index = 0;index < 4;index++) 8.540 + { 8.541 + // Calculate the gain (coefficient) for each all-pass line. 8.542 + State->Late.ApCoeff[index] = CalcDecayCoeff(ALLPASS_LINE_LENGTH[index], 8.543 + decayTime); 8.544 + 8.545 + // Calculate the length (in seconds) of each cyclical delay line. 8.546 + length = LATE_LINE_LENGTH[index] * (1.0f + (density * 8.547 + LATE_LINE_MULTIPLIER)); 8.548 + 8.549 + // Calculate the delay offset for each cyclical delay line. 8.550 + State->Late.Offset[index] = (ALuint)(length * frequency); 8.551 + 8.552 + // Calculate the gain (coefficient) for each cyclical line. 8.553 + State->Late.Coeff[index] = CalcDecayCoeff(length, decayTime); 8.554 + 8.555 + // Calculate the damping coefficient for each low-pass filter. 8.556 + State->Late.LpCoeff[index] = 8.557 + CalcDampingCoeff(hfRatio, length, decayTime, 8.558 + State->Late.Coeff[index], cw); 8.559 + 8.560 + // Attenuate the cyclical line coefficients by the mixing coefficient 8.561 + // (x). 8.562 + State->Late.Coeff[index] *= xMix; 8.563 + } 8.564 +} 8.565 + 8.566 +// Update the echo gain, line offset, line coefficients, and mixing 8.567 +// coefficients. 8.568 +static ALvoid UpdateEchoLine(ALfloat reverbGain, ALfloat lateGain, ALfloat echoTime, ALfloat decayTime, ALfloat diffusion, ALfloat echoDepth, ALfloat hfRatio, ALfloat cw, ALuint frequency, ALverbState *State) 8.569 +{ 8.570 + // Update the offset and coefficient for the echo delay line. 8.571 + State->Echo.Offset = (ALuint)(echoTime * frequency); 8.572 + 8.573 + // Calculate the decay coefficient for the echo line. 8.574 + State->Echo.Coeff = CalcDecayCoeff(echoTime, decayTime); 8.575 + 8.576 + // Calculate the energy-based attenuation coefficient for the echo delay 8.577 + // line. 8.578 + State->Echo.DensityGain = CalcDensityGain(State->Echo.Coeff); 8.579 + 8.580 + // Calculate the echo all-pass feed coefficient. 8.581 + State->Echo.ApFeedCoeff = 0.5f * aluPow(diffusion, 2.0f); 8.582 + 8.583 + // Calculate the echo all-pass attenuation coefficient. 8.584 + State->Echo.ApCoeff = CalcDecayCoeff(ECHO_ALLPASS_LENGTH, decayTime); 8.585 + 8.586 + // Calculate the damping coefficient for each low-pass filter. 8.587 + State->Echo.LpCoeff = CalcDampingCoeff(hfRatio, echoTime, decayTime, 8.588 + State->Echo.Coeff, cw); 8.589 + 8.590 + /* Calculate the echo mixing coefficients. The first is applied to the 8.591 + * echo itself. The second is used to attenuate the late reverb when 8.592 + * echo depth is high and diffusion is low, so the echo is slightly 8.593 + * stronger than the decorrelated echos in the reverb tail. 8.594 + */ 8.595 + State->Echo.MixCoeff[0] = reverbGain * lateGain * echoDepth; 8.596 + State->Echo.MixCoeff[1] = 1.0f - (echoDepth * 0.5f * (1.0f - diffusion)); 8.597 +} 8.598 + 8.599 +// Update the early and late 3D panning gains. 8.600 +static ALvoid Update3DPanning(const ALCdevice *Device, const ALfloat *ReflectionsPan, const ALfloat *LateReverbPan, ALfloat Gain, ALverbState *State) 8.601 +{ 8.602 + ALfloat earlyPan[3] = { ReflectionsPan[0], ReflectionsPan[1], 8.603 + ReflectionsPan[2] }; 8.604 + ALfloat latePan[3] = { LateReverbPan[0], LateReverbPan[1], 8.605 + LateReverbPan[2] }; 8.606 + const ALfloat *speakerGain; 8.607 + ALfloat ambientGain; 8.608 + ALfloat dirGain; 8.609 + ALfloat length; 8.610 + ALuint index; 8.611 + ALint pos; 8.612 + 8.613 + Gain *= ReverbBoost; 8.614 + 8.615 + // Attenuate non-directional reverb according to the number of channels 8.616 + ambientGain = aluSqrt(2.0f/Device->NumChan); 8.617 + 8.618 + // Calculate the 3D-panning gains for the early reflections and late 8.619 + // reverb. 8.620 + length = earlyPan[0]*earlyPan[0] + earlyPan[1]*earlyPan[1] + earlyPan[2]*earlyPan[2]; 8.621 + if(length > 1.0f) 8.622 + { 8.623 + length = 1.0f / aluSqrt(length); 8.624 + earlyPan[0] *= length; 8.625 + earlyPan[1] *= length; 8.626 + earlyPan[2] *= length; 8.627 + } 8.628 + length = latePan[0]*latePan[0] + latePan[1]*latePan[1] + latePan[2]*latePan[2]; 8.629 + if(length > 1.0f) 8.630 + { 8.631 + length = 1.0f / aluSqrt(length); 8.632 + latePan[0] *= length; 8.633 + latePan[1] *= length; 8.634 + latePan[2] *= length; 8.635 + } 8.636 + 8.637 + /* This code applies directional reverb just like the mixer applies 8.638 + * directional sources. It diffuses the sound toward all speakers as the 8.639 + * magnitude of the panning vector drops, which is only a rough 8.640 + * approximation of the expansion of sound across the speakers from the 8.641 + * panning direction. 8.642 + */ 8.643 + pos = aluCart2LUTpos(earlyPan[2], earlyPan[0]); 8.644 + speakerGain = Device->PanningLUT[pos]; 8.645 + dirGain = aluSqrt((earlyPan[0] * earlyPan[0]) + (earlyPan[2] * earlyPan[2])); 8.646 + 8.647 + for(index = 0;index < MAXCHANNELS;index++) 8.648 + State->Early.PanGain[index] = 0.0f; 8.649 + for(index = 0;index < Device->NumChan;index++) 8.650 + { 8.651 + enum Channel chan = Device->Speaker2Chan[index]; 8.652 + State->Early.PanGain[chan] = lerp(ambientGain, speakerGain[chan], dirGain) * Gain; 8.653 + } 8.654 + 8.655 + 8.656 + pos = aluCart2LUTpos(latePan[2], latePan[0]); 8.657 + speakerGain = Device->PanningLUT[pos]; 8.658 + dirGain = aluSqrt((latePan[0] * latePan[0]) + (latePan[2] * latePan[2])); 8.659 + 8.660 + for(index = 0;index < MAXCHANNELS;index++) 8.661 + State->Late.PanGain[index] = 0.0f; 8.662 + for(index = 0;index < Device->NumChan;index++) 8.663 + { 8.664 + enum Channel chan = Device->Speaker2Chan[index]; 8.665 + State->Late.PanGain[chan] = lerp(ambientGain, speakerGain[chan], dirGain) * Gain; 8.666 + } 8.667 +} 8.668 + 8.669 +// Basic delay line input/output routines. 8.670 +static __inline ALfloat DelayLineOut(DelayLine *Delay, ALuint offset) 8.671 +{ 8.672 + return Delay->Line[offset&Delay->Mask]; 8.673 +} 8.674 + 8.675 +static __inline ALvoid DelayLineIn(DelayLine *Delay, ALuint offset, ALfloat in) 8.676 +{ 8.677 + Delay->Line[offset&Delay->Mask] = in; 8.678 +} 8.679 + 8.680 +// Attenuated delay line output routine. 8.681 +static __inline ALfloat AttenuatedDelayLineOut(DelayLine *Delay, ALuint offset, ALfloat coeff) 8.682 +{ 8.683 + return coeff * Delay->Line[offset&Delay->Mask]; 8.684 +} 8.685 + 8.686 +// Basic attenuated all-pass input/output routine. 8.687 +static __inline ALfloat AllpassInOut(DelayLine *Delay, ALuint outOffset, ALuint inOffset, ALfloat in, ALfloat feedCoeff, ALfloat coeff) 8.688 +{ 8.689 + ALfloat out, feed; 8.690 + 8.691 + out = DelayLineOut(Delay, outOffset); 8.692 + feed = feedCoeff * in; 8.693 + DelayLineIn(Delay, inOffset, (feedCoeff * (out - feed)) + in); 8.694 + 8.695 + // The time-based attenuation is only applied to the delay output to 8.696 + // keep it from affecting the feed-back path (which is already controlled 8.697 + // by the all-pass feed coefficient). 8.698 + return (coeff * out) - feed; 8.699 +} 8.700 + 8.701 +// Given an input sample, this function produces modulation for the late 8.702 +// reverb. 8.703 +static __inline ALfloat EAXModulation(ALverbState *State, ALfloat in) 8.704 +{ 8.705 + ALfloat sinus, frac; 8.706 + ALuint offset; 8.707 + ALfloat out0, out1; 8.708 + 8.709 + // Calculate the sinus rythm (dependent on modulation time and the 8.710 + // sampling rate). The center of the sinus is moved to reduce the delay 8.711 + // of the effect when the time or depth are low. 8.712 + sinus = 1.0f - cos(2.0f * M_PI * State->Mod.Index / State->Mod.Range); 8.713 + 8.714 + // The depth determines the range over which to read the input samples 8.715 + // from, so it must be filtered to reduce the distortion caused by even 8.716 + // small parameter changes. 8.717 + State->Mod.Filter = lerp(State->Mod.Filter, State->Mod.Depth, 8.718 + State->Mod.Coeff); 8.719 + 8.720 + // Calculate the read offset and fraction between it and the next sample. 8.721 + frac = (1.0f + (State->Mod.Filter * sinus)); 8.722 + offset = (ALuint)frac; 8.723 + frac -= offset; 8.724 + 8.725 + // Get the two samples crossed by the offset, and feed the delay line 8.726 + // with the next input sample. 8.727 + out0 = DelayLineOut(&State->Mod.Delay, State->Offset - offset); 8.728 + out1 = DelayLineOut(&State->Mod.Delay, State->Offset - offset - 1); 8.729 + DelayLineIn(&State->Mod.Delay, State->Offset, in); 8.730 + 8.731 + // Step the modulation index forward, keeping it bound to its range. 8.732 + State->Mod.Index = (State->Mod.Index + 1) % State->Mod.Range; 8.733 + 8.734 + // The output is obtained by linearly interpolating the two samples that 8.735 + // were acquired above. 8.736 + return lerp(out0, out1, frac); 8.737 +} 8.738 + 8.739 +// Delay line output routine for early reflections. 8.740 +static __inline ALfloat EarlyDelayLineOut(ALverbState *State, ALuint index) 8.741 +{ 8.742 + return AttenuatedDelayLineOut(&State->Early.Delay[index], 8.743 + State->Offset - State->Early.Offset[index], 8.744 + State->Early.Coeff[index]); 8.745 +} 8.746 + 8.747 +// Given an input sample, this function produces four-channel output for the 8.748 +// early reflections. 8.749 +static __inline ALvoid EarlyReflection(ALverbState *State, ALfloat in, ALfloat *out) 8.750 +{ 8.751 + ALfloat d[4], v, f[4]; 8.752 + 8.753 + // Obtain the decayed results of each early delay line. 8.754 + d[0] = EarlyDelayLineOut(State, 0); 8.755 + d[1] = EarlyDelayLineOut(State, 1); 8.756 + d[2] = EarlyDelayLineOut(State, 2); 8.757 + d[3] = EarlyDelayLineOut(State, 3); 8.758 + 8.759 + /* The following uses a lossless scattering junction from waveguide 8.760 + * theory. It actually amounts to a householder mixing matrix, which 8.761 + * will produce a maximally diffuse response, and means this can probably 8.762 + * be considered a simple feed-back delay network (FDN). 8.763 + * N 8.764 + * --- 8.765 + * \ 8.766 + * v = 2/N / d_i 8.767 + * --- 8.768 + * i=1 8.769 + */ 8.770 + v = (d[0] + d[1] + d[2] + d[3]) * 0.5f; 8.771 + // The junction is loaded with the input here. 8.772 + v += in; 8.773 + 8.774 + // Calculate the feed values for the delay lines. 8.775 + f[0] = v - d[0]; 8.776 + f[1] = v - d[1]; 8.777 + f[2] = v - d[2]; 8.778 + f[3] = v - d[3]; 8.779 + 8.780 + // Re-feed the delay lines. 8.781 + DelayLineIn(&State->Early.Delay[0], State->Offset, f[0]); 8.782 + DelayLineIn(&State->Early.Delay[1], State->Offset, f[1]); 8.783 + DelayLineIn(&State->Early.Delay[2], State->Offset, f[2]); 8.784 + DelayLineIn(&State->Early.Delay[3], State->Offset, f[3]); 8.785 + 8.786 + // Output the results of the junction for all four channels. 8.787 + out[0] = State->Early.Gain * f[0]; 8.788 + out[1] = State->Early.Gain * f[1]; 8.789 + out[2] = State->Early.Gain * f[2]; 8.790 + out[3] = State->Early.Gain * f[3]; 8.791 +} 8.792 + 8.793 +// All-pass input/output routine for late reverb. 8.794 +static __inline ALfloat LateAllPassInOut(ALverbState *State, ALuint index, ALfloat in) 8.795 +{ 8.796 + return AllpassInOut(&State->Late.ApDelay[index], 8.797 + State->Offset - State->Late.ApOffset[index], 8.798 + State->Offset, in, State->Late.ApFeedCoeff, 8.799 + State->Late.ApCoeff[index]); 8.800 +} 8.801 + 8.802 +// Delay line output routine for late reverb. 8.803 +static __inline ALfloat LateDelayLineOut(ALverbState *State, ALuint index) 8.804 +{ 8.805 + return AttenuatedDelayLineOut(&State->Late.Delay[index], 8.806 + State->Offset - State->Late.Offset[index], 8.807 + State->Late.Coeff[index]); 8.808 +} 8.809 + 8.810 +// Low-pass filter input/output routine for late reverb. 8.811 +static __inline ALfloat LateLowPassInOut(ALverbState *State, ALuint index, ALfloat in) 8.812 +{ 8.813 + in = lerp(in, State->Late.LpSample[index], State->Late.LpCoeff[index]); 8.814 + State->Late.LpSample[index] = in; 8.815 + return in; 8.816 +} 8.817 + 8.818 +// Given four decorrelated input samples, this function produces four-channel 8.819 +// output for the late reverb. 8.820 +static __inline ALvoid LateReverb(ALverbState *State, ALfloat *in, ALfloat *out) 8.821 +{ 8.822 + ALfloat d[4], f[4]; 8.823 + 8.824 + // Obtain the decayed results of the cyclical delay lines, and add the 8.825 + // corresponding input channels. Then pass the results through the 8.826 + // low-pass filters. 8.827 + 8.828 + // This is where the feed-back cycles from line 0 to 1 to 3 to 2 and back 8.829 + // to 0. 8.830 + d[0] = LateLowPassInOut(State, 2, in[2] + LateDelayLineOut(State, 2)); 8.831 + d[1] = LateLowPassInOut(State, 0, in[0] + LateDelayLineOut(State, 0)); 8.832 + d[2] = LateLowPassInOut(State, 3, in[3] + LateDelayLineOut(State, 3)); 8.833 + d[3] = LateLowPassInOut(State, 1, in[1] + LateDelayLineOut(State, 1)); 8.834 + 8.835 + // To help increase diffusion, run each line through an all-pass filter. 8.836 + // When there is no diffusion, the shortest all-pass filter will feed the 8.837 + // shortest delay line. 8.838 + d[0] = LateAllPassInOut(State, 0, d[0]); 8.839 + d[1] = LateAllPassInOut(State, 1, d[1]); 8.840 + d[2] = LateAllPassInOut(State, 2, d[2]); 8.841 + d[3] = LateAllPassInOut(State, 3, d[3]); 8.842 + 8.843 + /* Late reverb is done with a modified feed-back delay network (FDN) 8.844 + * topology. Four input lines are each fed through their own all-pass 8.845 + * filter and then into the mixing matrix. The four outputs of the 8.846 + * mixing matrix are then cycled back to the inputs. Each output feeds 8.847 + * a different input to form a circlular feed cycle. 8.848 + * 8.849 + * The mixing matrix used is a 4D skew-symmetric rotation matrix derived 8.850 + * using a single unitary rotational parameter: 8.851 + * 8.852 + * [ d, a, b, c ] 1 = a^2 + b^2 + c^2 + d^2 8.853 + * [ -a, d, c, -b ] 8.854 + * [ -b, -c, d, a ] 8.855 + * [ -c, b, -a, d ] 8.856 + * 8.857 + * The rotation is constructed from the effect's diffusion parameter, 8.858 + * yielding: 1 = x^2 + 3 y^2; where a, b, and c are the coefficient y 8.859 + * with differing signs, and d is the coefficient x. The matrix is thus: 8.860 + * 8.861 + * [ x, y, -y, y ] n = sqrt(matrix_order - 1) 8.862 + * [ -y, x, y, y ] t = diffusion_parameter * atan(n) 8.863 + * [ y, -y, x, y ] x = cos(t) 8.864 + * [ -y, -y, -y, x ] y = sin(t) / n 8.865 + * 8.866 + * To reduce the number of multiplies, the x coefficient is applied with 8.867 + * the cyclical delay line coefficients. Thus only the y coefficient is 8.868 + * applied when mixing, and is modified to be: y / x. 8.869 + */ 8.870 + f[0] = d[0] + (State->Late.MixCoeff * ( d[1] + -d[2] + d[3])); 8.871 + f[1] = d[1] + (State->Late.MixCoeff * (-d[0] + d[2] + d[3])); 8.872 + f[2] = d[2] + (State->Late.MixCoeff * ( d[0] + -d[1] + d[3])); 8.873 + f[3] = d[3] + (State->Late.MixCoeff * (-d[0] + -d[1] + -d[2] )); 8.874 + 8.875 + // Output the results of the matrix for all four channels, attenuated by 8.876 + // the late reverb gain (which is attenuated by the 'x' mix coefficient). 8.877 + out[0] = State->Late.Gain * f[0]; 8.878 + out[1] = State->Late.Gain * f[1]; 8.879 + out[2] = State->Late.Gain * f[2]; 8.880 + out[3] = State->Late.Gain * f[3]; 8.881 + 8.882 + // Re-feed the cyclical delay lines. 8.883 + DelayLineIn(&State->Late.Delay[0], State->Offset, f[0]); 8.884 + DelayLineIn(&State->Late.Delay[1], State->Offset, f[1]); 8.885 + DelayLineIn(&State->Late.Delay[2], State->Offset, f[2]); 8.886 + DelayLineIn(&State->Late.Delay[3], State->Offset, f[3]); 8.887 +} 8.888 + 8.889 +// Given an input sample, this function mixes echo into the four-channel late 8.890 +// reverb. 8.891 +static __inline ALvoid EAXEcho(ALverbState *State, ALfloat in, ALfloat *late) 8.892 +{ 8.893 + ALfloat out, feed; 8.894 + 8.895 + // Get the latest attenuated echo sample for output. 8.896 + feed = AttenuatedDelayLineOut(&State->Echo.Delay, 8.897 + State->Offset - State->Echo.Offset, 8.898 + State->Echo.Coeff); 8.899 + 8.900 + // Mix the output into the late reverb channels. 8.901 + out = State->Echo.MixCoeff[0] * feed; 8.902 + late[0] = (State->Echo.MixCoeff[1] * late[0]) + out; 8.903 + late[1] = (State->Echo.MixCoeff[1] * late[1]) + out; 8.904 + late[2] = (State->Echo.MixCoeff[1] * late[2]) + out; 8.905 + late[3] = (State->Echo.MixCoeff[1] * late[3]) + out; 8.906 + 8.907 + // Mix the energy-attenuated input with the output and pass it through 8.908 + // the echo low-pass filter. 8.909 + feed += State->Echo.DensityGain * in; 8.910 + feed = lerp(feed, State->Echo.LpSample, State->Echo.LpCoeff); 8.911 + State->Echo.LpSample = feed; 8.912 + 8.913 + // Then the echo all-pass filter. 8.914 + feed = AllpassInOut(&State->Echo.ApDelay, 8.915 + State->Offset - State->Echo.ApOffset, 8.916 + State->Offset, feed, State->Echo.ApFeedCoeff, 8.917 + State->Echo.ApCoeff); 8.918 + 8.919 + // Feed the delay with the mixed and filtered sample. 8.920 + DelayLineIn(&State->Echo.Delay, State->Offset, feed); 8.921 +} 8.922 + 8.923 +// Perform the non-EAX reverb pass on a given input sample, resulting in 8.924 +// four-channel output. 8.925 +static __inline ALvoid VerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late) 8.926 +{ 8.927 + ALfloat feed, taps[4]; 8.928 + 8.929 + // Low-pass filter the incoming sample. 8.930 + in = lpFilter2P(&State->LpFilter, 0, in); 8.931 + 8.932 + // Feed the initial delay line. 8.933 + DelayLineIn(&State->Delay, State->Offset, in); 8.934 + 8.935 + // Calculate the early reflection from the first delay tap. 8.936 + in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]); 8.937 + EarlyReflection(State, in, early); 8.938 + 8.939 + // Feed the decorrelator from the energy-attenuated output of the second 8.940 + // delay tap. 8.941 + in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]); 8.942 + feed = in * State->Late.DensityGain; 8.943 + DelayLineIn(&State->Decorrelator, State->Offset, feed); 8.944 + 8.945 + // Calculate the late reverb from the decorrelator taps. 8.946 + taps[0] = feed; 8.947 + taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]); 8.948 + taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]); 8.949 + taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]); 8.950 + LateReverb(State, taps, late); 8.951 + 8.952 + // Step all delays forward one sample. 8.953 + State->Offset++; 8.954 +} 8.955 + 8.956 +// Perform the EAX reverb pass on a given input sample, resulting in four- 8.957 +// channel output. 8.958 +static __inline ALvoid EAXVerbPass(ALverbState *State, ALfloat in, ALfloat *early, ALfloat *late) 8.959 +{ 8.960 + ALfloat feed, taps[4]; 8.961 + 8.962 + // Low-pass filter the incoming sample. 8.963 + in = lpFilter2P(&State->LpFilter, 0, in); 8.964 + 8.965 + // Perform any modulation on the input. 8.966 + in = EAXModulation(State, in); 8.967 + 8.968 + // Feed the initial delay line. 8.969 + DelayLineIn(&State->Delay, State->Offset, in); 8.970 + 8.971 + // Calculate the early reflection from the first delay tap. 8.972 + in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[0]); 8.973 + EarlyReflection(State, in, early); 8.974 + 8.975 + // Feed the decorrelator from the energy-attenuated output of the second 8.976 + // delay tap. 8.977 + in = DelayLineOut(&State->Delay, State->Offset - State->DelayTap[1]); 8.978 + feed = in * State->Late.DensityGain; 8.979 + DelayLineIn(&State->Decorrelator, State->Offset, feed); 8.980 + 8.981 + // Calculate the late reverb from the decorrelator taps. 8.982 + taps[0] = feed; 8.983 + taps[1] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[0]); 8.984 + taps[2] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[1]); 8.985 + taps[3] = DelayLineOut(&State->Decorrelator, State->Offset - State->DecoTap[2]); 8.986 + LateReverb(State, taps, late); 8.987 + 8.988 + // Calculate and mix in any echo. 8.989 + EAXEcho(State, in, late); 8.990 + 8.991 + // Step all delays forward one sample. 8.992 + State->Offset++; 8.993 +} 8.994 + 8.995 +// This destroys the reverb state. It should be called only when the effect 8.996 +// slot has a different (or no) effect loaded over the reverb effect. 8.997 +static ALvoid VerbDestroy(ALeffectState *effect) 8.998 +{ 8.999 + ALverbState *State = (ALverbState*)effect; 8.1000 + if(State) 8.1001 + { 8.1002 + free(State->SampleBuffer); 8.1003 + State->SampleBuffer = NULL; 8.1004 + free(State); 8.1005 + } 8.1006 +} 8.1007 + 8.1008 +// This updates the device-dependant reverb state. This is called on 8.1009 +// initialization and any time the device parameters (eg. playback frequency, 8.1010 +// or format) have been changed. 8.1011 +static ALboolean VerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device) 8.1012 +{ 8.1013 + ALverbState *State = (ALverbState*)effect; 8.1014 + ALuint frequency = Device->Frequency; 8.1015 + ALuint index; 8.1016 + 8.1017 + // Allocate the delay lines. 8.1018 + if(!AllocLines(AL_FALSE, frequency, State)) 8.1019 + return AL_FALSE; 8.1020 + 8.1021 + // The early reflection and late all-pass filter line lengths are static, 8.1022 + // so their offsets only need to be calculated once. 8.1023 + for(index = 0;index < 4;index++) 8.1024 + { 8.1025 + State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] * 8.1026 + frequency); 8.1027 + State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] * 8.1028 + frequency); 8.1029 + } 8.1030 + 8.1031 + return AL_TRUE; 8.1032 +} 8.1033 + 8.1034 +// This updates the device-dependant EAX reverb state. This is called on 8.1035 +// initialization and any time the device parameters (eg. playback frequency, 8.1036 +// format) have been changed. 8.1037 +static ALboolean EAXVerbDeviceUpdate(ALeffectState *effect, ALCdevice *Device) 8.1038 +{ 8.1039 + ALverbState *State = (ALverbState*)effect; 8.1040 + ALuint frequency = Device->Frequency, index; 8.1041 + 8.1042 + // Allocate the delay lines. 8.1043 + if(!AllocLines(AL_TRUE, frequency, State)) 8.1044 + return AL_FALSE; 8.1045 + 8.1046 + // Calculate the modulation filter coefficient. Notice that the exponent 8.1047 + // is calculated given the current sample rate. This ensures that the 8.1048 + // resulting filter response over time is consistent across all sample 8.1049 + // rates. 8.1050 + State->Mod.Coeff = aluPow(MODULATION_FILTER_COEFF, 8.1051 + MODULATION_FILTER_CONST / frequency); 8.1052 + 8.1053 + // The early reflection and late all-pass filter line lengths are static, 8.1054 + // so their offsets only need to be calculated once. 8.1055 + for(index = 0;index < 4;index++) 8.1056 + { 8.1057 + State->Early.Offset[index] = (ALuint)(EARLY_LINE_LENGTH[index] * 8.1058 + frequency); 8.1059 + State->Late.ApOffset[index] = (ALuint)(ALLPASS_LINE_LENGTH[index] * 8.1060 + frequency); 8.1061 + } 8.1062 + 8.1063 + // The echo all-pass filter line length is static, so its offset only 8.1064 + // needs to be calculated once. 8.1065 + State->Echo.ApOffset = (ALuint)(ECHO_ALLPASS_LENGTH * frequency); 8.1066 + 8.1067 + return AL_TRUE; 8.1068 +} 8.1069 + 8.1070 +// This updates the reverb state. This is called any time the reverb effect 8.1071 +// is loaded into a slot. 8.1072 +static ALvoid VerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) 8.1073 +{ 8.1074 + ALverbState *State = (ALverbState*)effect; 8.1075 + ALCdevice *Device = Context->Device; 8.1076 + ALuint frequency = Device->Frequency; 8.1077 + ALfloat cw, x, y, hfRatio, gain; 8.1078 + ALuint index; 8.1079 + 8.1080 + // Calculate the master low-pass filter (from the master effect HF gain). 8.1081 + cw = CalcI3DL2HFreq(Slot->effect.Params.Reverb.HFReference, frequency); 8.1082 + // This is done with 2 chained 1-pole filters, so no need to square g. 8.1083 + State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Params.Reverb.GainHF, cw); 8.1084 + 8.1085 + // Update the initial effect delay. 8.1086 + UpdateDelayLine(Slot->effect.Params.Reverb.ReflectionsDelay, 8.1087 + Slot->effect.Params.Reverb.LateReverbDelay, 8.1088 + frequency, State); 8.1089 + 8.1090 + // Update the early lines. 8.1091 + UpdateEarlyLines(Slot->effect.Params.Reverb.Gain, 8.1092 + Slot->effect.Params.Reverb.ReflectionsGain, 8.1093 + Slot->effect.Params.Reverb.LateReverbDelay, State); 8.1094 + 8.1095 + // Update the decorrelator. 8.1096 + UpdateDecorrelator(Slot->effect.Params.Reverb.Density, frequency, State); 8.1097 + 8.1098 + // Get the mixing matrix coefficients (x and y). 8.1099 + CalcMatrixCoeffs(Slot->effect.Params.Reverb.Diffusion, &x, &y); 8.1100 + // Then divide x into y to simplify the matrix calculation. 8.1101 + State->Late.MixCoeff = y / x; 8.1102 + 8.1103 + // If the HF limit parameter is flagged, calculate an appropriate limit 8.1104 + // based on the air absorption parameter. 8.1105 + hfRatio = Slot->effect.Params.Reverb.DecayHFRatio; 8.1106 + if(Slot->effect.Params.Reverb.DecayHFLimit && 8.1107 + Slot->effect.Params.Reverb.AirAbsorptionGainHF < 1.0f) 8.1108 + hfRatio = CalcLimitedHfRatio(hfRatio, 8.1109 + Slot->effect.Params.Reverb.AirAbsorptionGainHF, 8.1110 + Slot->effect.Params.Reverb.DecayTime); 8.1111 + 8.1112 + // Update the late lines. 8.1113 + UpdateLateLines(Slot->effect.Params.Reverb.Gain, Slot->effect.Params.Reverb.LateReverbGain, 8.1114 + x, Slot->effect.Params.Reverb.Density, Slot->effect.Params.Reverb.DecayTime, 8.1115 + Slot->effect.Params.Reverb.Diffusion, hfRatio, cw, frequency, State); 8.1116 + 8.1117 + // Update channel gains 8.1118 + gain = Slot->Gain; 8.1119 + gain *= aluSqrt(2.0f/Device->NumChan); 8.1120 + gain *= ReverbBoost; 8.1121 + for(index = 0;index < MAXCHANNELS;index++) 8.1122 + State->Gain[index] = 0.0f; 8.1123 + for(index = 0;index < Device->NumChan;index++) 8.1124 + { 8.1125 + enum Channel chan = Device->Speaker2Chan[index]; 8.1126 + State->Gain[chan] = gain; 8.1127 + } 8.1128 +} 8.1129 + 8.1130 +// This updates the EAX reverb state. This is called any time the EAX reverb 8.1131 +// effect is loaded into a slot. 8.1132 +static ALvoid EAXVerbUpdate(ALeffectState *effect, ALCcontext *Context, const ALeffectslot *Slot) 8.1133 +{ 8.1134 + ALverbState *State = (ALverbState*)effect; 8.1135 + ALuint frequency = Context->Device->Frequency; 8.1136 + ALfloat cw, x, y, hfRatio; 8.1137 + 8.1138 + // Calculate the master low-pass filter (from the master effect HF gain). 8.1139 + cw = CalcI3DL2HFreq(Slot->effect.Params.Reverb.HFReference, frequency); 8.1140 + // This is done with 2 chained 1-pole filters, so no need to square g. 8.1141 + State->LpFilter.coeff = lpCoeffCalc(Slot->effect.Params.Reverb.GainHF, cw); 8.1142 + 8.1143 + // Update the modulator line. 8.1144 + UpdateModulator(Slot->effect.Params.Reverb.ModulationTime, 8.1145 + Slot->effect.Params.Reverb.ModulationDepth, 8.1146 + frequency, State); 8.1147 + 8.1148 + // Update the initial effect delay. 8.1149 + UpdateDelayLine(Slot->effect.Params.Reverb.ReflectionsDelay, 8.1150 + Slot->effect.Params.Reverb.LateReverbDelay, 8.1151 + frequency, State); 8.1152 + 8.1153 + // Update the early lines. 8.1154 + UpdateEarlyLines(Slot->effect.Params.Reverb.Gain, 8.1155 + Slot->effect.Params.Reverb.ReflectionsGain, 8.1156 + Slot->effect.Params.Reverb.LateReverbDelay, State); 8.1157 + 8.1158 + // Update the decorrelator. 8.1159 + UpdateDecorrelator(Slot->effect.Params.Reverb.Density, frequency, State); 8.1160 + 8.1161 + // Get the mixing matrix coefficients (x and y). 8.1162 + CalcMatrixCoeffs(Slot->effect.Params.Reverb.Diffusion, &x, &y); 8.1163 + // Then divide x into y to simplify the matrix calculation. 8.1164 + State->Late.MixCoeff = y / x; 8.1165 + 8.1166 + // If the HF limit parameter is flagged, calculate an appropriate limit 8.1167 + // based on the air absorption parameter. 8.1168 + hfRatio = Slot->effect.Params.Reverb.DecayHFRatio; 8.1169 + if(Slot->effect.Params.Reverb.DecayHFLimit && 8.1170 + Slot->effect.Params.Reverb.AirAbsorptionGainHF < 1.0f) 8.1171 + hfRatio = CalcLimitedHfRatio(hfRatio, 8.1172 + Slot->effect.Params.Reverb.AirAbsorptionGainHF, 8.1173 + Slot->effect.Params.Reverb.DecayTime); 8.1174 + 8.1175 + // Update the late lines. 8.1176 + UpdateLateLines(Slot->effect.Params.Reverb.Gain, Slot->effect.Params.Reverb.LateReverbGain, 8.1177 + x, Slot->effect.Params.Reverb.Density, Slot->effect.Params.Reverb.DecayTime, 8.1178 + Slot->effect.Params.Reverb.Diffusion, hfRatio, cw, frequency, State); 8.1179 + 8.1180 + // Update the echo line. 8.1181 + UpdateEchoLine(Slot->effect.Params.Reverb.Gain, Slot->effect.Params.Reverb.LateReverbGain, 8.1182 + Slot->effect.Params.Reverb.EchoTime, Slot->effect.Params.Reverb.DecayTime, 8.1183 + Slot->effect.Params.Reverb.Diffusion, Slot->effect.Params.Reverb.EchoDepth, 8.1184 + hfRatio, cw, frequency, State); 8.1185 + 8.1186 + // Update early and late 3D panning. 8.1187 + Update3DPanning(Context->Device, Slot->effect.Params.Reverb.ReflectionsPan, 8.1188 + Slot->effect.Params.Reverb.LateReverbPan, Slot->Gain, State); 8.1189 +} 8.1190 + 8.1191 +// This processes the reverb state, given the input samples and an output 8.1192 +// buffer. 8.1193 +static ALvoid VerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 8.1194 +{ 8.1195 + ALverbState *State = (ALverbState*)effect; 8.1196 + ALuint index; 8.1197 + ALfloat early[4], late[4], out[4]; 8.1198 + const ALfloat *panGain = State->Gain; 8.1199 + (void)Slot; 8.1200 + 8.1201 + for(index = 0;index < SamplesToDo;index++) 8.1202 + { 8.1203 + // Process reverb for this sample. 8.1204 + VerbPass(State, SamplesIn[index], early, late); 8.1205 + 8.1206 + // Mix early reflections and late reverb. 8.1207 + out[0] = (early[0] + late[0]); 8.1208 + out[1] = (early[1] + late[1]); 8.1209 + out[2] = (early[2] + late[2]); 8.1210 + out[3] = (early[3] + late[3]); 8.1211 + 8.1212 + // Output the results. 8.1213 + SamplesOut[index][FRONT_LEFT] += panGain[FRONT_LEFT] * out[0]; 8.1214 + SamplesOut[index][FRONT_RIGHT] += panGain[FRONT_RIGHT] * out[1]; 8.1215 + SamplesOut[index][FRONT_CENTER] += panGain[FRONT_CENTER] * out[3]; 8.1216 + SamplesOut[index][SIDE_LEFT] += panGain[SIDE_LEFT] * out[0]; 8.1217 + SamplesOut[index][SIDE_RIGHT] += panGain[SIDE_RIGHT] * out[1]; 8.1218 + SamplesOut[index][BACK_LEFT] += panGain[BACK_LEFT] * out[0]; 8.1219 + SamplesOut[index][BACK_RIGHT] += panGain[BACK_RIGHT] * out[1]; 8.1220 + SamplesOut[index][BACK_CENTER] += panGain[BACK_CENTER] * out[2]; 8.1221 + } 8.1222 +} 8.1223 + 8.1224 +// This processes the EAX reverb state, given the input samples and an output 8.1225 +// buffer. 8.1226 +static ALvoid EAXVerbProcess(ALeffectState *effect, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 8.1227 +{ 8.1228 + ALverbState *State = (ALverbState*)effect; 8.1229 + ALuint index; 8.1230 + ALfloat early[4], late[4]; 8.1231 + (void)Slot; 8.1232 + 8.1233 + for(index = 0;index < SamplesToDo;index++) 8.1234 + { 8.1235 + // Process reverb for this sample. 8.1236 + EAXVerbPass(State, SamplesIn[index], early, late); 8.1237 + 8.1238 + // Unfortunately, while the number and configuration of gains for 8.1239 + // panning adjust according to MAXCHANNELS, the output from the 8.1240 + // reverb engine is not so scalable. 8.1241 + SamplesOut[index][FRONT_LEFT] += 8.1242 + (State->Early.PanGain[FRONT_LEFT]*early[0] + 8.1243 + State->Late.PanGain[FRONT_LEFT]*late[0]); 8.1244 + SamplesOut[index][FRONT_RIGHT] += 8.1245 + (State->Early.PanGain[FRONT_RIGHT]*early[1] + 8.1246 + State->Late.PanGain[FRONT_RIGHT]*late[1]); 8.1247 + SamplesOut[index][FRONT_CENTER] += 8.1248 + (State->Early.PanGain[FRONT_CENTER]*early[3] + 8.1249 + State->Late.PanGain[FRONT_CENTER]*late[3]); 8.1250 + SamplesOut[index][SIDE_LEFT] += 8.1251 + (State->Early.PanGain[SIDE_LEFT]*early[0] + 8.1252 + State->Late.PanGain[SIDE_LEFT]*late[0]); 8.1253 + SamplesOut[index][SIDE_RIGHT] += 8.1254 + (State->Early.PanGain[SIDE_RIGHT]*early[1] + 8.1255 + State->Late.PanGain[SIDE_RIGHT]*late[1]); 8.1256 + SamplesOut[index][BACK_LEFT] += 8.1257 + (State->Early.PanGain[BACK_LEFT]*early[0] + 8.1258 + State->Late.PanGain[BACK_LEFT]*late[0]); 8.1259 + SamplesOut[index][BACK_RIGHT] += 8.1260 + (State->Early.PanGain[BACK_RIGHT]*early[1] + 8.1261 + State->Late.PanGain[BACK_RIGHT]*late[1]); 8.1262 + SamplesOut[index][BACK_CENTER] += 8.1263 + (State->Early.PanGain[BACK_CENTER]*early[2] + 8.1264 + State->Late.PanGain[BACK_CENTER]*late[2]); 8.1265 + } 8.1266 +} 8.1267 + 8.1268 +// This creates the reverb state. It should be called only when the reverb 8.1269 +// effect is loaded into a slot that doesn't already have a reverb effect. 8.1270 +ALeffectState *VerbCreate(void) 8.1271 +{ 8.1272 + ALverbState *State = NULL; 8.1273 + ALuint index; 8.1274 + 8.1275 + State = malloc(sizeof(ALverbState)); 8.1276 + if(!State) 8.1277 + return NULL; 8.1278 + 8.1279 + State->state.Destroy = VerbDestroy; 8.1280 + State->state.DeviceUpdate = VerbDeviceUpdate; 8.1281 + State->state.Update = VerbUpdate; 8.1282 + State->state.Process = VerbProcess; 8.1283 + 8.1284 + State->TotalSamples = 0; 8.1285 + State->SampleBuffer = NULL; 8.1286 + 8.1287 + State->LpFilter.coeff = 0.0f; 8.1288 + State->LpFilter.history[0] = 0.0f; 8.1289 + State->LpFilter.history[1] = 0.0f; 8.1290 + 8.1291 + State->Mod.Delay.Mask = 0; 8.1292 + State->Mod.Delay.Line = NULL; 8.1293 + State->Mod.Index = 0; 8.1294 + State->Mod.Range = 1; 8.1295 + State->Mod.Depth = 0.0f; 8.1296 + State->Mod.Coeff = 0.0f; 8.1297 + State->Mod.Filter = 0.0f; 8.1298 + 8.1299 + State->Delay.Mask = 0; 8.1300 + State->Delay.Line = NULL; 8.1301 + State->DelayTap[0] = 0; 8.1302 + State->DelayTap[1] = 0; 8.1303 + 8.1304 + State->Early.Gain = 0.0f; 8.1305 + for(index = 0;index < 4;index++) 8.1306 + { 8.1307 + State->Early.Coeff[index] = 0.0f; 8.1308 + State->Early.Delay[index].Mask = 0; 8.1309 + State->Early.Delay[index].Line = NULL; 8.1310 + State->Early.Offset[index] = 0; 8.1311 + } 8.1312 + 8.1313 + State->Decorrelator.Mask = 0; 8.1314 + State->Decorrelator.Line = NULL; 8.1315 + State->DecoTap[0] = 0; 8.1316 + State->DecoTap[1] = 0; 8.1317 + State->DecoTap[2] = 0; 8.1318 + 8.1319 + State->Late.Gain = 0.0f; 8.1320 + State->Late.DensityGain = 0.0f; 8.1321 + State->Late.ApFeedCoeff = 0.0f; 8.1322 + State->Late.MixCoeff = 0.0f; 8.1323 + for(index = 0;index < 4;index++) 8.1324 + { 8.1325 + State->Late.ApCoeff[index] = 0.0f; 8.1326 + State->Late.ApDelay[index].Mask = 0; 8.1327 + State->Late.ApDelay[index].Line = NULL; 8.1328 + State->Late.ApOffset[index] = 0; 8.1329 + 8.1330 + State->Late.Coeff[index] = 0.0f; 8.1331 + State->Late.Delay[index].Mask = 0; 8.1332 + State->Late.Delay[index].Line = NULL; 8.1333 + State->Late.Offset[index] = 0; 8.1334 + 8.1335 + State->Late.LpCoeff[index] = 0.0f; 8.1336 + State->Late.LpSample[index] = 0.0f; 8.1337 + } 8.1338 + 8.1339 + for(index = 0;index < MAXCHANNELS;index++) 8.1340 + { 8.1341 + State->Early.PanGain[index] = 0.0f; 8.1342 + State->Late.PanGain[index] = 0.0f; 8.1343 + } 8.1344 + 8.1345 + State->Echo.DensityGain = 0.0f; 8.1346 + State->Echo.Delay.Mask = 0; 8.1347 + State->Echo.Delay.Line = NULL; 8.1348 + State->Echo.ApDelay.Mask = 0; 8.1349 + State->Echo.ApDelay.Line = NULL; 8.1350 + State->Echo.Coeff = 0.0f; 8.1351 + State->Echo.ApFeedCoeff = 0.0f; 8.1352 + State->Echo.ApCoeff = 0.0f; 8.1353 + State->Echo.Offset = 0; 8.1354 + State->Echo.ApOffset = 0; 8.1355 + State->Echo.LpCoeff = 0.0f; 8.1356 + State->Echo.LpSample = 0.0f; 8.1357 + State->Echo.MixCoeff[0] = 0.0f; 8.1358 + State->Echo.MixCoeff[1] = 0.0f; 8.1359 + 8.1360 + State->Offset = 0; 8.1361 + 8.1362 + State->Gain = State->Late.PanGain; 8.1363 + 8.1364 + return &State->state; 8.1365 +} 8.1366 + 8.1367 +ALeffectState *EAXVerbCreate(void) 8.1368 +{ 8.1369 + ALeffectState *State = VerbCreate(); 8.1370 + if(State && EmulateEAXReverb == AL_FALSE) 8.1371 + { 8.1372 + State->DeviceUpdate = EAXVerbDeviceUpdate; 8.1373 + State->Update = EAXVerbUpdate; 8.1374 + State->Process = EAXVerbProcess; 8.1375 + } 8.1376 + return State; 8.1377 +}
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/Alc/alcRing.c Tue Oct 25 13:02:31 2011 -0700 9.3 @@ -0,0 +1,127 @@ 9.4 +/** 9.5 + * OpenAL cross platform audio library 9.6 + * Copyright (C) 1999-2007 by authors. 9.7 + * This library is free software; you can redistribute it and/or 9.8 + * modify it under the terms of the GNU Library General Public 9.9 + * License as published by the Free Software Foundation; either 9.10 + * version 2 of the License, or (at your option) any later version. 9.11 + * 9.12 + * This library is distributed in the hope that it will be useful, 9.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9.15 + * Library General Public License for more details. 9.16 + * 9.17 + * You should have received a copy of the GNU Library General Public 9.18 + * License along with this library; if not, write to the 9.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 9.20 + * Boston, MA 02111-1307, USA. 9.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 9.22 + */ 9.23 + 9.24 +#include "config.h" 9.25 + 9.26 +#include <string.h> 9.27 +#include <stdlib.h> 9.28 + 9.29 +#include "alMain.h" 9.30 + 9.31 + 9.32 +struct RingBuffer { 9.33 + ALubyte *mem; 9.34 + 9.35 + ALsizei frame_size; 9.36 + ALsizei length; 9.37 + ALint read_pos; 9.38 + ALint write_pos; 9.39 + 9.40 + CRITICAL_SECTION cs; 9.41 +}; 9.42 + 9.43 + 9.44 +RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length) 9.45 +{ 9.46 + RingBuffer *ring = calloc(1, sizeof(*ring) + ((length+1) * frame_size)); 9.47 + if(ring) 9.48 + { 9.49 + ring->mem = (ALubyte*)(ring+1); 9.50 + 9.51 + ring->frame_size = frame_size; 9.52 + ring->length = length+1; 9.53 + ring->read_pos = 0; 9.54 + ring->write_pos = 0; 9.55 + 9.56 + InitializeCriticalSection(&ring->cs); 9.57 + } 9.58 + return ring; 9.59 +} 9.60 + 9.61 +void DestroyRingBuffer(RingBuffer *ring) 9.62 +{ 9.63 + if(ring) 9.64 + { 9.65 + DeleteCriticalSection(&ring->cs); 9.66 + free(ring); 9.67 + } 9.68 +} 9.69 + 9.70 +ALsizei RingBufferSize(RingBuffer *ring) 9.71 +{ 9.72 + ALsizei s; 9.73 + 9.74 + EnterCriticalSection(&ring->cs); 9.75 + s = (ring->write_pos-ring->read_pos+ring->length) % ring->length; 9.76 + LeaveCriticalSection(&ring->cs); 9.77 + 9.78 + return s; 9.79 +} 9.80 + 9.81 +void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len) 9.82 +{ 9.83 + int remain; 9.84 + 9.85 + EnterCriticalSection(&ring->cs); 9.86 + 9.87 + remain = (ring->read_pos-ring->write_pos-1+ring->length) % ring->length; 9.88 + if(remain < len) len = remain; 9.89 + 9.90 + if(len > 0) 9.91 + { 9.92 + remain = ring->length - ring->write_pos; 9.93 + if(remain < len) 9.94 + { 9.95 + memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, 9.96 + remain*ring->frame_size); 9.97 + memcpy(ring->mem, data+(remain*ring->frame_size), 9.98 + (len-remain)*ring->frame_size); 9.99 + } 9.100 + else 9.101 + memcpy(ring->mem+(ring->write_pos*ring->frame_size), data, 9.102 + len*ring->frame_size); 9.103 + 9.104 + ring->write_pos += len; 9.105 + ring->write_pos %= ring->length; 9.106 + } 9.107 + 9.108 + LeaveCriticalSection(&ring->cs); 9.109 +} 9.110 + 9.111 +void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len) 9.112 +{ 9.113 + int remain; 9.114 + 9.115 + EnterCriticalSection(&ring->cs); 9.116 + 9.117 + remain = ring->length - ring->read_pos; 9.118 + if(remain < len) 9.119 + { 9.120 + memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), remain*ring->frame_size); 9.121 + memcpy(data+(remain*ring->frame_size), ring->mem, (len-remain)*ring->frame_size); 9.122 + } 9.123 + else 9.124 + memcpy(data, ring->mem+(ring->read_pos*ring->frame_size), len*ring->frame_size); 9.125 + 9.126 + ring->read_pos += len; 9.127 + ring->read_pos %= ring->length; 9.128 + 9.129 + LeaveCriticalSection(&ring->cs); 9.130 +}
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/Alc/alcThread.c Tue Oct 25 13:02:31 2011 -0700 10.3 @@ -0,0 +1,128 @@ 10.4 +/** 10.5 + * OpenAL cross platform audio library 10.6 + * Copyright (C) 1999-2007 by authors. 10.7 + * This library is free software; you can redistribute it and/or 10.8 + * modify it under the terms of the GNU Library General Public 10.9 + * License as published by the Free Software Foundation; either 10.10 + * version 2 of the License, or (at your option) any later version. 10.11 + * 10.12 + * This library is distributed in the hope that it will be useful, 10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10.15 + * Library General Public License for more details. 10.16 + * 10.17 + * You should have received a copy of the GNU Library General Public 10.18 + * License along with this library; if not, write to the 10.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 10.20 + * Boston, MA 02111-1307, USA. 10.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 10.22 + */ 10.23 + 10.24 +#include "config.h" 10.25 + 10.26 +#include <stdlib.h> 10.27 + 10.28 +#include "alMain.h" 10.29 +#include "alThunk.h" 10.30 + 10.31 + 10.32 +#ifdef _WIN32 10.33 + 10.34 +typedef struct { 10.35 + ALuint (*func)(ALvoid*); 10.36 + ALvoid *ptr; 10.37 + HANDLE thread; 10.38 +} ThreadInfo; 10.39 + 10.40 +static DWORD CALLBACK StarterFunc(void *ptr) 10.41 +{ 10.42 + ThreadInfo *inf = (ThreadInfo*)ptr; 10.43 + ALint ret; 10.44 + 10.45 + ret = inf->func(inf->ptr); 10.46 + ExitThread((DWORD)ret); 10.47 + 10.48 + return (DWORD)ret; 10.49 +} 10.50 + 10.51 +ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr) 10.52 +{ 10.53 + DWORD dummy; 10.54 + ThreadInfo *inf = malloc(sizeof(ThreadInfo)); 10.55 + if(!inf) return 0; 10.56 + 10.57 + inf->func = func; 10.58 + inf->ptr = ptr; 10.59 + 10.60 + inf->thread = CreateThread(NULL, 0, StarterFunc, inf, 0, &dummy); 10.61 + if(!inf->thread) 10.62 + { 10.63 + free(inf); 10.64 + return NULL; 10.65 + } 10.66 + 10.67 + return inf; 10.68 +} 10.69 + 10.70 +ALuint StopThread(ALvoid *thread) 10.71 +{ 10.72 + ThreadInfo *inf = thread; 10.73 + DWORD ret = 0; 10.74 + 10.75 + WaitForSingleObject(inf->thread, INFINITE); 10.76 + GetExitCodeThread(inf->thread, &ret); 10.77 + CloseHandle(inf->thread); 10.78 + 10.79 + free(inf); 10.80 + 10.81 + return (ALuint)ret; 10.82 +} 10.83 + 10.84 +#else 10.85 + 10.86 +#include <pthread.h> 10.87 + 10.88 +typedef struct { 10.89 + ALuint (*func)(ALvoid*); 10.90 + ALvoid *ptr; 10.91 + ALuint ret; 10.92 + pthread_t thread; 10.93 +} ThreadInfo; 10.94 + 10.95 +static void *StarterFunc(void *ptr) 10.96 +{ 10.97 + ThreadInfo *inf = (ThreadInfo*)ptr; 10.98 + inf->ret = inf->func(inf->ptr); 10.99 + return NULL; 10.100 +} 10.101 + 10.102 +ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr) 10.103 +{ 10.104 + ThreadInfo *inf = malloc(sizeof(ThreadInfo)); 10.105 + if(!inf) return NULL; 10.106 + 10.107 + inf->func = func; 10.108 + inf->ptr = ptr; 10.109 + if(pthread_create(&inf->thread, NULL, StarterFunc, inf) != 0) 10.110 + { 10.111 + free(inf); 10.112 + return NULL; 10.113 + } 10.114 + 10.115 + return inf; 10.116 +} 10.117 + 10.118 +ALuint StopThread(ALvoid *thread) 10.119 +{ 10.120 + ThreadInfo *inf = thread; 10.121 + ALuint ret; 10.122 + 10.123 + pthread_join(inf->thread, NULL); 10.124 + ret = inf->ret; 10.125 + 10.126 + free(inf); 10.127 + 10.128 + return ret; 10.129 +} 10.130 + 10.131 +#endif
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 11.2 +++ b/Alc/backends/alsa.c Tue Oct 25 13:02:31 2011 -0700 11.3 @@ -0,0 +1,1138 @@ 11.4 +/** 11.5 + * OpenAL cross platform audio library 11.6 + * Copyright (C) 1999-2007 by authors. 11.7 + * This library is free software; you can redistribute it and/or 11.8 + * modify it under the terms of the GNU Library General Public 11.9 + * License as published by the Free Software Foundation; either 11.10 + * version 2 of the License, or (at your option) any later version. 11.11 + * 11.12 + * This library is distributed in the hope that it will be useful, 11.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11.15 + * Library General Public License for more details. 11.16 + * 11.17 + * You should have received a copy of the GNU Library General Public 11.18 + * License along with this library; if not, write to the 11.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 11.20 + * Boston, MA 02111-1307, USA. 11.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 11.22 + */ 11.23 + 11.24 +#include "config.h" 11.25 + 11.26 +#include <stdlib.h> 11.27 +#include <stdio.h> 11.28 +#include <memory.h> 11.29 + 11.30 +#include "alMain.h" 11.31 + 11.32 +#include <alsa/asoundlib.h> 11.33 + 11.34 + 11.35 +static const ALCchar alsaDevice[] = "ALSA Default"; 11.36 + 11.37 + 11.38 +static void *alsa_handle; 11.39 +#ifdef HAVE_DYNLOAD 11.40 +#define MAKE_FUNC(f) static typeof(f) * p##f 11.41 +MAKE_FUNC(snd_strerror); 11.42 +MAKE_FUNC(snd_pcm_open); 11.43 +MAKE_FUNC(snd_pcm_close); 11.44 +MAKE_FUNC(snd_pcm_nonblock); 11.45 +MAKE_FUNC(snd_pcm_frames_to_bytes); 11.46 +MAKE_FUNC(snd_pcm_bytes_to_frames); 11.47 +MAKE_FUNC(snd_pcm_hw_params_malloc); 11.48 +MAKE_FUNC(snd_pcm_hw_params_free); 11.49 +MAKE_FUNC(snd_pcm_hw_params_any); 11.50 +MAKE_FUNC(snd_pcm_hw_params_set_access); 11.51 +MAKE_FUNC(snd_pcm_hw_params_set_format); 11.52 +MAKE_FUNC(snd_pcm_hw_params_set_channels); 11.53 +MAKE_FUNC(snd_pcm_hw_params_set_periods_near); 11.54 +MAKE_FUNC(snd_pcm_hw_params_set_rate_near); 11.55 +MAKE_FUNC(snd_pcm_hw_params_set_rate); 11.56 +MAKE_FUNC(snd_pcm_hw_params_set_rate_resample); 11.57 +MAKE_FUNC(snd_pcm_hw_params_set_buffer_time_near); 11.58 +MAKE_FUNC(snd_pcm_hw_params_set_period_time_near); 11.59 +MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_near); 11.60 +MAKE_FUNC(snd_pcm_hw_params_set_period_size_near); 11.61 +MAKE_FUNC(snd_pcm_hw_params_set_buffer_size_min); 11.62 +MAKE_FUNC(snd_pcm_hw_params_get_buffer_size); 11.63 +MAKE_FUNC(snd_pcm_hw_params_get_period_size); 11.64 +MAKE_FUNC(snd_pcm_hw_params_get_access); 11.65 +MAKE_FUNC(snd_pcm_hw_params_get_periods); 11.66 +MAKE_FUNC(snd_pcm_hw_params); 11.67 +MAKE_FUNC(snd_pcm_sw_params_malloc); 11.68 +MAKE_FUNC(snd_pcm_sw_params_current); 11.69 +MAKE_FUNC(snd_pcm_sw_params_set_avail_min); 11.70 +MAKE_FUNC(snd_pcm_sw_params); 11.71 +MAKE_FUNC(snd_pcm_sw_params_free); 11.72 +MAKE_FUNC(snd_pcm_prepare); 11.73 +MAKE_FUNC(snd_pcm_start); 11.74 +MAKE_FUNC(snd_pcm_resume); 11.75 +MAKE_FUNC(snd_pcm_wait); 11.76 +MAKE_FUNC(snd_pcm_state); 11.77 +MAKE_FUNC(snd_pcm_avail_update); 11.78 +MAKE_FUNC(snd_pcm_areas_silence); 11.79 +MAKE_FUNC(snd_pcm_mmap_begin); 11.80 +MAKE_FUNC(snd_pcm_mmap_commit); 11.81 +MAKE_FUNC(snd_pcm_readi); 11.82 +MAKE_FUNC(snd_pcm_writei); 11.83 +MAKE_FUNC(snd_pcm_drain); 11.84 +MAKE_FUNC(snd_pcm_recover); 11.85 +MAKE_FUNC(snd_pcm_info_malloc); 11.86 +MAKE_FUNC(snd_pcm_info_free); 11.87 +MAKE_FUNC(snd_pcm_info_set_device); 11.88 +MAKE_FUNC(snd_pcm_info_set_subdevice); 11.89 +MAKE_FUNC(snd_pcm_info_set_stream); 11.90 +MAKE_FUNC(snd_pcm_info_get_name); 11.91 +MAKE_FUNC(snd_ctl_pcm_next_device); 11.92 +MAKE_FUNC(snd_ctl_pcm_info); 11.93 +MAKE_FUNC(snd_ctl_open); 11.94 +MAKE_FUNC(snd_ctl_close); 11.95 +MAKE_FUNC(snd_ctl_card_info_malloc); 11.96 +MAKE_FUNC(snd_ctl_card_info_free); 11.97 +MAKE_FUNC(snd_ctl_card_info); 11.98 +MAKE_FUNC(snd_ctl_card_info_get_name); 11.99 +MAKE_FUNC(snd_ctl_card_info_get_id); 11.100 +MAKE_FUNC(snd_card_next); 11.101 +#undef MAKE_FUNC 11.102 + 11.103 +#define snd_strerror psnd_strerror 11.104 +#define snd_pcm_open psnd_pcm_open 11.105 +#define snd_pcm_close psnd_pcm_close 11.106 +#define snd_pcm_nonblock psnd_pcm_nonblock 11.107 +#define snd_pcm_frames_to_bytes psnd_pcm_frames_to_bytes 11.108 +#define snd_pcm_bytes_to_frames psnd_pcm_bytes_to_frames 11.109 +#define snd_pcm_hw_params_malloc psnd_pcm_hw_params_malloc 11.110 +#define snd_pcm_hw_params_free psnd_pcm_hw_params_free 11.111 +#define snd_pcm_hw_params_any psnd_pcm_hw_params_any 11.112 +#define snd_pcm_hw_params_set_access psnd_pcm_hw_params_set_access 11.113 +#define snd_pcm_hw_params_set_format psnd_pcm_hw_params_set_format 11.114 +#define snd_pcm_hw_params_set_channels psnd_pcm_hw_params_set_channels 11.115 +#define snd_pcm_hw_params_set_periods_near psnd_pcm_hw_params_set_periods_near 11.116 +#define snd_pcm_hw_params_set_rate_near psnd_pcm_hw_params_set_rate_near 11.117 +#define snd_pcm_hw_params_set_rate psnd_pcm_hw_params_set_rate 11.118 +#define snd_pcm_hw_params_set_rate_resample psnd_pcm_hw_params_set_rate_resample 11.119 +#define snd_pcm_hw_params_set_buffer_time_near psnd_pcm_hw_params_set_buffer_time_near 11.120 +#define snd_pcm_hw_params_set_period_time_near psnd_pcm_hw_params_set_period_time_near 11.121 +#define snd_pcm_hw_params_set_buffer_size_near psnd_pcm_hw_params_set_buffer_size_near 11.122 +#define snd_pcm_hw_params_set_period_size_near psnd_pcm_hw_params_set_period_size_near 11.123 +#define snd_pcm_hw_params_set_buffer_size_min psnd_pcm_hw_params_set_buffer_size_min 11.124 +#define snd_pcm_hw_params_get_buffer_size psnd_pcm_hw_params_get_buffer_size 11.125 +#define snd_pcm_hw_params_get_period_size psnd_pcm_hw_params_get_period_size 11.126 +#define snd_pcm_hw_params_get_access psnd_pcm_hw_params_get_access 11.127 +#define snd_pcm_hw_params_get_periods psnd_pcm_hw_params_get_periods 11.128 +#define snd_pcm_hw_params psnd_pcm_hw_params 11.129 +#define snd_pcm_sw_params_malloc psnd_pcm_sw_params_malloc 11.130 +#define snd_pcm_sw_params_current psnd_pcm_sw_params_current 11.131 +#define snd_pcm_sw_params_set_avail_min psnd_pcm_sw_params_set_avail_min 11.132 +#define snd_pcm_sw_params psnd_pcm_sw_params 11.133 +#define snd_pcm_sw_params_free psnd_pcm_sw_params_free 11.134 +#define snd_pcm_prepare psnd_pcm_prepare 11.135 +#define snd_pcm_start psnd_pcm_start 11.136 +#define snd_pcm_resume psnd_pcm_resume 11.137 +#define snd_pcm_wait psnd_pcm_wait 11.138 +#define snd_pcm_state psnd_pcm_state 11.139 +#define snd_pcm_avail_update psnd_pcm_avail_update 11.140 +#define snd_pcm_areas_silence psnd_pcm_areas_silence 11.141 +#define snd_pcm_mmap_begin psnd_pcm_mmap_begin 11.142 +#define snd_pcm_mmap_commit psnd_pcm_mmap_commit 11.143 +#define snd_pcm_readi psnd_pcm_readi 11.144 +#define snd_pcm_writei psnd_pcm_writei 11.145 +#define snd_pcm_drain psnd_pcm_drain 11.146 +#define snd_pcm_recover psnd_pcm_recover 11.147 +#define snd_pcm_info_malloc psnd_pcm_info_malloc 11.148 +#define snd_pcm_info_free psnd_pcm_info_free 11.149 +#define snd_pcm_info_set_device psnd_pcm_info_set_device 11.150 +#define snd_pcm_info_set_subdevice psnd_pcm_info_set_subdevice 11.151 +#define snd_pcm_info_set_stream psnd_pcm_info_set_stream 11.152 +#define snd_pcm_info_get_name psnd_pcm_info_get_name 11.153 +#define snd_ctl_pcm_next_device psnd_ctl_pcm_next_device 11.154 +#define snd_ctl_pcm_info psnd_ctl_pcm_info 11.155 +#define snd_ctl_open psnd_ctl_open 11.156 +#define snd_ctl_close psnd_ctl_close 11.157 +#define snd_ctl_card_info_malloc psnd_ctl_card_info_malloc 11.158 +#define snd_ctl_card_info_free psnd_ctl_card_info_free 11.159 +#define snd_ctl_card_info psnd_ctl_card_info 11.160 +#define snd_ctl_card_info_get_name psnd_ctl_card_info_get_name 11.161 +#define snd_ctl_card_info_get_id psnd_ctl_card_info_get_id 11.162 +#define snd_card_next psnd_card_next 11.163 +#endif 11.164 + 11.165 + 11.166 +static ALCboolean alsa_load(void) 11.167 +{ 11.168 + if(!alsa_handle) 11.169 + { 11.170 +#ifdef HAVE_DYNLOAD 11.171 + alsa_handle = LoadLib("libasound.so.2"); 11.172 + if(!alsa_handle) 11.173 + return ALC_FALSE; 11.174 + 11.175 +#define LOAD_FUNC(f) do { \ 11.176 + p##f = GetSymbol(alsa_handle, #f); \ 11.177 + if(p##f == NULL) { \ 11.178 + CloseLib(alsa_handle); \ 11.179 + alsa_handle = NULL; \ 11.180 + return ALC_FALSE; \ 11.181 + } \ 11.182 +} while(0) 11.183 + LOAD_FUNC(snd_strerror); 11.184 + LOAD_FUNC(snd_pcm_open); 11.185 + LOAD_FUNC(snd_pcm_close); 11.186 + LOAD_FUNC(snd_pcm_nonblock); 11.187 + LOAD_FUNC(snd_pcm_frames_to_bytes); 11.188 + LOAD_FUNC(snd_pcm_bytes_to_frames); 11.189 + LOAD_FUNC(snd_pcm_hw_params_malloc); 11.190 + LOAD_FUNC(snd_pcm_hw_params_free); 11.191 + LOAD_FUNC(snd_pcm_hw_params_any); 11.192 + LOAD_FUNC(snd_pcm_hw_params_set_access); 11.193 + LOAD_FUNC(snd_pcm_hw_params_set_format); 11.194 + LOAD_FUNC(snd_pcm_hw_params_set_channels); 11.195 + LOAD_FUNC(snd_pcm_hw_params_set_periods_near); 11.196 + LOAD_FUNC(snd_pcm_hw_params_set_rate_near); 11.197 + LOAD_FUNC(snd_pcm_hw_params_set_rate); 11.198 + LOAD_FUNC(snd_pcm_hw_params_set_rate_resample); 11.199 + LOAD_FUNC(snd_pcm_hw_params_set_buffer_time_near); 11.200 + LOAD_FUNC(snd_pcm_hw_params_set_period_time_near); 11.201 + LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_near); 11.202 + LOAD_FUNC(snd_pcm_hw_params_set_buffer_size_min); 11.203 + LOAD_FUNC(snd_pcm_hw_params_set_period_size_near); 11.204 + LOAD_FUNC(snd_pcm_hw_params_get_buffer_size); 11.205 + LOAD_FUNC(snd_pcm_hw_params_get_period_size); 11.206 + LOAD_FUNC(snd_pcm_hw_params_get_access); 11.207 + LOAD_FUNC(snd_pcm_hw_params_get_periods); 11.208 + LOAD_FUNC(snd_pcm_hw_params); 11.209 + LOAD_FUNC(snd_pcm_sw_params_malloc); 11.210 + LOAD_FUNC(snd_pcm_sw_params_current); 11.211 + LOAD_FUNC(snd_pcm_sw_params_set_avail_min); 11.212 + LOAD_FUNC(snd_pcm_sw_params); 11.213 + LOAD_FUNC(snd_pcm_sw_params_free); 11.214 + LOAD_FUNC(snd_pcm_prepare); 11.215 + LOAD_FUNC(snd_pcm_start); 11.216 + LOAD_FUNC(snd_pcm_resume); 11.217 + LOAD_FUNC(snd_pcm_wait); 11.218 + LOAD_FUNC(snd_pcm_state); 11.219 + LOAD_FUNC(snd_pcm_avail_update); 11.220 + LOAD_FUNC(snd_pcm_areas_silence); 11.221 + LOAD_FUNC(snd_pcm_mmap_begin); 11.222 + LOAD_FUNC(snd_pcm_mmap_commit); 11.223 + LOAD_FUNC(snd_pcm_readi); 11.224 + LOAD_FUNC(snd_pcm_writei); 11.225 + LOAD_FUNC(snd_pcm_drain); 11.226 + LOAD_FUNC(snd_pcm_recover); 11.227 + LOAD_FUNC(snd_pcm_info_malloc); 11.228 + LOAD_FUNC(snd_pcm_info_free); 11.229 + LOAD_FUNC(snd_pcm_info_set_device); 11.230 + LOAD_FUNC(snd_pcm_info_set_subdevice); 11.231 + LOAD_FUNC(snd_pcm_info_set_stream); 11.232 + LOAD_FUNC(snd_pcm_info_get_name); 11.233 + LOAD_FUNC(snd_ctl_pcm_next_device); 11.234 + LOAD_FUNC(snd_ctl_pcm_info); 11.235 + LOAD_FUNC(snd_ctl_open); 11.236 + LOAD_FUNC(snd_ctl_close); 11.237 + LOAD_FUNC(snd_ctl_card_info_malloc); 11.238 + LOAD_FUNC(snd_ctl_card_info_free); 11.239 + LOAD_FUNC(snd_ctl_card_info); 11.240 + LOAD_FUNC(snd_ctl_card_info_get_name); 11.241 + LOAD_FUNC(snd_ctl_card_info_get_id); 11.242 + LOAD_FUNC(snd_card_next); 11.243 +#undef LOAD_FUNC 11.244 +#else 11.245 + alsa_handle = (void*)0xDEADBEEF; 11.246 +#endif 11.247 + } 11.248 + return ALC_TRUE; 11.249 +} 11.250 + 11.251 + 11.252 +typedef struct { 11.253 + snd_pcm_t *pcmHandle; 11.254 + 11.255 + ALvoid *buffer; 11.256 + ALsizei size; 11.257 + 11.258 + ALboolean doCapture; 11.259 + RingBuffer *ring; 11.260 + 11.261 + volatile int killNow; 11.262 + ALvoid *thread; 11.263 +} alsa_data; 11.264 + 11.265 +typedef struct { 11.266 + ALCchar *name; 11.267 + char *card; 11.268 + int dev; 11.269 +} DevMap; 11.270 + 11.271 +static DevMap *allDevNameMap; 11.272 +static ALuint numDevNames; 11.273 +static DevMap *allCaptureDevNameMap; 11.274 +static ALuint numCaptureDevNames; 11.275 + 11.276 +static const char *device_prefix; 11.277 +static const char *capture_prefix; 11.278 + 11.279 + 11.280 +static DevMap *probe_devices(snd_pcm_stream_t stream, ALuint *count) 11.281 +{ 11.282 + snd_ctl_t *handle; 11.283 + int card, err, dev, idx; 11.284 + snd_ctl_card_info_t *info; 11.285 + snd_pcm_info_t *pcminfo; 11.286 + DevMap *DevList; 11.287 + char name[1024]; 11.288 + 11.289 + snd_ctl_card_info_malloc(&info); 11.290 + snd_pcm_info_malloc(&pcminfo); 11.291 + 11.292 + card = -1; 11.293 + if((err=snd_card_next(&card)) < 0) 11.294 + ERR("Failed to find a card: %s\n", snd_strerror(err)); 11.295 + 11.296 + DevList = malloc(sizeof(DevMap) * 1); 11.297 + DevList[0].name = strdup("ALSA Default"); 11.298 + DevList[0].card = NULL; 11.299 + DevList[0].dev = 0; 11.300 + idx = 1; 11.301 + while(card >= 0) 11.302 + { 11.303 + sprintf(name, "hw:%d", card); 11.304 + if((err = snd_ctl_open(&handle, name, 0)) < 0) 11.305 + { 11.306 + ERR("control open (%i): %s\n", card, snd_strerror(err)); 11.307 + goto next_card; 11.308 + } 11.309 + if((err = snd_ctl_card_info(handle, info)) < 0) 11.310 + { 11.311 + ERR("control hardware info (%i): %s\n", card, snd_strerror(err)); 11.312 + snd_ctl_close(handle); 11.313 + goto next_card; 11.314 + } 11.315 + 11.316 + dev = -1; 11.317 + while(1) 11.318 + { 11.319 + const char *cname, *dname, *cid; 11.320 + void *temp; 11.321 + 11.322 + if(snd_ctl_pcm_next_device(handle, &dev) < 0) 11.323 + ERR("snd_ctl_pcm_next_device failed\n"); 11.324 + if(dev < 0) 11.325 + break; 11.326 + 11.327 + snd_pcm_info_set_device(pcminfo, dev); 11.328 + snd_pcm_info_set_subdevice(pcminfo, 0); 11.329 + snd_pcm_info_set_stream(pcminfo, stream); 11.330 + if((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) { 11.331 + if(err != -ENOENT) 11.332 + ERR("control digital audio info (%i): %s\n", card, snd_strerror(err)); 11.333 + continue; 11.334 + } 11.335 + 11.336 + temp = realloc(DevList, sizeof(DevMap) * (idx+1)); 11.337 + if(temp) 11.338 + { 11.339 + DevList = temp; 11.340 + cname = snd_ctl_card_info_get_name(info); 11.341 + dname = snd_pcm_info_get_name(pcminfo); 11.342 + cid = snd_ctl_card_info_get_id(info); 11.343 + snprintf(name, sizeof(name), "%s, %s (CARD=%s,DEV=%d)", 11.344 + cname, dname, cid, dev); 11.345 + DevList[idx].name = strdup(name); 11.346 + DevList[idx].card = strdup(cid); 11.347 + DevList[idx].dev = dev; 11.348 + idx++; 11.349 + } 11.350 + } 11.351 + snd_ctl_close(handle); 11.352 + next_card: 11.353 + if(snd_card_next(&card) < 0) { 11.354 + ERR("snd_card_next failed\n"); 11.355 + break; 11.356 + } 11.357 + } 11.358 + 11.359 + snd_pcm_info_free(pcminfo); 11.360 + snd_ctl_card_info_free(info); 11.361 + 11.362 + *count = idx; 11.363 + return DevList; 11.364 +} 11.365 + 11.366 + 11.367 +static int xrun_recovery(snd_pcm_t *handle, int err) 11.368 +{ 11.369 + err = snd_pcm_recover(handle, err, 1); 11.370 + if(err < 0) 11.371 + ERR("recover failed: %s\n", snd_strerror(err)); 11.372 + return err; 11.373 +} 11.374 + 11.375 +static int verify_state(snd_pcm_t *handle) 11.376 +{ 11.377 + snd_pcm_state_t state = snd_pcm_state(handle); 11.378 + if(state == SND_PCM_STATE_DISCONNECTED) 11.379 + return -ENODEV; 11.380 + if(state == SND_PCM_STATE_XRUN) 11.381 + { 11.382 + int err = xrun_recovery(handle, -EPIPE); 11.383 + if(err < 0) return err; 11.384 + } 11.385 + else if(state == SND_PCM_STATE_SUSPENDED) 11.386 + { 11.387 + int err = xrun_recovery(handle, -ESTRPIPE); 11.388 + if(err < 0) return err; 11.389 + } 11.390 + 11.391 + return state; 11.392 +} 11.393 + 11.394 + 11.395 +static ALuint ALSAProc(ALvoid *ptr) 11.396 +{ 11.397 + ALCdevice *pDevice = (ALCdevice*)ptr; 11.398 + alsa_data *data = (alsa_data*)pDevice->ExtraData; 11.399 + const snd_pcm_channel_area_t *areas = NULL; 11.400 + snd_pcm_sframes_t avail, commitres; 11.401 + snd_pcm_uframes_t offset, frames; 11.402 + char *WritePtr; 11.403 + int err; 11.404 + 11.405 + SetRTPriority(); 11.406 + 11.407 + while(!data->killNow) 11.408 + { 11.409 + int state = verify_state(data->pcmHandle); 11.410 + if(state < 0) 11.411 + { 11.412 + ERR("Invalid state detected: %s\n", snd_strerror(state)); 11.413 + aluHandleDisconnect(pDevice); 11.414 + break; 11.415 + } 11.416 + 11.417 + avail = snd_pcm_avail_update(data->pcmHandle); 11.418 + if(avail < 0) 11.419 + { 11.420 + ERR("available update failed: %s\n", snd_strerror(avail)); 11.421 + continue; 11.422 + } 11.423 + 11.424 + // make sure there's frames to process 11.425 + if((snd_pcm_uframes_t)avail < pDevice->UpdateSize) 11.426 + { 11.427 + if(state != SND_PCM_STATE_RUNNING) 11.428 + { 11.429 + err = snd_pcm_start(data->pcmHandle); 11.430 + if(err < 0) 11.431 + { 11.432 + ERR("start failed: %s\n", snd_strerror(err)); 11.433 + continue; 11.434 + } 11.435 + } 11.436 + if(snd_pcm_wait(data->pcmHandle, 1000) == 0) 11.437 + ERR("Wait timeout... buffer size too low?\n"); 11.438 + continue; 11.439 + } 11.440 + avail -= avail%pDevice->UpdateSize; 11.441 + 11.442 + // it is possible that contiguous areas are smaller, thus we use a loop 11.443 + while(avail > 0) 11.444 + { 11.445 + frames = avail; 11.446 + 11.447 + err = snd_pcm_mmap_begin(data->pcmHandle, &areas, &offset, &frames); 11.448 + if(err < 0) 11.449 + { 11.450 + ERR("mmap begin error: %s\n", snd_strerror(err)); 11.451 + break; 11.452 + } 11.453 + 11.454 + WritePtr = (char*)areas->addr + (offset * areas->step / 8); 11.455 + aluMixData(pDevice, WritePtr, frames); 11.456 + 11.457 + commitres = snd_pcm_mmap_commit(data->pcmHandle, offset, frames); 11.458 + if(commitres < 0 || (commitres-frames) != 0) 11.459 + { 11.460 + ERR("mmap commit error: %s\n", 11.461 + snd_strerror(commitres >= 0 ? -EPIPE : commitres)); 11.462 + break; 11.463 + } 11.464 + 11.465 + avail -= frames; 11.466 + } 11.467 + } 11.468 + 11.469 + return 0; 11.470 +} 11.471 + 11.472 +static ALuint ALSANoMMapProc(ALvoid *ptr) 11.473 +{ 11.474 + ALCdevice *pDevice = (ALCdevice*)ptr; 11.475 + alsa_data *data = (alsa_data*)pDevice->ExtraData; 11.476 + snd_pcm_sframes_t avail; 11.477 + char *WritePtr; 11.478 + 11.479 + SetRTPriority(); 11.480 + 11.481 + while(!data->killNow) 11.482 + { 11.483 + int state = verify_state(data->pcmHandle); 11.484 + if(state < 0) 11.485 + { 11.486 + ERR("Invalid state detected: %s\n", snd_strerror(state)); 11.487 + aluHandleDisconnect(pDevice); 11.488 + break; 11.489 + } 11.490 + 11.491 + WritePtr = data->buffer; 11.492 + avail = data->size / snd_pcm_frames_to_bytes(data->pcmHandle, 1); 11.493 + aluMixData(pDevice, WritePtr, avail); 11.494 + 11.495 + while(avail > 0) 11.496 + { 11.497 + int ret = snd_pcm_writei(data->pcmHandle, WritePtr, avail); 11.498 + switch (ret) 11.499 + { 11.500 + case -EAGAIN: 11.501 + continue; 11.502 + case -ESTRPIPE: 11.503 + case -EPIPE: 11.504 + case -EINTR: 11.505 + ret = snd_pcm_recover(data->pcmHandle, ret, 1); 11.506 + if(ret < 0) 11.507 + avail = 0; 11.508 + break; 11.509 + default: 11.510 + if (ret >= 0) 11.511 + { 11.512 + WritePtr += snd_pcm_frames_to_bytes(data->pcmHandle, ret); 11.513 + avail -= ret; 11.514 + } 11.515 + break; 11.516 + } 11.517 + if (ret < 0) 11.518 + { 11.519 + ret = snd_pcm_prepare(data->pcmHandle); 11.520 + if(ret < 0) 11.521 + break; 11.522 + } 11.523 + } 11.524 + } 11.525 + 11.526 + return 0; 11.527 +} 11.528 + 11.529 +static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName) 11.530 +{ 11.531 + alsa_data *data; 11.532 + char driver[128]; 11.533 + int i; 11.534 + 11.535 + strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1); 11.536 + driver[sizeof(driver)-1] = 0; 11.537 + 11.538 + if(!deviceName) 11.539 + deviceName = alsaDevice; 11.540 + else if(strcmp(deviceName, alsaDevice) != 0) 11.541 + { 11.542 + size_t idx; 11.543 + 11.544 + if(!allDevNameMap) 11.545 + allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); 11.546 + 11.547 + for(idx = 0;idx < numDevNames;idx++) 11.548 + { 11.549 + if(allDevNameMap[idx].name && 11.550 + strcmp(deviceName, allDevNameMap[idx].name) == 0) 11.551 + { 11.552 + if(idx > 0) 11.553 + snprintf(driver, sizeof(driver), "%sCARD=%s,DEV=%d", device_prefix, 11.554 + allDevNameMap[idx].card, allDevNameMap[idx].dev); 11.555 + break; 11.556 + } 11.557 + } 11.558 + if(idx == numDevNames) 11.559 + return ALC_FALSE; 11.560 + } 11.561 + 11.562 + data = (alsa_data*)calloc(1, sizeof(alsa_data)); 11.563 + 11.564 + i = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); 11.565 + if(i >= 0) 11.566 + { 11.567 + i = snd_pcm_nonblock(data->pcmHandle, 0); 11.568 + if(i < 0) 11.569 + snd_pcm_close(data->pcmHandle); 11.570 + } 11.571 + if(i < 0) 11.572 + { 11.573 + free(data); 11.574 + ERR("Could not open playback device '%s': %s\n", driver, snd_strerror(i)); 11.575 + return ALC_FALSE; 11.576 + } 11.577 + 11.578 + device->szDeviceName = strdup(deviceName); 11.579 + device->ExtraData = data; 11.580 + return ALC_TRUE; 11.581 +} 11.582 + 11.583 +static void alsa_close_playback(ALCdevice *device) 11.584 +{ 11.585 + alsa_data *data = (alsa_data*)device->ExtraData; 11.586 + 11.587 + snd_pcm_close(data->pcmHandle); 11.588 + free(data); 11.589 + device->ExtraData = NULL; 11.590 +} 11.591 + 11.592 +static ALCboolean alsa_reset_playback(ALCdevice *device) 11.593 +{ 11.594 + alsa_data *data = (alsa_data*)device->ExtraData; 11.595 + snd_pcm_uframes_t periodSizeInFrames; 11.596 + unsigned int periodLen, bufferLen; 11.597 + snd_pcm_sw_params_t *sp = NULL; 11.598 + snd_pcm_hw_params_t *p = NULL; 11.599 + snd_pcm_access_t access; 11.600 + snd_pcm_format_t format; 11.601 + unsigned int periods; 11.602 + unsigned int rate; 11.603 + int allowmmap; 11.604 + char *err; 11.605 + int i; 11.606 + 11.607 + 11.608 + format = -1; 11.609 + switch(device->FmtType) 11.610 + { 11.611 + case DevFmtByte: 11.612 + format = SND_PCM_FORMAT_S8; 11.613 + break; 11.614 + case DevFmtUByte: 11.615 + format = SND_PCM_FORMAT_U8; 11.616 + break; 11.617 + case DevFmtShort: 11.618 + format = SND_PCM_FORMAT_S16; 11.619 + break; 11.620 + case DevFmtUShort: 11.621 + format = SND_PCM_FORMAT_U16; 11.622 + break; 11.623 + case DevFmtFloat: 11.624 + format = SND_PCM_FORMAT_FLOAT; 11.625 + break; 11.626 + } 11.627 + 11.628 + allowmmap = GetConfigValueBool("alsa", "mmap", 1); 11.629 + periods = device->NumUpdates; 11.630 + periodLen = (ALuint64)device->UpdateSize * 1000000 / device->Frequency; 11.631 + bufferLen = periodLen * periods; 11.632 + rate = device->Frequency; 11.633 + 11.634 + err = NULL; 11.635 + snd_pcm_hw_params_malloc(&p); 11.636 + 11.637 + if((i=snd_pcm_hw_params_any(data->pcmHandle, p)) < 0) 11.638 + err = "any"; 11.639 + /* set interleaved access */ 11.640 + if(i >= 0 && (!allowmmap || (i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_MMAP_INTERLEAVED)) < 0)) 11.641 + { 11.642 + if(periods > 2) 11.643 + { 11.644 + periods--; 11.645 + bufferLen = periodLen * periods; 11.646 + } 11.647 + if((i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 11.648 + err = "set access"; 11.649 + } 11.650 + /* set format (implicitly sets sample bits) */ 11.651 + if(i >= 0 && (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) 11.652 + { 11.653 + device->FmtType = DevFmtFloat; 11.654 + if(format == SND_PCM_FORMAT_FLOAT || 11.655 + (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_FLOAT)) < 0) 11.656 + { 11.657 + device->FmtType = DevFmtShort; 11.658 + if(format == SND_PCM_FORMAT_S16 || 11.659 + (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_S16)) < 0) 11.660 + { 11.661 + device->FmtType = DevFmtUByte; 11.662 + if(format == SND_PCM_FORMAT_U8 || 11.663 + (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, SND_PCM_FORMAT_U8)) < 0) 11.664 + err = "set format"; 11.665 + } 11.666 + } 11.667 + } 11.668 + /* set channels (implicitly sets frame bits) */ 11.669 + if(i >= 0 && (i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, ChannelsFromDevFmt(device->FmtChans))) < 0) 11.670 + { 11.671 + if((i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, 2)) < 0) 11.672 + { 11.673 + if((i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, 1)) < 0) 11.674 + err = "set channels"; 11.675 + else 11.676 + { 11.677 + if((device->Flags&DEVICE_CHANNELS_REQUEST)) 11.678 + ERR("Failed to set %s, got Mono instead\n", DevFmtChannelsString(device->FmtChans)); 11.679 + device->FmtChans = DevFmtMono; 11.680 + } 11.681 + } 11.682 + else 11.683 + { 11.684 + if((device->Flags&DEVICE_CHANNELS_REQUEST)) 11.685 + ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(device->FmtChans)); 11.686 + device->FmtChans = DevFmtStereo; 11.687 + } 11.688 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 11.689 + } 11.690 + if(i >= 0 && (i=snd_pcm_hw_params_set_rate_resample(data->pcmHandle, p, 0)) < 0) 11.691 + { 11.692 + ERR("Failed to disable ALSA resampler\n"); 11.693 + i = 0; 11.694 + } 11.695 + /* set rate (implicitly constrains period/buffer parameters) */ 11.696 + if(i >= 0 && (i=snd_pcm_hw_params_set_rate_near(data->pcmHandle, p, &rate, NULL)) < 0) 11.697 + err = "set rate near"; 11.698 + /* set buffer time (implicitly constrains period/buffer parameters) */ 11.699 + if(i >= 0 && (i=snd_pcm_hw_params_set_buffer_time_near(data->pcmHandle, p, &bufferLen, NULL)) < 0) 11.700 + err = "set buffer time near"; 11.701 + /* set period time in frame units (implicitly sets buffer size/bytes/time and period size/bytes) */ 11.702 + if(i >= 0 && (i=snd_pcm_hw_params_set_period_time_near(data->pcmHandle, p, &periodLen, NULL)) < 0) 11.703 + err = "set period time near"; 11.704 + /* install and prepare hardware configuration */ 11.705 + if(i >= 0 && (i=snd_pcm_hw_params(data->pcmHandle, p)) < 0) 11.706 + err = "set params"; 11.707 + if(i >= 0 && (i=snd_pcm_hw_params_get_access(p, &access)) < 0) 11.708 + err = "get access"; 11.709 + if(i >= 0 && (i=snd_pcm_hw_params_get_period_size(p, &periodSizeInFrames, NULL)) < 0) 11.710 + err = "get period size"; 11.711 + if(i >= 0 && (i=snd_pcm_hw_params_get_periods(p, &periods, NULL)) < 0) 11.712 + err = "get periods"; 11.713 + if(i < 0) 11.714 + { 11.715 + ERR("%s failed: %s\n", err, snd_strerror(i)); 11.716 + snd_pcm_hw_params_free(p); 11.717 + return ALC_FALSE; 11.718 + } 11.719 + 11.720 + snd_pcm_hw_params_free(p); 11.721 + 11.722 + err = NULL; 11.723 + snd_pcm_sw_params_malloc(&sp); 11.724 + 11.725 + if((i=snd_pcm_sw_params_current(data->pcmHandle, sp)) != 0) 11.726 + err = "sw current"; 11.727 + if(i == 0 && (i=snd_pcm_sw_params_set_avail_min(data->pcmHandle, sp, periodSizeInFrames)) != 0) 11.728 + err = "sw set avail min"; 11.729 + if(i == 0 && (i=snd_pcm_sw_params(data->pcmHandle, sp)) != 0) 11.730 + err = "sw set params"; 11.731 + if(i != 0) 11.732 + { 11.733 + ERR("%s failed: %s\n", err, snd_strerror(i)); 11.734 + snd_pcm_sw_params_free(sp); 11.735 + return ALC_FALSE; 11.736 + } 11.737 + 11.738 + snd_pcm_sw_params_free(sp); 11.739 + 11.740 + if(device->Frequency != rate) 11.741 + { 11.742 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 11.743 + ERR("Failed to set %dhz, got %dhz instead\n", device->Frequency, rate); 11.744 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 11.745 + device->Frequency = rate; 11.746 + } 11.747 + 11.748 + SetDefaultChannelOrder(device); 11.749 + 11.750 + data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames); 11.751 + if(access == SND_PCM_ACCESS_RW_INTERLEAVED) 11.752 + { 11.753 + /* Increase periods by one, since the temp buffer counts as an extra 11.754 + * period */ 11.755 + periods++; 11.756 + data->buffer = malloc(data->size); 11.757 + if(!data->buffer) 11.758 + { 11.759 + ERR("buffer malloc failed\n"); 11.760 + return ALC_FALSE; 11.761 + } 11.762 + device->UpdateSize = periodSizeInFrames; 11.763 + device->NumUpdates = periods; 11.764 + data->thread = StartThread(ALSANoMMapProc, device); 11.765 + } 11.766 + else 11.767 + { 11.768 + i = snd_pcm_prepare(data->pcmHandle); 11.769 + if(i < 0) 11.770 + { 11.771 + ERR("prepare error: %s\n", snd_strerror(i)); 11.772 + return ALC_FALSE; 11.773 + } 11.774 + device->UpdateSize = periodSizeInFrames; 11.775 + device->NumUpdates = periods; 11.776 + data->thread = StartThread(ALSAProc, device); 11.777 + } 11.778 + if(data->thread == NULL) 11.779 + { 11.780 + ERR("Could not create playback thread\n"); 11.781 + free(data->buffer); 11.782 + data->buffer = NULL; 11.783 + return ALC_FALSE; 11.784 + } 11.785 + 11.786 + return ALC_TRUE; 11.787 +} 11.788 + 11.789 +static void alsa_stop_playback(ALCdevice *device) 11.790 +{ 11.791 + alsa_data *data = (alsa_data*)device->ExtraData; 11.792 + 11.793 + if(data->thread) 11.794 + { 11.795 + data->killNow = 1; 11.796 + StopThread(data->thread); 11.797 + data->thread = NULL; 11.798 + } 11.799 + data->killNow = 0; 11.800 + free(data->buffer); 11.801 + data->buffer = NULL; 11.802 +} 11.803 + 11.804 + 11.805 +static ALCboolean alsa_open_capture(ALCdevice *pDevice, const ALCchar *deviceName) 11.806 +{ 11.807 + snd_pcm_hw_params_t *p; 11.808 + snd_pcm_uframes_t bufferSizeInFrames; 11.809 + snd_pcm_format_t format; 11.810 + ALuint frameSize; 11.811 + alsa_data *data; 11.812 + char driver[128]; 11.813 + char *err; 11.814 + int i; 11.815 + 11.816 + strncpy(driver, GetConfigValue("alsa", "capture", "default"), sizeof(driver)-1); 11.817 + driver[sizeof(driver)-1] = 0; 11.818 + 11.819 + if(!allCaptureDevNameMap) 11.820 + allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); 11.821 + 11.822 + if(!deviceName) 11.823 + deviceName = allCaptureDevNameMap[0].name; 11.824 + else 11.825 + { 11.826 + size_t idx; 11.827 + 11.828 + for(idx = 0;idx < numCaptureDevNames;idx++) 11.829 + { 11.830 + if(allCaptureDevNameMap[idx].name && 11.831 + strcmp(deviceName, allCaptureDevNameMap[idx].name) == 0) 11.832 + { 11.833 + if(idx > 0) 11.834 + snprintf(driver, sizeof(driver), "%sCARD=%s,DEV=%d", capture_prefix, 11.835 + allCaptureDevNameMap[idx].card, allCaptureDevNameMap[idx].dev); 11.836 + break; 11.837 + } 11.838 + } 11.839 + if(idx == numCaptureDevNames) 11.840 + return ALC_FALSE; 11.841 + } 11.842 + 11.843 + data = (alsa_data*)calloc(1, sizeof(alsa_data)); 11.844 + 11.845 + i = snd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK); 11.846 + if(i < 0) 11.847 + { 11.848 + ERR("Could not open capture device '%s': %s\n", driver, snd_strerror(i)); 11.849 + free(data); 11.850 + return ALC_FALSE; 11.851 + } 11.852 + 11.853 + format = -1; 11.854 + switch(pDevice->FmtType) 11.855 + { 11.856 + case DevFmtByte: 11.857 + format = SND_PCM_FORMAT_S8; 11.858 + break; 11.859 + case DevFmtUByte: 11.860 + format = SND_PCM_FORMAT_U8; 11.861 + break; 11.862 + case DevFmtShort: 11.863 + format = SND_PCM_FORMAT_S16; 11.864 + break; 11.865 + case DevFmtUShort: 11.866 + format = SND_PCM_FORMAT_U16; 11.867 + break; 11.868 + case DevFmtFloat: 11.869 + format = SND_PCM_FORMAT_FLOAT; 11.870 + break; 11.871 + } 11.872 + 11.873 + err = NULL; 11.874 + bufferSizeInFrames = pDevice->UpdateSize * pDevice->NumUpdates; 11.875 + snd_pcm_hw_params_malloc(&p); 11.876 + 11.877 + if((i=snd_pcm_hw_params_any(data->pcmHandle, p)) < 0) 11.878 + err = "any"; 11.879 + /* set interleaved access */ 11.880 + if(i >= 0 && (i=snd_pcm_hw_params_set_access(data->pcmHandle, p, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) 11.881 + err = "set access"; 11.882 + /* set format (implicitly sets sample bits) */ 11.883 + if(i >= 0 && (i=snd_pcm_hw_params_set_format(data->pcmHandle, p, format)) < 0) 11.884 + err = "set format"; 11.885 + /* set channels (implicitly sets frame bits) */ 11.886 + if(i >= 0 && (i=snd_pcm_hw_params_set_channels(data->pcmHandle, p, ChannelsFromDevFmt(pDevice->FmtChans))) < 0) 11.887 + err = "set channels"; 11.888 + /* set rate (implicitly constrains period/buffer parameters) */ 11.889 + if(i >= 0 && (i=snd_pcm_hw_params_set_rate(data->pcmHandle, p, pDevice->Frequency, 0)) < 0) 11.890 + err = "set rate near"; 11.891 + /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ 11.892 + if(i >= 0 && (i=snd_pcm_hw_params_set_buffer_size_near(data->pcmHandle, p, &bufferSizeInFrames)) < 0) 11.893 + err = "set buffer size near"; 11.894 + /* install and prepare hardware configuration */ 11.895 + if(i >= 0 && (i=snd_pcm_hw_params(data->pcmHandle, p)) < 0) 11.896 + err = "set params"; 11.897 + if(i < 0) 11.898 + { 11.899 + ERR("%s failed: %s\n", err, snd_strerror(i)); 11.900 + snd_pcm_hw_params_free(p); 11.901 + goto error; 11.902 + } 11.903 + 11.904 + if((i=snd_pcm_hw_params_get_period_size(p, &bufferSizeInFrames, NULL)) < 0) 11.905 + { 11.906 + ERR("get size failed: %s\n", snd_strerror(i)); 11.907 + snd_pcm_hw_params_free(p); 11.908 + goto error; 11.909 + } 11.910 + 11.911 + snd_pcm_hw_params_free(p); 11.912 + 11.913 + frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 11.914 + 11.915 + data->ring = CreateRingBuffer(frameSize, pDevice->UpdateSize*pDevice->NumUpdates); 11.916 + if(!data->ring) 11.917 + { 11.918 + ERR("ring buffer create failed\n"); 11.919 + goto error; 11.920 + } 11.921 + 11.922 + data->size = snd_pcm_frames_to_bytes(data->pcmHandle, bufferSizeInFrames); 11.923 + data->buffer = malloc(data->size); 11.924 + if(!data->buffer) 11.925 + { 11.926 + ERR("buffer malloc failed\n"); 11.927 + goto error; 11.928 + } 11.929 + 11.930 + pDevice->szDeviceName = strdup(deviceName); 11.931 + 11.932 + pDevice->ExtraData = data; 11.933 + return ALC_TRUE; 11.934 + 11.935 +error: 11.936 + free(data->buffer); 11.937 + DestroyRingBuffer(data->ring); 11.938 + snd_pcm_close(data->pcmHandle); 11.939 + free(data); 11.940 + 11.941 + pDevice->ExtraData = NULL; 11.942 + return ALC_FALSE; 11.943 +} 11.944 + 11.945 +static void alsa_close_capture(ALCdevice *pDevice) 11.946 +{ 11.947 + alsa_data *data = (alsa_data*)pDevice->ExtraData; 11.948 + 11.949 + snd_pcm_close(data->pcmHandle); 11.950 + DestroyRingBuffer(data->ring); 11.951 + 11.952 + free(data->buffer); 11.953 + free(data); 11.954 + pDevice->ExtraData = NULL; 11.955 +} 11.956 + 11.957 +static void alsa_start_capture(ALCdevice *Device) 11.958 +{ 11.959 + alsa_data *data = (alsa_data*)Device->ExtraData; 11.960 + int err; 11.961 + 11.962 + err = snd_pcm_start(data->pcmHandle); 11.963 + if(err < 0) 11.964 + { 11.965 + ERR("start failed: %s\n", snd_strerror(err)); 11.966 + aluHandleDisconnect(Device); 11.967 + } 11.968 + else 11.969 + data->doCapture = AL_TRUE; 11.970 +} 11.971 + 11.972 +static void alsa_stop_capture(ALCdevice *Device) 11.973 +{ 11.974 + alsa_data *data = (alsa_data*)Device->ExtraData; 11.975 + snd_pcm_drain(data->pcmHandle); 11.976 + data->doCapture = AL_FALSE; 11.977 +} 11.978 + 11.979 +static ALCuint alsa_available_samples(ALCdevice *Device) 11.980 +{ 11.981 + alsa_data *data = (alsa_data*)Device->ExtraData; 11.982 + snd_pcm_sframes_t avail; 11.983 + 11.984 + avail = (Device->Connected ? snd_pcm_avail_update(data->pcmHandle) : 0); 11.985 + if(avail < 0) 11.986 + { 11.987 + ERR("avail update failed: %s\n", snd_strerror(avail)); 11.988 + 11.989 + if((avail=snd_pcm_recover(data->pcmHandle, avail, 1)) >= 0) 11.990 + { 11.991 + if(data->doCapture) 11.992 + avail = snd_pcm_start(data->pcmHandle); 11.993 + if(avail >= 0) 11.994 + avail = snd_pcm_avail_update(data->pcmHandle); 11.995 + } 11.996 + if(avail < 0) 11.997 + { 11.998 + ERR("restore error: %s\n", snd_strerror(avail)); 11.999 + aluHandleDisconnect(Device); 11.1000 + } 11.1001 + } 11.1002 + while(avail > 0) 11.1003 + { 11.1004 + snd_pcm_sframes_t amt; 11.1005 + 11.1006 + amt = snd_pcm_bytes_to_frames(data->pcmHandle, data->size); 11.1007 + if(avail < amt) amt = avail; 11.1008 + 11.1009 + amt = snd_pcm_readi(data->pcmHandle, data->buffer, amt); 11.1010 + if(amt < 0) 11.1011 + { 11.1012 + ERR("read error: %s\n", snd_strerror(amt)); 11.1013 + 11.1014 + if(amt == -EAGAIN) 11.1015 + continue; 11.1016 + if((amt=snd_pcm_recover(data->pcmHandle, amt, 1)) >= 0) 11.1017 + { 11.1018 + if(data->doCapture) 11.1019 + amt = snd_pcm_start(data->pcmHandle); 11.1020 + if(amt >= 0) 11.1021 + amt = snd_pcm_avail_update(data->pcmHandle); 11.1022 + } 11.1023 + if(amt < 0) 11.1024 + { 11.1025 + ERR("restore error: %s\n", snd_strerror(amt)); 11.1026 + aluHandleDisconnect(Device); 11.1027 + break; 11.1028 + } 11.1029 + avail = amt; 11.1030 + continue; 11.1031 + } 11.1032 + 11.1033 + WriteRingBuffer(data->ring, data->buffer, amt); 11.1034 + avail -= amt; 11.1035 + } 11.1036 + 11.1037 + return RingBufferSize(data->ring); 11.1038 +} 11.1039 + 11.1040 +static void alsa_capture_samples(ALCdevice *Device, ALCvoid *Buffer, ALCuint Samples) 11.1041 +{ 11.1042 + alsa_data *data = (alsa_data*)Device->ExtraData; 11.1043 + 11.1044 + if(Samples <= alsa_available_samples(Device)) 11.1045 + ReadRingBuffer(data->ring, Buffer, Samples); 11.1046 + else 11.1047 + alcSetError(Device, ALC_INVALID_VALUE); 11.1048 +} 11.1049 + 11.1050 + 11.1051 +static const BackendFuncs alsa_funcs = { 11.1052 + alsa_open_playback, 11.1053 + alsa_close_playback, 11.1054 + alsa_reset_playback, 11.1055 + alsa_stop_playback, 11.1056 + alsa_open_capture, 11.1057 + alsa_close_capture, 11.1058 + alsa_start_capture, 11.1059 + alsa_stop_capture, 11.1060 + alsa_capture_samples, 11.1061 + alsa_available_samples 11.1062 +}; 11.1063 + 11.1064 +ALCboolean alc_alsa_init(BackendFuncs *func_list) 11.1065 +{ 11.1066 + if(!alsa_load()) 11.1067 + return ALC_FALSE; 11.1068 + device_prefix = GetConfigValue("alsa", "device-prefix", "plughw:"); 11.1069 + capture_prefix = GetConfigValue("alsa", "capture-prefix", "plughw:"); 11.1070 + *func_list = alsa_funcs; 11.1071 + return ALC_TRUE; 11.1072 +} 11.1073 + 11.1074 +void alc_alsa_deinit(void) 11.1075 +{ 11.1076 + ALuint i; 11.1077 + 11.1078 + for(i = 0;i < numDevNames;++i) 11.1079 + { 11.1080 + free(allDevNameMap[i].name); 11.1081 + free(allDevNameMap[i].card); 11.1082 + } 11.1083 + free(allDevNameMap); 11.1084 + allDevNameMap = NULL; 11.1085 + numDevNames = 0; 11.1086 + 11.1087 + for(i = 0;i < numCaptureDevNames;++i) 11.1088 + { 11.1089 + free(allCaptureDevNameMap[i].name); 11.1090 + free(allCaptureDevNameMap[i].card); 11.1091 + } 11.1092 + free(allCaptureDevNameMap); 11.1093 + allCaptureDevNameMap = NULL; 11.1094 + numCaptureDevNames = 0; 11.1095 + 11.1096 +#ifdef HAVE_DYNLOAD 11.1097 + if(alsa_handle) 11.1098 + CloseLib(alsa_handle); 11.1099 + alsa_handle = NULL; 11.1100 +#endif 11.1101 +} 11.1102 + 11.1103 +void alc_alsa_probe(enum DevProbe type) 11.1104 +{ 11.1105 + ALuint i; 11.1106 + 11.1107 + switch(type) 11.1108 + { 11.1109 + case DEVICE_PROBE: 11.1110 + AppendDeviceList(alsaDevice); 11.1111 + break; 11.1112 + 11.1113 + case ALL_DEVICE_PROBE: 11.1114 + for(i = 0;i < numDevNames;++i) 11.1115 + { 11.1116 + free(allDevNameMap[i].name); 11.1117 + free(allDevNameMap[i].card); 11.1118 + } 11.1119 + 11.1120 + free(allDevNameMap); 11.1121 + allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); 11.1122 + 11.1123 + for(i = 0;i < numDevNames;++i) 11.1124 + AppendAllDeviceList(allDevNameMap[i].name); 11.1125 + break; 11.1126 + 11.1127 + case CAPTURE_DEVICE_PROBE: 11.1128 + for(i = 0;i < numCaptureDevNames;++i) 11.1129 + { 11.1130 + free(allCaptureDevNameMap[i].name); 11.1131 + free(allCaptureDevNameMap[i].card); 11.1132 + } 11.1133 + 11.1134 + free(allCaptureDevNameMap); 11.1135 + allCaptureDevNameMap = probe_devices(SND_PCM_STREAM_CAPTURE, &numCaptureDevNames); 11.1136 + 11.1137 + for(i = 0;i < numCaptureDevNames;++i) 11.1138 + AppendCaptureDeviceList(allCaptureDevNameMap[i].name); 11.1139 + break; 11.1140 + } 11.1141 +}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 12.2 +++ b/Alc/backends/coreaudio.c Tue Oct 25 13:02:31 2011 -0700 12.3 @@ -0,0 +1,719 @@ 12.4 +/** 12.5 + * OpenAL cross platform audio library 12.6 + * Copyright (C) 1999-2007 by authors. 12.7 + * This library is free software; you can redistribute it and/or 12.8 + * modify it under the terms of the GNU Library General Public 12.9 + * License as published by the Free Software Foundation; either 12.10 + * version 2 of the License, or (at your option) any later version. 12.11 + * 12.12 + * This library is distributed in the hope that it will be useful, 12.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 12.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12.15 + * Library General Public License for more details. 12.16 + * 12.17 + * You should have received a copy of the GNU Library General Public 12.18 + * License along with this library; if not, write to the 12.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 12.20 + * Boston, MA 02111-1307, USA. 12.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 12.22 + */ 12.23 + 12.24 +#include "config.h" 12.25 + 12.26 +#include <stdio.h> 12.27 +#include <stdlib.h> 12.28 +#include <string.h> 12.29 + 12.30 +#include "alMain.h" 12.31 +#include "AL/al.h" 12.32 +#include "AL/alc.h" 12.33 + 12.34 +#include <CoreServices/CoreServices.h> 12.35 +#include <unistd.h> 12.36 +#include <AudioUnit/AudioUnit.h> 12.37 +#include <AudioToolbox/AudioToolbox.h> 12.38 + 12.39 + 12.40 +typedef struct { 12.41 + AudioUnit audioUnit; 12.42 + 12.43 + ALuint frameSize; 12.44 + ALdouble sampleRateRatio; // Ratio of hardware sample rate / requested sample rate 12.45 + AudioStreamBasicDescription format; // This is the OpenAL format as a CoreAudio ASBD 12.46 + 12.47 + AudioConverterRef audioConverter; // Sample rate converter if needed 12.48 + AudioBufferList *bufferList; // Buffer for data coming from the input device 12.49 + ALCvoid *resampleBuffer; // Buffer for returned RingBuffer data when resampling 12.50 + 12.51 + RingBuffer *ring; 12.52 +} ca_data; 12.53 + 12.54 +static const ALCchar ca_device[] = "CoreAudio Default"; 12.55 + 12.56 + 12.57 +static void destroy_buffer_list(AudioBufferList* list) 12.58 +{ 12.59 + if(list) 12.60 + { 12.61 + UInt32 i; 12.62 + for(i = 0;i < list->mNumberBuffers;i++) 12.63 + free(list->mBuffers[i].mData); 12.64 + free(list); 12.65 + } 12.66 +} 12.67 + 12.68 +static AudioBufferList* allocate_buffer_list(UInt32 channelCount, UInt32 byteSize) 12.69 +{ 12.70 + AudioBufferList *list; 12.71 + 12.72 + list = calloc(1, sizeof(AudioBufferList) + sizeof(AudioBuffer)); 12.73 + if(list) 12.74 + { 12.75 + list->mNumberBuffers = 1; 12.76 + 12.77 + list->mBuffers[0].mNumberChannels = channelCount; 12.78 + list->mBuffers[0].mDataByteSize = byteSize; 12.79 + list->mBuffers[0].mData = malloc(byteSize); 12.80 + if(list->mBuffers[0].mData == NULL) 12.81 + { 12.82 + free(list); 12.83 + list = NULL; 12.84 + } 12.85 + } 12.86 + return list; 12.87 +} 12.88 + 12.89 +static OSStatus ca_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, const AudioTimeStamp *inTimeStamp, 12.90 + UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) 12.91 +{ 12.92 + ALCdevice *device = (ALCdevice*)inRefCon; 12.93 + ca_data *data = (ca_data*)device->ExtraData; 12.94 + 12.95 + aluMixData(device, ioData->mBuffers[0].mData, 12.96 + ioData->mBuffers[0].mDataByteSize / data->frameSize); 12.97 + 12.98 + return noErr; 12.99 +} 12.100 + 12.101 +static OSStatus ca_capture_conversion_callback(AudioConverterRef inAudioConverter, UInt32 *ioNumberDataPackets, 12.102 + AudioBufferList *ioData, AudioStreamPacketDescription **outDataPacketDescription, void* inUserData) 12.103 +{ 12.104 + ALCdevice *device = (ALCdevice*)inUserData; 12.105 + ca_data *data = (ca_data*)device->ExtraData; 12.106 + 12.107 + // Read from the ring buffer and store temporarily in a large buffer 12.108 + ReadRingBuffer(data->ring, data->resampleBuffer, (ALsizei)(*ioNumberDataPackets)); 12.109 + 12.110 + // Set the input data 12.111 + ioData->mNumberBuffers = 1; 12.112 + ioData->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame; 12.113 + ioData->mBuffers[0].mData = data->resampleBuffer; 12.114 + ioData->mBuffers[0].mDataByteSize = (*ioNumberDataPackets) * data->format.mBytesPerFrame; 12.115 + 12.116 + return noErr; 12.117 +} 12.118 + 12.119 +static OSStatus ca_capture_callback(void *inRefCon, AudioUnitRenderActionFlags *ioActionFlags, 12.120 + const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, 12.121 + UInt32 inNumberFrames, AudioBufferList *ioData) 12.122 +{ 12.123 + ALCdevice *device = (ALCdevice*)inRefCon; 12.124 + ca_data *data = (ca_data*)device->ExtraData; 12.125 + AudioUnitRenderActionFlags flags = 0; 12.126 + OSStatus err; 12.127 + 12.128 + // fill the bufferList with data from the input device 12.129 + err = AudioUnitRender(data->audioUnit, &flags, inTimeStamp, 1, inNumberFrames, data->bufferList); 12.130 + if(err != noErr) 12.131 + { 12.132 + ERR("AudioUnitRender error: %d\n", err); 12.133 + return err; 12.134 + } 12.135 + 12.136 + WriteRingBuffer(data->ring, data->bufferList->mBuffers[0].mData, inNumberFrames); 12.137 + 12.138 + return noErr; 12.139 +} 12.140 + 12.141 +static ALCboolean ca_open_playback(ALCdevice *device, const ALCchar *deviceName) 12.142 +{ 12.143 + ComponentDescription desc; 12.144 + Component comp; 12.145 + ca_data *data; 12.146 + OSStatus err; 12.147 + 12.148 + if(!deviceName) 12.149 + deviceName = ca_device; 12.150 + else if(strcmp(deviceName, ca_device) != 0) 12.151 + return ALC_FALSE; 12.152 + 12.153 + /* open the default output unit */ 12.154 + desc.componentType = kAudioUnitType_Output; 12.155 + desc.componentSubType = kAudioUnitSubType_DefaultOutput; 12.156 + desc.componentManufacturer = kAudioUnitManufacturer_Apple; 12.157 + desc.componentFlags = 0; 12.158 + desc.componentFlagsMask = 0; 12.159 + 12.160 + comp = FindNextComponent(NULL, &desc); 12.161 + if(comp == NULL) 12.162 + { 12.163 + ERR("FindNextComponent failed\n"); 12.164 + return ALC_FALSE; 12.165 + } 12.166 + 12.167 + data = calloc(1, sizeof(*data)); 12.168 + device->ExtraData = data; 12.169 + 12.170 + err = OpenAComponent(comp, &data->audioUnit); 12.171 + if(err != noErr) 12.172 + { 12.173 + ERR("OpenAComponent failed\n"); 12.174 + free(data); 12.175 + device->ExtraData = NULL; 12.176 + return ALC_FALSE; 12.177 + } 12.178 + 12.179 + return ALC_TRUE; 12.180 +} 12.181 + 12.182 +static void ca_close_playback(ALCdevice *device) 12.183 +{ 12.184 + ca_data *data = (ca_data*)device->ExtraData; 12.185 + 12.186 + CloseComponent(data->audioUnit); 12.187 + 12.188 + free(data); 12.189 + device->ExtraData = NULL; 12.190 +} 12.191 + 12.192 +static ALCboolean ca_reset_playback(ALCdevice *device) 12.193 +{ 12.194 + ca_data *data = (ca_data*)device->ExtraData; 12.195 + AudioStreamBasicDescription streamFormat; 12.196 + AURenderCallbackStruct input; 12.197 + OSStatus err; 12.198 + UInt32 size; 12.199 + 12.200 + /* init and start the default audio unit... */ 12.201 + err = AudioUnitInitialize(data->audioUnit); 12.202 + if(err != noErr) 12.203 + { 12.204 + ERR("AudioUnitInitialize failed\n"); 12.205 + return ALC_FALSE; 12.206 + } 12.207 + 12.208 + err = AudioOutputUnitStart(data->audioUnit); 12.209 + if(err != noErr) 12.210 + { 12.211 + ERR("AudioOutputUnitStart failed\n"); 12.212 + return ALC_FALSE; 12.213 + } 12.214 + 12.215 + /* retrieve default output unit's properties (output side) */ 12.216 + size = sizeof(AudioStreamBasicDescription); 12.217 + err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &streamFormat, &size); 12.218 + if(err != noErr || size != sizeof(AudioStreamBasicDescription)) 12.219 + { 12.220 + ERR("AudioUnitGetProperty failed\n"); 12.221 + return ALC_FALSE; 12.222 + } 12.223 + 12.224 +#if 0 12.225 + TRACE("Output streamFormat of default output unit -\n"); 12.226 + TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat.mFramesPerPacket); 12.227 + TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat.mChannelsPerFrame); 12.228 + TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat.mBitsPerChannel); 12.229 + TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat.mBytesPerPacket); 12.230 + TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat.mBytesPerFrame); 12.231 + TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat.mSampleRate); 12.232 +#endif 12.233 + 12.234 + /* set default output unit's input side to match output side */ 12.235 + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, size); 12.236 + if(err != noErr) 12.237 + { 12.238 + ERR("AudioUnitSetProperty failed\n"); 12.239 + return ALC_FALSE; 12.240 + } 12.241 + 12.242 + if(device->Frequency != streamFormat.mSampleRate) 12.243 + { 12.244 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 12.245 + ERR("CoreAudio does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, streamFormat.mSampleRate); 12.246 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 12.247 + 12.248 + device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize * 12.249 + streamFormat.mSampleRate / 12.250 + device->Frequency); 12.251 + device->Frequency = streamFormat.mSampleRate; 12.252 + } 12.253 + 12.254 + /* FIXME: How to tell what channels are what in the output device, and how 12.255 + * to specify what we're giving? eg, 6.0 vs 5.1 */ 12.256 + switch(streamFormat.mChannelsPerFrame) 12.257 + { 12.258 + case 1: 12.259 + if((device->Flags&DEVICE_CHANNELS_REQUEST) && 12.260 + device->FmtChans != DevFmtMono) 12.261 + { 12.262 + ERR("Failed to set %s, got Mono instead\n", DevFmtChannelsString(device->FmtChans)); 12.263 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.264 + } 12.265 + device->FmtChans = DevFmtMono; 12.266 + break; 12.267 + case 2: 12.268 + if((device->Flags&DEVICE_CHANNELS_REQUEST) && 12.269 + device->FmtChans != DevFmtStereo) 12.270 + { 12.271 + ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(device->FmtChans)); 12.272 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.273 + } 12.274 + device->FmtChans = DevFmtStereo; 12.275 + break; 12.276 + case 4: 12.277 + if((device->Flags&DEVICE_CHANNELS_REQUEST) && 12.278 + device->FmtChans != DevFmtQuad) 12.279 + { 12.280 + ERR("Failed to set %s, got Quad instead\n", DevFmtChannelsString(device->FmtChans)); 12.281 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.282 + } 12.283 + device->FmtChans = DevFmtQuad; 12.284 + break; 12.285 + case 6: 12.286 + if((device->Flags&DEVICE_CHANNELS_REQUEST) && 12.287 + device->FmtChans != DevFmtX51) 12.288 + { 12.289 + ERR("Failed to set %s, got 5.1 Surround instead\n", DevFmtChannelsString(device->FmtChans)); 12.290 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.291 + } 12.292 + device->FmtChans = DevFmtX51; 12.293 + break; 12.294 + case 7: 12.295 + if((device->Flags&DEVICE_CHANNELS_REQUEST) && 12.296 + device->FmtChans != DevFmtX61) 12.297 + { 12.298 + ERR("Failed to set %s, got 6.1 Surround instead\n", DevFmtChannelsString(device->FmtChans)); 12.299 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.300 + } 12.301 + device->FmtChans = DevFmtX61; 12.302 + break; 12.303 + case 8: 12.304 + if((device->Flags&DEVICE_CHANNELS_REQUEST) && 12.305 + device->FmtChans != DevFmtX71) 12.306 + { 12.307 + ERR("Failed to set %s, got 7.1 Surround instead\n", DevFmtChannelsString(device->FmtChans)); 12.308 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.309 + } 12.310 + device->FmtChans = DevFmtX71; 12.311 + break; 12.312 + default: 12.313 + ERR("Unhandled channel count (%d), using Stereo\n", streamFormat.mChannelsPerFrame); 12.314 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 12.315 + device->FmtChans = DevFmtStereo; 12.316 + streamFormat.mChannelsPerFrame = 2; 12.317 + break; 12.318 + } 12.319 + SetDefaultWFXChannelOrder(device); 12.320 + 12.321 + /* use channel count and sample rate from the default output unit's current 12.322 + * parameters, but reset everything else */ 12.323 + streamFormat.mFramesPerPacket = 1; 12.324 + switch(device->FmtType) 12.325 + { 12.326 + case DevFmtUByte: 12.327 + device->FmtType = DevFmtByte; 12.328 + /* fall-through */ 12.329 + case DevFmtByte: 12.330 + streamFormat.mBitsPerChannel = 8; 12.331 + streamFormat.mBytesPerPacket = streamFormat.mChannelsPerFrame; 12.332 + streamFormat.mBytesPerFrame = streamFormat.mChannelsPerFrame; 12.333 + break; 12.334 + case DevFmtUShort: 12.335 + case DevFmtFloat: 12.336 + device->FmtType = DevFmtShort; 12.337 + /* fall-through */ 12.338 + case DevFmtShort: 12.339 + streamFormat.mBitsPerChannel = 16; 12.340 + streamFormat.mBytesPerPacket = 2 * streamFormat.mChannelsPerFrame; 12.341 + streamFormat.mBytesPerFrame = 2 * streamFormat.mChannelsPerFrame; 12.342 + break; 12.343 + } 12.344 + streamFormat.mFormatID = kAudioFormatLinearPCM; 12.345 + streamFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | 12.346 + kAudioFormatFlagsNativeEndian | 12.347 + kLinearPCMFormatFlagIsPacked; 12.348 + 12.349 + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &streamFormat, sizeof(AudioStreamBasicDescription)); 12.350 + if(err != noErr) 12.351 + { 12.352 + ERR("AudioUnitSetProperty failed\n"); 12.353 + return ALC_FALSE; 12.354 + } 12.355 + 12.356 + /* setup callback */ 12.357 + data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 12.358 + input.inputProc = ca_callback; 12.359 + input.inputProcRefCon = device; 12.360 + 12.361 + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &input, sizeof(AURenderCallbackStruct)); 12.362 + if(err != noErr) 12.363 + { 12.364 + ERR("AudioUnitSetProperty failed\n"); 12.365 + return ALC_FALSE; 12.366 + } 12.367 + 12.368 + return ALC_TRUE; 12.369 +} 12.370 + 12.371 +static void ca_stop_playback(ALCdevice *device) 12.372 +{ 12.373 + ca_data *data = (ca_data*)device->ExtraData; 12.374 + OSStatus err; 12.375 + 12.376 + AudioOutputUnitStop(data->audioUnit); 12.377 + err = AudioUnitUninitialize(data->audioUnit); 12.378 + if(err != noErr) 12.379 + ERR("-- AudioUnitUninitialize failed.\n"); 12.380 +} 12.381 + 12.382 +static ALCboolean ca_open_capture(ALCdevice *device, const ALCchar *deviceName) 12.383 +{ 12.384 + AudioStreamBasicDescription requestedFormat; // The application requested format 12.385 + AudioStreamBasicDescription hardwareFormat; // The hardware format 12.386 + AudioStreamBasicDescription outputFormat; // The AudioUnit output format 12.387 + AURenderCallbackStruct input; 12.388 + ComponentDescription desc; 12.389 + AudioDeviceID inputDevice; 12.390 + UInt32 outputFrameCount; 12.391 + UInt32 propertySize; 12.392 + UInt32 enableIO; 12.393 + Component comp; 12.394 + ca_data *data; 12.395 + OSStatus err; 12.396 + 12.397 + desc.componentType = kAudioUnitType_Output; 12.398 + desc.componentSubType = kAudioUnitSubType_HALOutput; 12.399 + desc.componentManufacturer = kAudioUnitManufacturer_Apple; 12.400 + desc.componentFlags = 0; 12.401 + desc.componentFlagsMask = 0; 12.402 + 12.403 + // Search for component with given description 12.404 + comp = FindNextComponent(NULL, &desc); 12.405 + if(comp == NULL) 12.406 + { 12.407 + ERR("FindNextComponent failed\n"); 12.408 + return ALC_FALSE; 12.409 + } 12.410 + 12.411 + data = calloc(1, sizeof(*data)); 12.412 + device->ExtraData = data; 12.413 + 12.414 + // Open the component 12.415 + err = OpenAComponent(comp, &data->audioUnit); 12.416 + if(err != noErr) 12.417 + { 12.418 + ERR("OpenAComponent failed\n"); 12.419 + goto error; 12.420 + } 12.421 + 12.422 + // Turn off AudioUnit output 12.423 + enableIO = 0; 12.424 + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, 0, &enableIO, sizeof(ALuint)); 12.425 + if(err != noErr) 12.426 + { 12.427 + ERR("AudioUnitSetProperty failed\n"); 12.428 + goto error; 12.429 + } 12.430 + 12.431 + // Turn on AudioUnit input 12.432 + enableIO = 1; 12.433 + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, 1, &enableIO, sizeof(ALuint)); 12.434 + if(err != noErr) 12.435 + { 12.436 + ERR("AudioUnitSetProperty failed\n"); 12.437 + goto error; 12.438 + } 12.439 + 12.440 + // Get the default input device 12.441 + propertySize = sizeof(AudioDeviceID); 12.442 + err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &propertySize, &inputDevice); 12.443 + if(err != noErr) 12.444 + { 12.445 + ERR("AudioHardwareGetProperty failed\n"); 12.446 + goto error; 12.447 + } 12.448 + 12.449 + if(inputDevice == kAudioDeviceUnknown) 12.450 + { 12.451 + ERR("No input device found\n"); 12.452 + goto error; 12.453 + } 12.454 + 12.455 + // Track the input device 12.456 + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &inputDevice, sizeof(AudioDeviceID)); 12.457 + if(err != noErr) 12.458 + { 12.459 + ERR("AudioUnitSetProperty failed\n"); 12.460 + goto error; 12.461 + } 12.462 + 12.463 + // set capture callback 12.464 + input.inputProc = ca_capture_callback; 12.465 + input.inputProcRefCon = device; 12.466 + 12.467 + err = AudioUnitSetProperty(data->audioUnit, kAudioOutputUnitProperty_SetInputCallback, kAudioUnitScope_Global, 0, &input, sizeof(AURenderCallbackStruct)); 12.468 + if(err != noErr) 12.469 + { 12.470 + ERR("AudioUnitSetProperty failed\n"); 12.471 + goto error; 12.472 + } 12.473 + 12.474 + // Initialize the device 12.475 + err = AudioUnitInitialize(data->audioUnit); 12.476 + if(err != noErr) 12.477 + { 12.478 + ERR("AudioUnitInitialize failed\n"); 12.479 + goto error; 12.480 + } 12.481 + 12.482 + // Get the hardware format 12.483 + propertySize = sizeof(AudioStreamBasicDescription); 12.484 + err = AudioUnitGetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 1, &hardwareFormat, &propertySize); 12.485 + if(err != noErr || propertySize != sizeof(AudioStreamBasicDescription)) 12.486 + { 12.487 + ERR("AudioUnitGetProperty failed\n"); 12.488 + goto error; 12.489 + } 12.490 + 12.491 + // Set up the requested format description 12.492 + switch(device->FmtType) 12.493 + { 12.494 + case DevFmtUByte: 12.495 + requestedFormat.mBitsPerChannel = 8; 12.496 + requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; 12.497 + break; 12.498 + case DevFmtShort: 12.499 + requestedFormat.mBitsPerChannel = 16; 12.500 + requestedFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagsNativeEndian | kAudioFormatFlagIsPacked; 12.501 + break; 12.502 + case DevFmtFloat: 12.503 + requestedFormat.mBitsPerChannel = 32; 12.504 + requestedFormat.mFormatFlags = kAudioFormatFlagIsPacked; 12.505 + break; 12.506 + case DevFmtByte: 12.507 + case DevFmtUShort: 12.508 + ERR("%s samples not supported\n", DevFmtTypeString(device->FmtType)); 12.509 + goto error; 12.510 + } 12.511 + 12.512 + switch(device->FmtChans) 12.513 + { 12.514 + case DevFmtMono: 12.515 + requestedFormat.mChannelsPerFrame = 1; 12.516 + break; 12.517 + case DevFmtStereo: 12.518 + requestedFormat.mChannelsPerFrame = 2; 12.519 + break; 12.520 + 12.521 + case DevFmtQuad: 12.522 + case DevFmtX51: 12.523 + case DevFmtX51Side: 12.524 + case DevFmtX61: 12.525 + case DevFmtX71: 12.526 + ERR("%s not supported\n", DevFmtChannelsString(device->FmtChans)); 12.527 + goto error; 12.528 + } 12.529 + 12.530 + requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8; 12.531 + requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame; 12.532 + requestedFormat.mSampleRate = device->Frequency; 12.533 + requestedFormat.mFormatID = kAudioFormatLinearPCM; 12.534 + requestedFormat.mReserved = 0; 12.535 + requestedFormat.mFramesPerPacket = 1; 12.536 + 12.537 + // save requested format description for later use 12.538 + data->format = requestedFormat; 12.539 + data->frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 12.540 + 12.541 + // Use intermediate format for sample rate conversion (outputFormat) 12.542 + // Set sample rate to the same as hardware for resampling later 12.543 + outputFormat = requestedFormat; 12.544 + outputFormat.mSampleRate = hardwareFormat.mSampleRate; 12.545 + 12.546 + // Determine sample rate ratio for resampling 12.547 + data->sampleRateRatio = outputFormat.mSampleRate / device->Frequency; 12.548 + 12.549 + // The output format should be the requested format, but using the hardware sample rate 12.550 + // This is because the AudioUnit will automatically scale other properties, except for sample rate 12.551 + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, (void *)&outputFormat, sizeof(outputFormat)); 12.552 + if(err != noErr) 12.553 + { 12.554 + ERR("AudioUnitSetProperty failed\n"); 12.555 + goto error; 12.556 + } 12.557 + 12.558 + // Set the AudioUnit output format frame count 12.559 + outputFrameCount = device->UpdateSize * data->sampleRateRatio; 12.560 + err = AudioUnitSetProperty(data->audioUnit, kAudioUnitProperty_MaximumFramesPerSlice, kAudioUnitScope_Output, 0, &outputFrameCount, sizeof(outputFrameCount)); 12.561 + if(err != noErr) 12.562 + { 12.563 + ERR("AudioUnitSetProperty failed: %d\n", err); 12.564 + goto error; 12.565 + } 12.566 + 12.567 + // Set up sample converter 12.568 + err = AudioConverterNew(&outputFormat, &requestedFormat, &data->audioConverter); 12.569 + if(err != noErr) 12.570 + { 12.571 + ERR("AudioConverterNew failed: %d\n", err); 12.572 + goto error; 12.573 + } 12.574 + 12.575 + // Create a buffer for use in the resample callback 12.576 + data->resampleBuffer = malloc(device->UpdateSize * data->frameSize * data->sampleRateRatio); 12.577 + 12.578 + // Allocate buffer for the AudioUnit output 12.579 + data->bufferList = allocate_buffer_list(outputFormat.mChannelsPerFrame, device->UpdateSize * data->frameSize * data->sampleRateRatio); 12.580 + if(data->bufferList == NULL) 12.581 + { 12.582 + alcSetError(device, ALC_OUT_OF_MEMORY); 12.583 + goto error; 12.584 + } 12.585 + 12.586 + data->ring = CreateRingBuffer(data->frameSize, (device->UpdateSize * data->sampleRateRatio) * device->NumUpdates); 12.587 + if(data->ring == NULL) 12.588 + { 12.589 + alcSetError(device, ALC_OUT_OF_MEMORY); 12.590 + goto error; 12.591 + } 12.592 + 12.593 + return ALC_TRUE; 12.594 + 12.595 +error: 12.596 + DestroyRingBuffer(data->ring); 12.597 + free(data->resampleBuffer); 12.598 + destroy_buffer_list(data->bufferList); 12.599 + 12.600 + if(data->audioConverter) 12.601 + AudioConverterDispose(data->audioConverter); 12.602 + if(data->audioUnit) 12.603 + CloseComponent(data->audioUnit); 12.604 + 12.605 + free(data); 12.606 + device->ExtraData = NULL; 12.607 + 12.608 + return ALC_FALSE; 12.609 +} 12.610 + 12.611 +static void ca_close_capture(ALCdevice *device) 12.612 +{ 12.613 + ca_data *data = (ca_data*)device->ExtraData; 12.614 + 12.615 + DestroyRingBuffer(data->ring); 12.616 + free(data->resampleBuffer); 12.617 + destroy_buffer_list(data->bufferList); 12.618 + 12.619 + AudioConverterDispose(data->audioConverter); 12.620 + CloseComponent(data->audioUnit); 12.621 + 12.622 + free(data); 12.623 + device->ExtraData = NULL; 12.624 +} 12.625 + 12.626 +static void ca_start_capture(ALCdevice *device) 12.627 +{ 12.628 + ca_data *data = (ca_data*)device->ExtraData; 12.629 + OSStatus err = AudioOutputUnitStart(data->audioUnit); 12.630 + if(err != noErr) 12.631 + ERR("AudioOutputUnitStart failed\n"); 12.632 +} 12.633 + 12.634 +static void ca_stop_capture(ALCdevice *device) 12.635 +{ 12.636 + ca_data *data = (ca_data*)device->ExtraData; 12.637 + OSStatus err = AudioOutputUnitStop(data->audioUnit); 12.638 + if(err != noErr) 12.639 + ERR("AudioOutputUnitStop failed\n"); 12.640 +} 12.641 + 12.642 +static ALCuint ca_available_samples(ALCdevice *device) 12.643 +{ 12.644 + ca_data *data = device->ExtraData; 12.645 + return RingBufferSize(data->ring) / data->sampleRateRatio; 12.646 +} 12.647 + 12.648 +static void ca_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) 12.649 +{ 12.650 + ca_data *data = (ca_data*)device->ExtraData; 12.651 + 12.652 + if(samples <= ca_available_samples(device)) 12.653 + { 12.654 + AudioBufferList *list; 12.655 + UInt32 frameCount; 12.656 + OSStatus err; 12.657 + 12.658 + // If no samples are requested, just return 12.659 + if(samples == 0) 12.660 + return; 12.661 + 12.662 + // Allocate a temporary AudioBufferList to use as the return resamples data 12.663 + list = alloca(sizeof(AudioBufferList) + sizeof(AudioBuffer)); 12.664 + 12.665 + // Point the resampling buffer to the capture buffer 12.666 + list->mNumberBuffers = 1; 12.667 + list->mBuffers[0].mNumberChannels = data->format.mChannelsPerFrame; 12.668 + list->mBuffers[0].mDataByteSize = samples * data->frameSize; 12.669 + list->mBuffers[0].mData = buffer; 12.670 + 12.671 + // Resample into another AudioBufferList 12.672 + frameCount = samples; 12.673 + err = AudioConverterFillComplexBuffer(data->audioConverter, ca_capture_conversion_callback, device, 12.674 + &frameCount, list, NULL); 12.675 + if(err != noErr) 12.676 + { 12.677 + ERR("AudioConverterFillComplexBuffer error: %d\n", err); 12.678 + alcSetError(device, ALC_INVALID_VALUE); 12.679 + } 12.680 + } 12.681 + else 12.682 + alcSetError(device, ALC_INVALID_VALUE); 12.683 +} 12.684 + 12.685 +static const BackendFuncs ca_funcs = { 12.686 + ca_open_playback, 12.687 + ca_close_playback, 12.688 + ca_reset_playback, 12.689 + ca_stop_playback, 12.690 + ca_open_capture, 12.691 + ca_close_capture, 12.692 + ca_start_capture, 12.693 + ca_stop_capture, 12.694 + ca_capture_samples, 12.695 + ca_available_samples 12.696 +}; 12.697 + 12.698 +ALCboolean alc_ca_init(BackendFuncs *func_list) 12.699 +{ 12.700 + *func_list = ca_funcs; 12.701 + return ALC_TRUE; 12.702 +} 12.703 + 12.704 +void alc_ca_deinit(void) 12.705 +{ 12.706 +} 12.707 + 12.708 +void alc_ca_probe(enum DevProbe type) 12.709 +{ 12.710 + switch(type) 12.711 + { 12.712 + case DEVICE_PROBE: 12.713 + AppendDeviceList(ca_device); 12.714 + break; 12.715 + case ALL_DEVICE_PROBE: 12.716 + AppendAllDeviceList(ca_device); 12.717 + break; 12.718 + case CAPTURE_DEVICE_PROBE: 12.719 + AppendCaptureDeviceList(ca_device); 12.720 + break; 12.721 + } 12.722 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 13.2 +++ b/Alc/backends/dsound.c Tue Oct 25 13:02:31 2011 -0700 13.3 @@ -0,0 +1,614 @@ 13.4 +/** 13.5 + * OpenAL cross platform audio library 13.6 + * Copyright (C) 1999-2007 by authors. 13.7 + * This library is free software; you can redistribute it and/or 13.8 + * modify it under the terms of the GNU Library General Public 13.9 + * License as published by the Free Software Foundation; either 13.10 + * version 2 of the License, or (at your option) any later version. 13.11 + * 13.12 + * This library is distributed in the hope that it will be useful, 13.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13.15 + * Library General Public License for more details. 13.16 + * 13.17 + * You should have received a copy of the GNU Library General Public 13.18 + * License along with this library; if not, write to the 13.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 13.20 + * Boston, MA 02111-1307, USA. 13.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 13.22 + */ 13.23 + 13.24 +#include "config.h" 13.25 + 13.26 +#define _WIN32_WINNT 0x0500 13.27 +#include <stdlib.h> 13.28 +#include <stdio.h> 13.29 +#include <memory.h> 13.30 + 13.31 +#include <dsound.h> 13.32 +#include <cguid.h> 13.33 +#include <mmreg.h> 13.34 +#ifndef _WAVEFORMATEXTENSIBLE_ 13.35 +#include <ks.h> 13.36 +#include <ksmedia.h> 13.37 +#endif 13.38 + 13.39 +#include "alMain.h" 13.40 +#include "AL/al.h" 13.41 +#include "AL/alc.h" 13.42 + 13.43 +#ifndef DSSPEAKER_5POINT1 13.44 +#define DSSPEAKER_5POINT1 6 13.45 +#endif 13.46 +#ifndef DSSPEAKER_7POINT1 13.47 +#define DSSPEAKER_7POINT1 7 13.48 +#endif 13.49 + 13.50 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 13.51 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 13.52 + 13.53 + 13.54 +static HMODULE ds_handle; 13.55 +static HRESULT (WINAPI *pDirectSoundCreate)(LPCGUID pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); 13.56 +static HRESULT (WINAPI *pDirectSoundEnumerateA)(LPDSENUMCALLBACKA pDSEnumCallback, void *pContext); 13.57 + 13.58 +#define DirectSoundCreate pDirectSoundCreate 13.59 +#define DirectSoundEnumerateA pDirectSoundEnumerateA 13.60 + 13.61 + 13.62 +typedef struct { 13.63 + // DirectSound Playback Device 13.64 + IDirectSound *lpDS; 13.65 + IDirectSoundBuffer *DSpbuffer; 13.66 + IDirectSoundBuffer *DSsbuffer; 13.67 + IDirectSoundNotify *DSnotify; 13.68 + HANDLE hNotifyEvent; 13.69 + 13.70 + volatile int killNow; 13.71 + ALvoid *thread; 13.72 +} DSoundData; 13.73 + 13.74 + 13.75 +typedef struct { 13.76 + ALCchar *name; 13.77 + GUID guid; 13.78 +} DevMap; 13.79 + 13.80 +static const ALCchar dsDevice[] = "DirectSound Default"; 13.81 +static DevMap *DeviceList; 13.82 +static ALuint NumDevices; 13.83 + 13.84 +#define MAX_UPDATES 128 13.85 + 13.86 +static ALCboolean DSoundLoad(void) 13.87 +{ 13.88 + ALCboolean ok = ALC_TRUE; 13.89 + if(!ds_handle) 13.90 + { 13.91 + ds_handle = LoadLibraryA("dsound.dll"); 13.92 + if(ds_handle == NULL) 13.93 + { 13.94 + ERR("Failed to load dsound.dll\n"); 13.95 + return ALC_FALSE; 13.96 + } 13.97 + 13.98 +#define LOAD_FUNC(x) do { \ 13.99 + if((p##x = (void*)GetProcAddress(ds_handle, #x)) == NULL) { \ 13.100 + ERR("Could not load %s from dsound.dll\n", #x); \ 13.101 + ok = ALC_FALSE; \ 13.102 + } \ 13.103 +} while(0) 13.104 + LOAD_FUNC(DirectSoundCreate); 13.105 + LOAD_FUNC(DirectSoundEnumerateA); 13.106 +#undef LOAD_FUNC 13.107 + 13.108 + if(!ok) 13.109 + { 13.110 + FreeLibrary(ds_handle); 13.111 + ds_handle = NULL; 13.112 + } 13.113 + } 13.114 + return ok; 13.115 +} 13.116 + 13.117 + 13.118 +static BOOL CALLBACK DSoundEnumDevices(LPGUID guid, LPCSTR desc, LPCSTR drvname, LPVOID data) 13.119 +{ 13.120 + char str[1024]; 13.121 + void *temp; 13.122 + int count; 13.123 + ALuint i; 13.124 + 13.125 + (void)data; 13.126 + (void)drvname; 13.127 + 13.128 + if(!guid) 13.129 + return TRUE; 13.130 + 13.131 + count = 0; 13.132 + do { 13.133 + if(count == 0) 13.134 + snprintf(str, sizeof(str), "%s", desc); 13.135 + else 13.136 + snprintf(str, sizeof(str), "%s #%d", desc, count+1); 13.137 + count++; 13.138 + 13.139 + for(i = 0;i < NumDevices;i++) 13.140 + { 13.141 + if(strcmp(str, DeviceList[i].name) == 0) 13.142 + break; 13.143 + } 13.144 + } while(i != NumDevices); 13.145 + 13.146 + temp = realloc(DeviceList, sizeof(DevMap) * (NumDevices+1)); 13.147 + if(temp) 13.148 + { 13.149 + DeviceList = temp; 13.150 + DeviceList[NumDevices].name = strdup(str); 13.151 + DeviceList[NumDevices].guid = *guid; 13.152 + NumDevices++; 13.153 + } 13.154 + 13.155 + return TRUE; 13.156 +} 13.157 + 13.158 + 13.159 +static ALuint DSoundProc(ALvoid *ptr) 13.160 +{ 13.161 + ALCdevice *pDevice = (ALCdevice*)ptr; 13.162 + DSoundData *pData = (DSoundData*)pDevice->ExtraData; 13.163 + DSBCAPS DSBCaps; 13.164 + DWORD LastCursor = 0; 13.165 + DWORD PlayCursor; 13.166 + VOID *WritePtr1, *WritePtr2; 13.167 + DWORD WriteCnt1, WriteCnt2; 13.168 + BOOL Playing = FALSE; 13.169 + DWORD FrameSize; 13.170 + DWORD FragSize; 13.171 + DWORD avail; 13.172 + HRESULT err; 13.173 + 13.174 + SetRTPriority(); 13.175 + 13.176 + memset(&DSBCaps, 0, sizeof(DSBCaps)); 13.177 + DSBCaps.dwSize = sizeof(DSBCaps); 13.178 + err = IDirectSoundBuffer_GetCaps(pData->DSsbuffer, &DSBCaps); 13.179 + if(FAILED(err)) 13.180 + { 13.181 + ERR("Failed to get buffer caps: 0x%lx\n", err); 13.182 + aluHandleDisconnect(pDevice); 13.183 + return 1; 13.184 + } 13.185 + 13.186 + FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 13.187 + FragSize = pDevice->UpdateSize * FrameSize; 13.188 + 13.189 + IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL); 13.190 + while(!pData->killNow) 13.191 + { 13.192 + // Get current play cursor 13.193 + IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL); 13.194 + avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; 13.195 + 13.196 + if(avail < FragSize) 13.197 + { 13.198 + if(!Playing) 13.199 + { 13.200 + err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING); 13.201 + if(FAILED(err)) 13.202 + { 13.203 + ERR("Failed to play buffer: 0x%lx\n", err); 13.204 + aluHandleDisconnect(pDevice); 13.205 + return 1; 13.206 + } 13.207 + Playing = TRUE; 13.208 + } 13.209 + 13.210 + avail = WaitForSingleObjectEx(pData->hNotifyEvent, 2000, FALSE); 13.211 + if(avail != WAIT_OBJECT_0) 13.212 + ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); 13.213 + continue; 13.214 + } 13.215 + avail -= avail%FragSize; 13.216 + 13.217 + // Lock output buffer 13.218 + WriteCnt1 = 0; 13.219 + WriteCnt2 = 0; 13.220 + err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); 13.221 + 13.222 + // If the buffer is lost, restore it and lock 13.223 + if(err == DSERR_BUFFERLOST) 13.224 + { 13.225 + WARN("Buffer lost, restoring...\n"); 13.226 + err = IDirectSoundBuffer_Restore(pData->DSsbuffer); 13.227 + if(SUCCEEDED(err)) 13.228 + { 13.229 + Playing = FALSE; 13.230 + LastCursor = 0; 13.231 + err = IDirectSoundBuffer_Lock(pData->DSsbuffer, 0, DSBCaps.dwBufferBytes, &WritePtr1, &WriteCnt1, &WritePtr2, &WriteCnt2, 0); 13.232 + } 13.233 + } 13.234 + 13.235 + // Successfully locked the output buffer 13.236 + if(SUCCEEDED(err)) 13.237 + { 13.238 + // If we have an active context, mix data directly into output buffer otherwise fill with silence 13.239 + aluMixData(pDevice, WritePtr1, WriteCnt1/FrameSize); 13.240 + aluMixData(pDevice, WritePtr2, WriteCnt2/FrameSize); 13.241 + 13.242 + // Unlock output buffer only when successfully locked 13.243 + IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); 13.244 + } 13.245 + else 13.246 + { 13.247 + ERR("Buffer lock error: %#lx\n", err); 13.248 + aluHandleDisconnect(pDevice); 13.249 + return 1; 13.250 + } 13.251 + 13.252 + // Update old write cursor location 13.253 + LastCursor += WriteCnt1+WriteCnt2; 13.254 + LastCursor %= DSBCaps.dwBufferBytes; 13.255 + } 13.256 + 13.257 + return 0; 13.258 +} 13.259 + 13.260 +static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) 13.261 +{ 13.262 + DSoundData *pData = NULL; 13.263 + LPGUID guid = NULL; 13.264 + HRESULT hr; 13.265 + 13.266 + if(!deviceName) 13.267 + deviceName = dsDevice; 13.268 + else if(strcmp(deviceName, dsDevice) != 0) 13.269 + { 13.270 + ALuint i; 13.271 + 13.272 + if(!DeviceList) 13.273 + { 13.274 + hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL); 13.275 + if(FAILED(hr)) 13.276 + ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); 13.277 + } 13.278 + 13.279 + for(i = 0;i < NumDevices;i++) 13.280 + { 13.281 + if(strcmp(deviceName, DeviceList[i].name) == 0) 13.282 + { 13.283 + guid = &DeviceList[i].guid; 13.284 + break; 13.285 + } 13.286 + } 13.287 + if(i == NumDevices) 13.288 + return ALC_FALSE; 13.289 + } 13.290 + 13.291 + //Initialise requested device 13.292 + pData = calloc(1, sizeof(DSoundData)); 13.293 + if(!pData) 13.294 + { 13.295 + alcSetError(device, ALC_OUT_OF_MEMORY); 13.296 + return ALC_FALSE; 13.297 + } 13.298 + 13.299 + hr = DS_OK; 13.300 + pData->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 13.301 + if(pData->hNotifyEvent == NULL) 13.302 + hr = E_FAIL; 13.303 + 13.304 + //DirectSound Init code 13.305 + if(SUCCEEDED(hr)) 13.306 + hr = DirectSoundCreate(guid, &pData->lpDS, NULL); 13.307 + if(SUCCEEDED(hr)) 13.308 + hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY); 13.309 + if(FAILED(hr)) 13.310 + { 13.311 + if(pData->lpDS) 13.312 + IDirectSound_Release(pData->lpDS); 13.313 + if(pData->hNotifyEvent) 13.314 + CloseHandle(pData->hNotifyEvent); 13.315 + free(pData); 13.316 + ERR("Device init failed: 0x%08lx\n", hr); 13.317 + return ALC_FALSE; 13.318 + } 13.319 + 13.320 + device->szDeviceName = strdup(deviceName); 13.321 + device->ExtraData = pData; 13.322 + return ALC_TRUE; 13.323 +} 13.324 + 13.325 +static void DSoundClosePlayback(ALCdevice *device) 13.326 +{ 13.327 + DSoundData *pData = device->ExtraData; 13.328 + 13.329 + IDirectSound_Release(pData->lpDS); 13.330 + CloseHandle(pData->hNotifyEvent); 13.331 + free(pData); 13.332 + device->ExtraData = NULL; 13.333 +} 13.334 + 13.335 +static ALCboolean DSoundResetPlayback(ALCdevice *device) 13.336 +{ 13.337 + DSoundData *pData = (DSoundData*)device->ExtraData; 13.338 + DSBUFFERDESC DSBDescription; 13.339 + WAVEFORMATEXTENSIBLE OutputType; 13.340 + DWORD speakers; 13.341 + HRESULT hr; 13.342 + 13.343 + memset(&OutputType, 0, sizeof(OutputType)); 13.344 + 13.345 + switch(device->FmtType) 13.346 + { 13.347 + case DevFmtByte: 13.348 + device->FmtType = DevFmtUByte; 13.349 + break; 13.350 + case DevFmtUShort: 13.351 + device->FmtType = DevFmtShort; 13.352 + break; 13.353 + case DevFmtUByte: 13.354 + case DevFmtShort: 13.355 + case DevFmtFloat: 13.356 + break; 13.357 + } 13.358 + 13.359 + hr = IDirectSound_GetSpeakerConfig(pData->lpDS, &speakers); 13.360 + if(SUCCEEDED(hr)) 13.361 + { 13.362 + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) 13.363 + { 13.364 + speakers = DSSPEAKER_CONFIG(speakers); 13.365 + if(speakers == DSSPEAKER_MONO) 13.366 + device->FmtChans = DevFmtMono; 13.367 + else if(speakers == DSSPEAKER_STEREO || speakers == DSSPEAKER_HEADPHONE) 13.368 + device->FmtChans = DevFmtStereo; 13.369 + else if(speakers == DSSPEAKER_QUAD) 13.370 + device->FmtChans = DevFmtQuad; 13.371 + else if(speakers == DSSPEAKER_5POINT1) 13.372 + device->FmtChans = DevFmtX51; 13.373 + else if(speakers == DSSPEAKER_7POINT1) 13.374 + device->FmtChans = DevFmtX71; 13.375 + else 13.376 + ERR("Unknown system speaker config: 0x%lx\n", speakers); 13.377 + } 13.378 + 13.379 + switch(device->FmtChans) 13.380 + { 13.381 + case DevFmtMono: 13.382 + OutputType.dwChannelMask = SPEAKER_FRONT_CENTER; 13.383 + break; 13.384 + case DevFmtStereo: 13.385 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 13.386 + SPEAKER_FRONT_RIGHT; 13.387 + break; 13.388 + case DevFmtQuad: 13.389 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 13.390 + SPEAKER_FRONT_RIGHT | 13.391 + SPEAKER_BACK_LEFT | 13.392 + SPEAKER_BACK_RIGHT; 13.393 + break; 13.394 + case DevFmtX51: 13.395 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 13.396 + SPEAKER_FRONT_RIGHT | 13.397 + SPEAKER_FRONT_CENTER | 13.398 + SPEAKER_LOW_FREQUENCY | 13.399 + SPEAKER_BACK_LEFT | 13.400 + SPEAKER_BACK_RIGHT; 13.401 + break; 13.402 + case DevFmtX51Side: 13.403 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 13.404 + SPEAKER_FRONT_RIGHT | 13.405 + SPEAKER_FRONT_CENTER | 13.406 + SPEAKER_LOW_FREQUENCY | 13.407 + SPEAKER_SIDE_LEFT | 13.408 + SPEAKER_SIDE_RIGHT; 13.409 + break; 13.410 + case DevFmtX61: 13.411 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 13.412 + SPEAKER_FRONT_RIGHT | 13.413 + SPEAKER_FRONT_CENTER | 13.414 + SPEAKER_LOW_FREQUENCY | 13.415 + SPEAKER_BACK_CENTER | 13.416 + SPEAKER_SIDE_LEFT | 13.417 + SPEAKER_SIDE_RIGHT; 13.418 + break; 13.419 + case DevFmtX71: 13.420 + OutputType.dwChannelMask = SPEAKER_FRONT_LEFT | 13.421 + SPEAKER_FRONT_RIGHT | 13.422 + SPEAKER_FRONT_CENTER | 13.423 + SPEAKER_LOW_FREQUENCY | 13.424 + SPEAKER_BACK_LEFT | 13.425 + SPEAKER_BACK_RIGHT | 13.426 + SPEAKER_SIDE_LEFT | 13.427 + SPEAKER_SIDE_RIGHT; 13.428 + break; 13.429 + } 13.430 + 13.431 + OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; 13.432 + OutputType.Format.nChannels = ChannelsFromDevFmt(device->FmtChans); 13.433 + OutputType.Format.wBitsPerSample = BytesFromDevFmt(device->FmtType) * 8; 13.434 + OutputType.Format.nBlockAlign = OutputType.Format.nChannels*OutputType.Format.wBitsPerSample/8; 13.435 + OutputType.Format.nSamplesPerSec = device->Frequency; 13.436 + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec*OutputType.Format.nBlockAlign; 13.437 + OutputType.Format.cbSize = 0; 13.438 + } 13.439 + 13.440 + if(OutputType.Format.nChannels > 2 || device->FmtType == DevFmtFloat) 13.441 + { 13.442 + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 13.443 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 13.444 + OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); 13.445 + if(device->FmtType == DevFmtFloat) 13.446 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; 13.447 + else 13.448 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 13.449 + } 13.450 + else 13.451 + { 13.452 + if(SUCCEEDED(hr)) 13.453 + { 13.454 + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); 13.455 + DSBDescription.dwSize=sizeof(DSBUFFERDESC); 13.456 + DSBDescription.dwFlags=DSBCAPS_PRIMARYBUFFER; 13.457 + hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSpbuffer, NULL); 13.458 + } 13.459 + if(SUCCEEDED(hr)) 13.460 + hr = IDirectSoundBuffer_SetFormat(pData->DSpbuffer,&OutputType.Format); 13.461 + } 13.462 + 13.463 + if(SUCCEEDED(hr)) 13.464 + { 13.465 + if(device->NumUpdates > MAX_UPDATES) 13.466 + { 13.467 + device->UpdateSize = (device->UpdateSize*device->NumUpdates + 13.468 + MAX_UPDATES-1) / MAX_UPDATES; 13.469 + device->NumUpdates = MAX_UPDATES; 13.470 + } 13.471 + 13.472 + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); 13.473 + DSBDescription.dwSize=sizeof(DSBUFFERDESC); 13.474 + DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; 13.475 + DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * 13.476 + OutputType.Format.nBlockAlign; 13.477 + DSBDescription.lpwfxFormat=&OutputType.Format; 13.478 + hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); 13.479 + } 13.480 + 13.481 + if(SUCCEEDED(hr)) 13.482 + { 13.483 + hr = IDirectSoundBuffer_QueryInterface(pData->DSsbuffer, &IID_IDirectSoundNotify, (LPVOID *)&pData->DSnotify); 13.484 + if(SUCCEEDED(hr)) 13.485 + { 13.486 + DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; 13.487 + ALuint i; 13.488 + 13.489 + for(i = 0;i < device->NumUpdates;++i) 13.490 + { 13.491 + notifies[i].dwOffset = i * device->UpdateSize * 13.492 + OutputType.Format.nBlockAlign; 13.493 + notifies[i].hEventNotify = pData->hNotifyEvent; 13.494 + } 13.495 + if(IDirectSoundNotify_SetNotificationPositions(pData->DSnotify, device->NumUpdates, notifies) != DS_OK) 13.496 + hr = E_FAIL; 13.497 + } 13.498 + } 13.499 + 13.500 + if(SUCCEEDED(hr)) 13.501 + { 13.502 + ResetEvent(pData->hNotifyEvent); 13.503 + SetDefaultWFXChannelOrder(device); 13.504 + pData->thread = StartThread(DSoundProc, device); 13.505 + if(pData->thread == NULL) 13.506 + hr = E_FAIL; 13.507 + } 13.508 + 13.509 + if(FAILED(hr)) 13.510 + { 13.511 + if(pData->DSnotify != NULL) 13.512 + IDirectSoundNotify_Release(pData->DSnotify); 13.513 + pData->DSnotify = NULL; 13.514 + if(pData->DSsbuffer != NULL) 13.515 + IDirectSoundBuffer_Release(pData->DSsbuffer); 13.516 + pData->DSsbuffer = NULL; 13.517 + if(pData->DSpbuffer != NULL) 13.518 + IDirectSoundBuffer_Release(pData->DSpbuffer); 13.519 + pData->DSpbuffer = NULL; 13.520 + return ALC_FALSE; 13.521 + } 13.522 + 13.523 + return ALC_TRUE; 13.524 +} 13.525 + 13.526 +static void DSoundStopPlayback(ALCdevice *device) 13.527 +{ 13.528 + DSoundData *pData = device->ExtraData; 13.529 + 13.530 + if(!pData->thread) 13.531 + return; 13.532 + 13.533 + pData->killNow = 1; 13.534 + StopThread(pData->thread); 13.535 + pData->thread = NULL; 13.536 + 13.537 + pData->killNow = 0; 13.538 + 13.539 + IDirectSoundNotify_Release(pData->DSnotify); 13.540 + pData->DSnotify = NULL; 13.541 + IDirectSoundBuffer_Release(pData->DSsbuffer); 13.542 + pData->DSsbuffer = NULL; 13.543 + if(pData->DSpbuffer != NULL) 13.544 + IDirectSoundBuffer_Release(pData->DSpbuffer); 13.545 + pData->DSpbuffer = NULL; 13.546 +} 13.547 + 13.548 + 13.549 +static const BackendFuncs DSoundFuncs = { 13.550 + DSoundOpenPlayback, 13.551 + DSoundClosePlayback, 13.552 + DSoundResetPlayback, 13.553 + DSoundStopPlayback, 13.554 + NULL, 13.555 + NULL, 13.556 + NULL, 13.557 + NULL, 13.558 + NULL, 13.559 + NULL 13.560 +}; 13.561 + 13.562 + 13.563 +ALCboolean alcDSoundInit(BackendFuncs *FuncList) 13.564 +{ 13.565 + if(!DSoundLoad()) 13.566 + return ALC_FALSE; 13.567 + *FuncList = DSoundFuncs; 13.568 + return ALC_TRUE; 13.569 +} 13.570 + 13.571 +void alcDSoundDeinit(void) 13.572 +{ 13.573 + ALuint i; 13.574 + 13.575 + for(i = 0;i < NumDevices;++i) 13.576 + free(DeviceList[i].name); 13.577 + free(DeviceList); 13.578 + DeviceList = NULL; 13.579 + NumDevices = 0; 13.580 + 13.581 + if(ds_handle) 13.582 + FreeLibrary(ds_handle); 13.583 + ds_handle = NULL; 13.584 +} 13.585 + 13.586 +void alcDSoundProbe(enum DevProbe type) 13.587 +{ 13.588 + HRESULT hr; 13.589 + ALuint i; 13.590 + 13.591 + switch(type) 13.592 + { 13.593 + case DEVICE_PROBE: 13.594 + AppendDeviceList(dsDevice); 13.595 + break; 13.596 + 13.597 + case ALL_DEVICE_PROBE: 13.598 + for(i = 0;i < NumDevices;++i) 13.599 + free(DeviceList[i].name); 13.600 + free(DeviceList); 13.601 + DeviceList = NULL; 13.602 + NumDevices = 0; 13.603 + 13.604 + hr = DirectSoundEnumerateA(DSoundEnumDevices, NULL); 13.605 + if(FAILED(hr)) 13.606 + ERR("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); 13.607 + else 13.608 + { 13.609 + for(i = 0;i < NumDevices;i++) 13.610 + AppendAllDeviceList(DeviceList[i].name); 13.611 + } 13.612 + break; 13.613 + 13.614 + case CAPTURE_DEVICE_PROBE: 13.615 + break; 13.616 + } 13.617 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 14.2 +++ b/Alc/backends/loopback.c Tue Oct 25 13:02:31 2011 -0700 14.3 @@ -0,0 +1,77 @@ 14.4 +/** 14.5 + * OpenAL cross platform audio library 14.6 + * Copyright (C) 2011 by Chris Robinson 14.7 + * This library is free software; you can redistribute it and/or 14.8 + * modify it under the terms of the GNU Library General Public 14.9 + * License as published by the Free Software Foundation; either 14.10 + * version 2 of the License, or (at your option) any later version. 14.11 + * 14.12 + * This library is distributed in the hope that it will be useful, 14.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 14.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14.15 + * Library General Public License for more details. 14.16 + * 14.17 + * You should have received a copy of the GNU Library General Public 14.18 + * License along with this library; if not, write to the 14.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 14.20 + * Boston, MA 02111-1307, USA. 14.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 14.22 + */ 14.23 + 14.24 +#include "config.h" 14.25 + 14.26 +#include <stdlib.h> 14.27 +#include "alMain.h" 14.28 +#include "AL/al.h" 14.29 +#include "AL/alc.h" 14.30 + 14.31 + 14.32 +static ALCboolean loopback_open_playback(ALCdevice *device, const ALCchar *deviceName) 14.33 +{ 14.34 + device->szDeviceName = strdup(deviceName); 14.35 + return ALC_TRUE; 14.36 +} 14.37 + 14.38 +static void loopback_close_playback(ALCdevice *device) 14.39 +{ 14.40 + (void)device; 14.41 +} 14.42 + 14.43 +static ALCboolean loopback_reset_playback(ALCdevice *device) 14.44 +{ 14.45 + SetDefaultWFXChannelOrder(device); 14.46 + return ALC_TRUE; 14.47 +} 14.48 + 14.49 +static void loopback_stop_playback(ALCdevice *device) 14.50 +{ 14.51 + (void)device; 14.52 +} 14.53 + 14.54 +static const BackendFuncs loopback_funcs = { 14.55 + loopback_open_playback, 14.56 + loopback_close_playback, 14.57 + loopback_reset_playback, 14.58 + loopback_stop_playback, 14.59 + NULL, 14.60 + NULL, 14.61 + NULL, 14.62 + NULL, 14.63 + NULL, 14.64 + NULL 14.65 +}; 14.66 + 14.67 +ALCboolean alc_loopback_init(BackendFuncs *func_list) 14.68 +{ 14.69 + *func_list = loopback_funcs; 14.70 + return ALC_TRUE; 14.71 +} 14.72 + 14.73 +void alc_loopback_deinit(void) 14.74 +{ 14.75 +} 14.76 + 14.77 +void alc_loopback_probe(enum DevProbe type) 14.78 +{ 14.79 + (void)type; 14.80 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 15.2 +++ b/Alc/backends/mmdevapi.c Tue Oct 25 13:02:31 2011 -0700 15.3 @@ -0,0 +1,775 @@ 15.4 +/** 15.5 + * OpenAL cross platform audio library 15.6 + * Copyright (C) 2011 by authors. 15.7 + * This library is free software; you can redistribute it and/or 15.8 + * modify it under the terms of the GNU Library General Public 15.9 + * License as published by the Free Software Foundation; either 15.10 + * version 2 of the License, or (at your option) any later version. 15.11 + * 15.12 + * This library is distributed in the hope that it will be useful, 15.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 15.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15.15 + * Library General Public License for more details. 15.16 + * 15.17 + * You should have received a copy of the GNU Library General Public 15.18 + * License along with this library; if not, write to the 15.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 15.20 + * Boston, MA 02111-1307, USA. 15.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 15.22 + */ 15.23 + 15.24 +#include "config.h" 15.25 + 15.26 +#define COBJMACROS 15.27 +#define _WIN32_WINNT 0x0500 15.28 +#include <stdlib.h> 15.29 +#include <stdio.h> 15.30 +#include <memory.h> 15.31 + 15.32 +#include <mmdeviceapi.h> 15.33 +#include <audioclient.h> 15.34 +#include <cguid.h> 15.35 +#include <mmreg.h> 15.36 +#ifndef _WAVEFORMATEXTENSIBLE_ 15.37 +#include <ks.h> 15.38 +#include <ksmedia.h> 15.39 +#endif 15.40 + 15.41 +#include "alMain.h" 15.42 +#include "AL/al.h" 15.43 +#include "AL/alc.h" 15.44 + 15.45 + 15.46 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 15.47 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 15.48 + 15.49 +#define MONO SPEAKER_FRONT_CENTER 15.50 +#define STEREO (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT) 15.51 +#define QUAD (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) 15.52 +#define X5DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT) 15.53 +#define X5DOT1SIDE (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) 15.54 +#define X6DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_CENTER|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) 15.55 +#define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) 15.56 + 15.57 + 15.58 +typedef struct { 15.59 + IMMDevice *mmdev; 15.60 + IAudioClient *client; 15.61 + HANDLE hNotifyEvent; 15.62 + 15.63 + HANDLE MsgEvent; 15.64 + 15.65 + volatile int killNow; 15.66 + ALvoid *thread; 15.67 +} MMDevApiData; 15.68 + 15.69 + 15.70 +static const ALCchar mmDevice[] = "WASAPI Default"; 15.71 + 15.72 + 15.73 +static HANDLE ThreadHdl; 15.74 +static DWORD ThreadID; 15.75 + 15.76 +typedef struct { 15.77 + HANDLE FinishedEvt; 15.78 + HRESULT result; 15.79 +} ThreadRequest; 15.80 + 15.81 +#define WM_USER_OpenDevice (WM_USER+0) 15.82 +#define WM_USER_ResetDevice (WM_USER+1) 15.83 +#define WM_USER_StopDevice (WM_USER+2) 15.84 +#define WM_USER_CloseDevice (WM_USER+3) 15.85 + 15.86 +static HRESULT WaitForResponse(ThreadRequest *req) 15.87 +{ 15.88 + if(WaitForSingleObject(req->FinishedEvt, INFINITE) == WAIT_OBJECT_0) 15.89 + return req->result; 15.90 + ERR("Message response error: %lu\n", GetLastError()); 15.91 + return E_FAIL; 15.92 +} 15.93 + 15.94 + 15.95 +static ALuint MMDevApiProc(ALvoid *ptr) 15.96 +{ 15.97 + ALCdevice *device = ptr; 15.98 + MMDevApiData *data = device->ExtraData; 15.99 + union { 15.100 + IAudioRenderClient *iface; 15.101 + void *ptr; 15.102 + } render; 15.103 + UINT32 written, len; 15.104 + BYTE *buffer; 15.105 + HRESULT hr; 15.106 + 15.107 + hr = CoInitialize(NULL); 15.108 + if(FAILED(hr)) 15.109 + { 15.110 + ERR("CoInitialize(NULL) failed: 0x%08lx\n", hr); 15.111 + aluHandleDisconnect(device); 15.112 + return 0; 15.113 + } 15.114 + 15.115 + hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &render.ptr); 15.116 + if(FAILED(hr)) 15.117 + { 15.118 + ERR("Failed to get AudioRenderClient service: 0x%08lx\n", hr); 15.119 + aluHandleDisconnect(device); 15.120 + return 0; 15.121 + } 15.122 + 15.123 + SetRTPriority(); 15.124 + 15.125 + while(!data->killNow) 15.126 + { 15.127 + hr = IAudioClient_GetCurrentPadding(data->client, &written); 15.128 + if(FAILED(hr)) 15.129 + { 15.130 + ERR("Failed to get padding: 0x%08lx\n", hr); 15.131 + aluHandleDisconnect(device); 15.132 + break; 15.133 + } 15.134 + 15.135 + len = device->UpdateSize*device->NumUpdates - written; 15.136 + if(len < device->UpdateSize) 15.137 + { 15.138 + DWORD res; 15.139 + res = WaitForSingleObjectEx(data->hNotifyEvent, 2000, FALSE); 15.140 + if(res != WAIT_OBJECT_0) 15.141 + ERR("WaitForSingleObjectEx error: 0x%lx\n", res); 15.142 + continue; 15.143 + } 15.144 + len -= len%device->UpdateSize; 15.145 + 15.146 + hr = IAudioRenderClient_GetBuffer(render.iface, len, &buffer); 15.147 + if(SUCCEEDED(hr)) 15.148 + { 15.149 + aluMixData(device, buffer, len); 15.150 + hr = IAudioRenderClient_ReleaseBuffer(render.iface, len, 0); 15.151 + } 15.152 + if(FAILED(hr)) 15.153 + { 15.154 + ERR("Failed to buffer data: 0x%08lx\n", hr); 15.155 + aluHandleDisconnect(device); 15.156 + break; 15.157 + } 15.158 + } 15.159 + 15.160 + IAudioRenderClient_Release(render.iface); 15.161 + 15.162 + CoUninitialize(); 15.163 + return 0; 15.164 +} 15.165 + 15.166 + 15.167 +static ALCboolean MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) 15.168 +{ 15.169 + memset(out, 0, sizeof(*out)); 15.170 + if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) 15.171 + *out = *(WAVEFORMATEXTENSIBLE*)in; 15.172 + else if(in->wFormatTag == WAVE_FORMAT_PCM) 15.173 + { 15.174 + out->Format = *in; 15.175 + out->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 15.176 + out->Format.cbSize = sizeof(*out) - sizeof(*in); 15.177 + if(out->Format.nChannels == 1) 15.178 + out->dwChannelMask = MONO; 15.179 + else if(out->Format.nChannels == 2) 15.180 + out->dwChannelMask = STEREO; 15.181 + else 15.182 + ERR("Unhandled PCM channel count: %d\n", out->Format.nChannels); 15.183 + out->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 15.184 + } 15.185 + else if(in->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) 15.186 + { 15.187 + out->Format = *in; 15.188 + out->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; 15.189 + out->Format.cbSize = sizeof(*out) - sizeof(*in); 15.190 + if(out->Format.nChannels == 1) 15.191 + out->dwChannelMask = MONO; 15.192 + else if(out->Format.nChannels == 2) 15.193 + out->dwChannelMask = STEREO; 15.194 + else 15.195 + ERR("Unhandled IEEE float channel count: %d\n", out->Format.nChannels); 15.196 + out->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; 15.197 + } 15.198 + else 15.199 + { 15.200 + ERR("Unhandled format tag: 0x%04x\n", in->wFormatTag); 15.201 + return ALC_FALSE; 15.202 + } 15.203 + return ALC_TRUE; 15.204 +} 15.205 + 15.206 +static HRESULT DoReset(ALCdevice *device) 15.207 +{ 15.208 + MMDevApiData *data = device->ExtraData; 15.209 + WAVEFORMATEXTENSIBLE OutputType; 15.210 + WAVEFORMATEX *wfx = NULL; 15.211 + REFERENCE_TIME min_per; 15.212 + UINT32 buffer_len, min_len; 15.213 + HRESULT hr; 15.214 + 15.215 + hr = IAudioClient_GetMixFormat(data->client, &wfx); 15.216 + if(FAILED(hr)) 15.217 + { 15.218 + ERR("Failed to get mix format: 0x%08lx\n", hr); 15.219 + return hr; 15.220 + } 15.221 + 15.222 + if(!MakeExtensible(&OutputType, wfx)) 15.223 + { 15.224 + CoTaskMemFree(wfx); 15.225 + return E_FAIL; 15.226 + } 15.227 + CoTaskMemFree(wfx); 15.228 + wfx = NULL; 15.229 + 15.230 + if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) 15.231 + device->Frequency = OutputType.Format.nSamplesPerSec; 15.232 + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) 15.233 + { 15.234 + if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) 15.235 + device->FmtChans = DevFmtMono; 15.236 + else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) 15.237 + device->FmtChans = DevFmtStereo; 15.238 + else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) 15.239 + device->FmtChans = DevFmtQuad; 15.240 + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) 15.241 + device->FmtChans = DevFmtX51; 15.242 + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) 15.243 + device->FmtChans = DevFmtX51Side; 15.244 + else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) 15.245 + device->FmtChans = DevFmtX61; 15.246 + else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1) 15.247 + device->FmtChans = DevFmtX71; 15.248 + else 15.249 + ERR("Unhandled channel config: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); 15.250 + } 15.251 + 15.252 + switch(device->FmtChans) 15.253 + { 15.254 + case DevFmtMono: 15.255 + OutputType.Format.nChannels = 1; 15.256 + OutputType.dwChannelMask = MONO; 15.257 + break; 15.258 + case DevFmtStereo: 15.259 + OutputType.Format.nChannels = 2; 15.260 + OutputType.dwChannelMask = STEREO; 15.261 + break; 15.262 + case DevFmtQuad: 15.263 + OutputType.Format.nChannels = 4; 15.264 + OutputType.dwChannelMask = QUAD; 15.265 + break; 15.266 + case DevFmtX51: 15.267 + OutputType.Format.nChannels = 6; 15.268 + OutputType.dwChannelMask = X5DOT1; 15.269 + break; 15.270 + case DevFmtX51Side: 15.271 + OutputType.Format.nChannels = 6; 15.272 + OutputType.dwChannelMask = X5DOT1SIDE; 15.273 + break; 15.274 + case DevFmtX61: 15.275 + OutputType.Format.nChannels = 7; 15.276 + OutputType.dwChannelMask = X6DOT1; 15.277 + break; 15.278 + case DevFmtX71: 15.279 + OutputType.Format.nChannels = 8; 15.280 + OutputType.dwChannelMask = X7DOT1; 15.281 + break; 15.282 + } 15.283 + switch(device->FmtType) 15.284 + { 15.285 + case DevFmtByte: 15.286 + device->FmtType = DevFmtUByte; 15.287 + /* fall-through */ 15.288 + case DevFmtUByte: 15.289 + OutputType.Format.wBitsPerSample = 8; 15.290 + OutputType.Samples.wValidBitsPerSample = 8; 15.291 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 15.292 + break; 15.293 + case DevFmtUShort: 15.294 + device->FmtType = DevFmtShort; 15.295 + /* fall-through */ 15.296 + case DevFmtShort: 15.297 + OutputType.Format.wBitsPerSample = 16; 15.298 + OutputType.Samples.wValidBitsPerSample = 16; 15.299 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 15.300 + break; 15.301 + case DevFmtFloat: 15.302 + OutputType.Format.wBitsPerSample = 32; 15.303 + OutputType.Samples.wValidBitsPerSample = 32; 15.304 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; 15.305 + break; 15.306 + } 15.307 + OutputType.Format.nSamplesPerSec = device->Frequency; 15.308 + 15.309 + OutputType.Format.nBlockAlign = OutputType.Format.nChannels * 15.310 + OutputType.Format.wBitsPerSample / 8; 15.311 + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * 15.312 + OutputType.Format.nBlockAlign; 15.313 + 15.314 + hr = IAudioClient_IsFormatSupported(data->client, AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); 15.315 + if(FAILED(hr)) 15.316 + { 15.317 + ERR("Failed to check format support: 0x%08lx\n", hr); 15.318 + hr = IAudioClient_GetMixFormat(data->client, &wfx); 15.319 + } 15.320 + if(FAILED(hr)) 15.321 + { 15.322 + ERR("Failed to find a supported format: 0x%08lx\n", hr); 15.323 + return hr; 15.324 + } 15.325 + 15.326 + if(wfx != NULL) 15.327 + { 15.328 + if(!MakeExtensible(&OutputType, wfx)) 15.329 + { 15.330 + CoTaskMemFree(wfx); 15.331 + return E_FAIL; 15.332 + } 15.333 + CoTaskMemFree(wfx); 15.334 + wfx = NULL; 15.335 + 15.336 + if(device->Frequency != OutputType.Format.nSamplesPerSec) 15.337 + { 15.338 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 15.339 + ERR("Failed to set %dhz, got %ldhz instead\n", device->Frequency, OutputType.Format.nSamplesPerSec); 15.340 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 15.341 + device->Frequency = OutputType.Format.nSamplesPerSec; 15.342 + } 15.343 + 15.344 + if(!((device->FmtChans == DevFmtMono && OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) || 15.345 + (device->FmtChans == DevFmtStereo && OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) || 15.346 + (device->FmtChans == DevFmtQuad && OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) || 15.347 + (device->FmtChans == DevFmtX51 && OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) || 15.348 + (device->FmtChans == DevFmtX51Side && OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) || 15.349 + (device->FmtChans == DevFmtX61 && OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) || 15.350 + (device->FmtChans == DevFmtX71 && OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1))) 15.351 + { 15.352 + if((device->Flags&DEVICE_CHANNELS_REQUEST)) 15.353 + ERR("Failed to set %s, got %d channels (0x%08lx) instead\n", DevFmtChannelsString(device->FmtChans), OutputType.Format.nChannels, OutputType.dwChannelMask); 15.354 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 15.355 + 15.356 + if(OutputType.Format.nChannels == 1 && OutputType.dwChannelMask == MONO) 15.357 + device->FmtChans = DevFmtMono; 15.358 + else if(OutputType.Format.nChannels == 2 && OutputType.dwChannelMask == STEREO) 15.359 + device->FmtChans = DevFmtStereo; 15.360 + else if(OutputType.Format.nChannels == 4 && OutputType.dwChannelMask == QUAD) 15.361 + device->FmtChans = DevFmtQuad; 15.362 + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1) 15.363 + device->FmtChans = DevFmtX51; 15.364 + else if(OutputType.Format.nChannels == 6 && OutputType.dwChannelMask == X5DOT1SIDE) 15.365 + device->FmtChans = DevFmtX51Side; 15.366 + else if(OutputType.Format.nChannels == 7 && OutputType.dwChannelMask == X6DOT1) 15.367 + device->FmtChans = DevFmtX61; 15.368 + else if(OutputType.Format.nChannels == 8 && OutputType.dwChannelMask == X7DOT1) 15.369 + device->FmtChans = DevFmtX71; 15.370 + else 15.371 + { 15.372 + ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, OutputType.dwChannelMask); 15.373 + device->FmtChans = DevFmtStereo; 15.374 + OutputType.Format.nChannels = 2; 15.375 + OutputType.dwChannelMask = STEREO; 15.376 + } 15.377 + } 15.378 + 15.379 + if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) 15.380 + { 15.381 + if(OutputType.Samples.wValidBitsPerSample == 0) 15.382 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 15.383 + if(OutputType.Samples.wValidBitsPerSample != OutputType.Format.wBitsPerSample || 15.384 + !((device->FmtType == DevFmtUByte && OutputType.Format.wBitsPerSample == 8) || 15.385 + (device->FmtType == DevFmtShort && OutputType.Format.wBitsPerSample == 16))) 15.386 + { 15.387 + ERR("Failed to set %s samples, got %d/%d-bit instead\n", DevFmtTypeString(device->FmtType), OutputType.Samples.wValidBitsPerSample, OutputType.Format.wBitsPerSample); 15.388 + if(OutputType.Format.wBitsPerSample == 8) 15.389 + device->FmtType = DevFmtUByte; 15.390 + else if(OutputType.Format.wBitsPerSample == 16) 15.391 + device->FmtType = DevFmtShort; 15.392 + else 15.393 + { 15.394 + device->FmtType = DevFmtShort; 15.395 + OutputType.Format.wBitsPerSample = 16; 15.396 + } 15.397 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 15.398 + } 15.399 + } 15.400 + else if(IsEqualGUID(&OutputType.SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)) 15.401 + { 15.402 + if(OutputType.Samples.wValidBitsPerSample == 0) 15.403 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 15.404 + if(OutputType.Samples.wValidBitsPerSample != OutputType.Format.wBitsPerSample || 15.405 + !((device->FmtType == DevFmtFloat && OutputType.Format.wBitsPerSample == 32))) 15.406 + { 15.407 + ERR("Failed to set %s samples, got %d/%d-bit instead\n", DevFmtTypeString(device->FmtType), OutputType.Samples.wValidBitsPerSample, OutputType.Format.wBitsPerSample); 15.408 + if(OutputType.Format.wBitsPerSample != 32) 15.409 + { 15.410 + device->FmtType = DevFmtFloat; 15.411 + OutputType.Format.wBitsPerSample = 32; 15.412 + } 15.413 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 15.414 + } 15.415 + } 15.416 + else 15.417 + { 15.418 + ERR("Unhandled format sub-type\n"); 15.419 + device->FmtType = DevFmtShort; 15.420 + OutputType.Format.wBitsPerSample = 16; 15.421 + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; 15.422 + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; 15.423 + } 15.424 + } 15.425 + 15.426 + SetDefaultWFXChannelOrder(device); 15.427 + 15.428 + hr = IAudioClient_GetDevicePeriod(data->client, &min_per, NULL); 15.429 + if(SUCCEEDED(hr)) 15.430 + { 15.431 + min_len = (min_per*device->Frequency + 10000000-1) / 10000000; 15.432 + if(min_len < device->UpdateSize) 15.433 + min_len *= (device->UpdateSize + min_len/2)/min_len; 15.434 + 15.435 + device->NumUpdates = (device->NumUpdates*device->UpdateSize + min_len/2) / 15.436 + min_len; 15.437 + device->NumUpdates = maxu(device->NumUpdates, 2); 15.438 + device->UpdateSize = min_len; 15.439 + 15.440 + hr = IAudioClient_Initialize(data->client, AUDCLNT_SHAREMODE_SHARED, 15.441 + AUDCLNT_STREAMFLAGS_EVENTCALLBACK, 15.442 + ((REFERENCE_TIME)device->UpdateSize* 15.443 + device->NumUpdates*10000000 + 15.444 + device->Frequency-1) / device->Frequency, 15.445 + 0, &OutputType.Format, NULL); 15.446 + } 15.447 + if(FAILED(hr)) 15.448 + { 15.449 + ERR("Failed to initialize audio client: 0x%08lx\n", hr); 15.450 + return hr; 15.451 + } 15.452 + 15.453 + hr = IAudioClient_GetBufferSize(data->client, &buffer_len); 15.454 + if(FAILED(hr)) 15.455 + { 15.456 + ERR("Failed to get audio buffer info: 0x%08lx\n", hr); 15.457 + return hr; 15.458 + } 15.459 + 15.460 + device->NumUpdates = buffer_len / device->UpdateSize; 15.461 + if(device->NumUpdates <= 1) 15.462 + { 15.463 + device->NumUpdates = 1; 15.464 + ERR("Audio client returned buffer_len < period*2; expect break up\n"); 15.465 + } 15.466 + 15.467 + ResetEvent(data->hNotifyEvent); 15.468 + hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent); 15.469 + if(SUCCEEDED(hr)) 15.470 + hr = IAudioClient_Start(data->client); 15.471 + if(FAILED(hr)) 15.472 + { 15.473 + ERR("Failed to start audio client: 0x%08lx\n", hr); 15.474 + return hr; 15.475 + } 15.476 + 15.477 + data->thread = StartThread(MMDevApiProc, device); 15.478 + if(!data->thread) 15.479 + { 15.480 + IAudioClient_Stop(data->client); 15.481 + ERR("Failed to start thread\n"); 15.482 + return E_FAIL; 15.483 + } 15.484 + 15.485 + return hr; 15.486 +} 15.487 + 15.488 + 15.489 +static DWORD CALLBACK MessageProc(void *ptr) 15.490 +{ 15.491 + ThreadRequest *req = ptr; 15.492 + IMMDeviceEnumerator *Enumerator; 15.493 + MMDevApiData *data; 15.494 + ALCdevice *device; 15.495 + HRESULT hr; 15.496 + MSG msg; 15.497 + 15.498 + TRACE("Starting message thread\n"); 15.499 + 15.500 + hr = CoInitialize(NULL); 15.501 + if(FAILED(hr)) 15.502 + { 15.503 + WARN("Failed to initialize COM: 0x%08lx\n", hr); 15.504 + req->result = hr; 15.505 + SetEvent(req->FinishedEvt); 15.506 + return 0; 15.507 + } 15.508 + 15.509 + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); 15.510 + if(FAILED(hr)) 15.511 + { 15.512 + WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); 15.513 + CoUninitialize(); 15.514 + req->result = hr; 15.515 + SetEvent(req->FinishedEvt); 15.516 + return 0; 15.517 + } 15.518 + Enumerator = ptr; 15.519 + IMMDeviceEnumerator_Release(Enumerator); 15.520 + Enumerator = NULL; 15.521 + 15.522 + req->result = S_OK; 15.523 + SetEvent(req->FinishedEvt); 15.524 + 15.525 + TRACE("Starting message loop\n"); 15.526 + while(GetMessage(&msg, NULL, 0, 0)) 15.527 + { 15.528 + TRACE("Got message %u\n", msg.message); 15.529 + switch(msg.message) 15.530 + { 15.531 + case WM_USER_OpenDevice: 15.532 + req = (ThreadRequest*)msg.wParam; 15.533 + device = (ALCdevice*)msg.lParam; 15.534 + data = device->ExtraData; 15.535 + 15.536 + hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, &ptr); 15.537 + if(SUCCEEDED(hr)) 15.538 + { 15.539 + Enumerator = ptr; 15.540 + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(Enumerator, eRender, eMultimedia, &data->mmdev); 15.541 + IMMDeviceEnumerator_Release(Enumerator); 15.542 + Enumerator = NULL; 15.543 + } 15.544 + if(SUCCEEDED(hr)) 15.545 + hr = IMMDevice_Activate(data->mmdev, &IID_IAudioClient, CLSCTX_INPROC_SERVER, NULL, &ptr); 15.546 + if(SUCCEEDED(hr)) 15.547 + data->client = ptr; 15.548 + 15.549 + if(FAILED(hr)) 15.550 + { 15.551 + if(data->mmdev) 15.552 + IMMDevice_Release(data->mmdev); 15.553 + data->mmdev = NULL; 15.554 + } 15.555 + 15.556 + req->result = hr; 15.557 + SetEvent(req->FinishedEvt); 15.558 + continue; 15.559 + 15.560 + case WM_USER_ResetDevice: 15.561 + req = (ThreadRequest*)msg.wParam; 15.562 + device = (ALCdevice*)msg.lParam; 15.563 + 15.564 + req->result = DoReset(device); 15.565 + SetEvent(req->FinishedEvt); 15.566 + continue; 15.567 + 15.568 + case WM_USER_StopDevice: 15.569 + req = (ThreadRequest*)msg.wParam; 15.570 + device = (ALCdevice*)msg.lParam; 15.571 + data = device->ExtraData; 15.572 + 15.573 + if(data->thread) 15.574 + { 15.575 + data->killNow = 1; 15.576 + StopThread(data->thread); 15.577 + data->thread = NULL; 15.578 + 15.579 + data->killNow = 0; 15.580 + 15.581 + IAudioClient_Stop(data->client); 15.582 + } 15.583 + 15.584 + req->result = S_OK; 15.585 + SetEvent(req->FinishedEvt); 15.586 + continue; 15.587 + 15.588 + case WM_USER_CloseDevice: 15.589 + req = (ThreadRequest*)msg.wParam; 15.590 + device = (ALCdevice*)msg.lParam; 15.591 + data = device->ExtraData; 15.592 + 15.593 + IAudioClient_Release(data->client); 15.594 + data->client = NULL; 15.595 + 15.596 + IMMDevice_Release(data->mmdev); 15.597 + data->mmdev = NULL; 15.598 + 15.599 + req->result = S_OK; 15.600 + SetEvent(req->FinishedEvt); 15.601 + continue; 15.602 + 15.603 + default: 15.604 + ERR("Unexpected message: %u\n", msg.message); 15.605 + continue; 15.606 + } 15.607 + } 15.608 + TRACE("Message loop finished\n"); 15.609 + 15.610 + CoUninitialize(); 15.611 + return 0; 15.612 +} 15.613 + 15.614 + 15.615 +static BOOL MMDevApiLoad(void) 15.616 +{ 15.617 + static HRESULT InitResult; 15.618 + if(!ThreadHdl) 15.619 + { 15.620 + ThreadRequest req; 15.621 + InitResult = E_FAIL; 15.622 + 15.623 + req.FinishedEvt = CreateEvent(NULL, FALSE, FALSE, NULL); 15.624 + if(req.FinishedEvt == NULL) 15.625 + ERR("Failed to create event: %lu\n", GetLastError()); 15.626 + else 15.627 + { 15.628 + ThreadHdl = CreateThread(NULL, 0, MessageProc, &req, 0, &ThreadID); 15.629 + if(ThreadHdl != NULL) 15.630 + InitResult = WaitForResponse(&req); 15.631 + CloseHandle(req.FinishedEvt); 15.632 + } 15.633 + } 15.634 + return SUCCEEDED(InitResult); 15.635 +} 15.636 + 15.637 + 15.638 +static ALCboolean MMDevApiOpenPlayback(ALCdevice *device, const ALCchar *deviceName) 15.639 +{ 15.640 + MMDevApiData *data = NULL; 15.641 + HRESULT hr; 15.642 + 15.643 + if(!deviceName) 15.644 + deviceName = mmDevice; 15.645 + else if(strcmp(deviceName, mmDevice) != 0) 15.646 + return ALC_FALSE; 15.647 + 15.648 + //Initialise requested device 15.649 + data = calloc(1, sizeof(MMDevApiData)); 15.650 + if(!data) 15.651 + { 15.652 + alcSetError(device, ALC_OUT_OF_MEMORY); 15.653 + return ALC_FALSE; 15.654 + } 15.655 + device->ExtraData = data; 15.656 + 15.657 + hr = S_OK; 15.658 + data->hNotifyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 15.659 + data->MsgEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 15.660 + if(data->hNotifyEvent == NULL || data->MsgEvent == NULL) 15.661 + hr = E_FAIL; 15.662 + 15.663 + if(SUCCEEDED(hr)) 15.664 + { 15.665 + ThreadRequest req = { data->MsgEvent, 0 }; 15.666 + 15.667 + hr = E_FAIL; 15.668 + if(PostThreadMessage(ThreadID, WM_USER_OpenDevice, (WPARAM)&req, (LPARAM)device)) 15.669 + hr = WaitForResponse(&req); 15.670 + } 15.671 + 15.672 + if(FAILED(hr)) 15.673 + { 15.674 + if(data->hNotifyEvent != NULL) 15.675 + CloseHandle(data->hNotifyEvent); 15.676 + data->hNotifyEvent = NULL; 15.677 + if(data->MsgEvent != NULL) 15.678 + CloseHandle(data->MsgEvent); 15.679 + data->MsgEvent = NULL; 15.680 + 15.681 + free(data); 15.682 + device->ExtraData = NULL; 15.683 + 15.684 + ERR("Device init failed: 0x%08lx\n", hr); 15.685 + return ALC_FALSE; 15.686 + } 15.687 + 15.688 + device->szDeviceName = strdup(deviceName); 15.689 + return ALC_TRUE; 15.690 +} 15.691 + 15.692 +static void MMDevApiClosePlayback(ALCdevice *device) 15.693 +{ 15.694 + MMDevApiData *data = device->ExtraData; 15.695 + ThreadRequest req = { data->MsgEvent, 0 }; 15.696 + 15.697 + if(PostThreadMessage(ThreadID, WM_USER_CloseDevice, (WPARAM)&req, (LPARAM)device)) 15.698 + (void)WaitForResponse(&req); 15.699 + 15.700 + CloseHandle(data->MsgEvent); 15.701 + data->MsgEvent = NULL; 15.702 + 15.703 + CloseHandle(data->hNotifyEvent); 15.704 + data->hNotifyEvent = NULL; 15.705 + 15.706 + free(data); 15.707 + device->ExtraData = NULL; 15.708 +} 15.709 + 15.710 +static ALCboolean MMDevApiResetPlayback(ALCdevice *device) 15.711 +{ 15.712 + MMDevApiData *data = device->ExtraData; 15.713 + ThreadRequest req = { data->MsgEvent, 0 }; 15.714 + HRESULT hr = E_FAIL; 15.715 + 15.716 + if(PostThreadMessage(ThreadID, WM_USER_ResetDevice, (WPARAM)&req, (LPARAM)device)) 15.717 + hr = WaitForResponse(&req); 15.718 + 15.719 + return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE; 15.720 +} 15.721 + 15.722 +static void MMDevApiStopPlayback(ALCdevice *device) 15.723 +{ 15.724 + MMDevApiData *data = device->ExtraData; 15.725 + ThreadRequest req = { data->MsgEvent, 0 }; 15.726 + 15.727 + if(PostThreadMessage(ThreadID, WM_USER_StopDevice, (WPARAM)&req, (LPARAM)device)) 15.728 + (void)WaitForResponse(&req); 15.729 +} 15.730 + 15.731 + 15.732 +static const BackendFuncs MMDevApiFuncs = { 15.733 + MMDevApiOpenPlayback, 15.734 + MMDevApiClosePlayback, 15.735 + MMDevApiResetPlayback, 15.736 + MMDevApiStopPlayback, 15.737 + NULL, 15.738 + NULL, 15.739 + NULL, 15.740 + NULL, 15.741 + NULL, 15.742 + NULL 15.743 +}; 15.744 + 15.745 + 15.746 +ALCboolean alcMMDevApiInit(BackendFuncs *FuncList) 15.747 +{ 15.748 + if(!MMDevApiLoad()) 15.749 + return ALC_FALSE; 15.750 + *FuncList = MMDevApiFuncs; 15.751 + return ALC_TRUE; 15.752 +} 15.753 + 15.754 +void alcMMDevApiDeinit(void) 15.755 +{ 15.756 + if(ThreadHdl) 15.757 + { 15.758 + TRACE("Sending WM_QUIT to Thread %04lx\n", ThreadID); 15.759 + PostThreadMessage(ThreadID, WM_QUIT, 0, 0); 15.760 + CloseHandle(ThreadHdl); 15.761 + ThreadHdl = NULL; 15.762 + } 15.763 +} 15.764 + 15.765 +void alcMMDevApiProbe(enum DevProbe type) 15.766 +{ 15.767 + switch(type) 15.768 + { 15.769 + case DEVICE_PROBE: 15.770 + AppendDeviceList(mmDevice); 15.771 + break; 15.772 + case ALL_DEVICE_PROBE: 15.773 + AppendAllDeviceList(mmDevice); 15.774 + break; 15.775 + case CAPTURE_DEVICE_PROBE: 15.776 + break; 15.777 + } 15.778 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 16.2 +++ b/Alc/backends/null.c Tue Oct 25 13:02:31 2011 -0700 16.3 @@ -0,0 +1,164 @@ 16.4 +/** 16.5 + * OpenAL cross platform audio library 16.6 + * Copyright (C) 2010 by Chris Robinson 16.7 + * This library is free software; you can redistribute it and/or 16.8 + * modify it under the terms of the GNU Library General Public 16.9 + * License as published by the Free Software Foundation; either 16.10 + * version 2 of the License, or (at your option) any later version. 16.11 + * 16.12 + * This library is distributed in the hope that it will be useful, 16.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 16.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16.15 + * Library General Public License for more details. 16.16 + * 16.17 + * You should have received a copy of the GNU Library General Public 16.18 + * License along with this library; if not, write to the 16.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 16.20 + * Boston, MA 02111-1307, USA. 16.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 16.22 + */ 16.23 + 16.24 +#include "config.h" 16.25 + 16.26 +#include <stdlib.h> 16.27 +#include "alMain.h" 16.28 +#include "AL/al.h" 16.29 +#include "AL/alc.h" 16.30 + 16.31 + 16.32 +typedef struct { 16.33 + volatile int killNow; 16.34 + ALvoid *thread; 16.35 +} null_data; 16.36 + 16.37 + 16.38 +static const ALCchar nullDevice[] = "No Output"; 16.39 + 16.40 +static ALuint NullProc(ALvoid *ptr) 16.41 +{ 16.42 + ALCdevice *Device = (ALCdevice*)ptr; 16.43 + null_data *data = (null_data*)Device->ExtraData; 16.44 + ALuint now, start; 16.45 + ALuint64 avail, done; 16.46 + const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 / 16.47 + Device->Frequency / 2; 16.48 + 16.49 + done = 0; 16.50 + start = timeGetTime(); 16.51 + while(!data->killNow && Device->Connected) 16.52 + { 16.53 + now = timeGetTime(); 16.54 + 16.55 + avail = (ALuint64)(now-start) * Device->Frequency / 1000; 16.56 + if(avail < done) 16.57 + { 16.58 + /* Timer wrapped. Add the remainder of the cycle to the available 16.59 + * count and reset the number of samples done */ 16.60 + avail += (ALuint64)0xFFFFFFFFu*Device->Frequency/1000 - done; 16.61 + done = 0; 16.62 + } 16.63 + if(avail-done < Device->UpdateSize) 16.64 + { 16.65 + Sleep(restTime); 16.66 + continue; 16.67 + } 16.68 + 16.69 + while(avail-done >= Device->UpdateSize) 16.70 + { 16.71 + aluMixData(Device, NULL, Device->UpdateSize); 16.72 + done += Device->UpdateSize; 16.73 + } 16.74 + } 16.75 + 16.76 + return 0; 16.77 +} 16.78 + 16.79 +static ALCboolean null_open_playback(ALCdevice *device, const ALCchar *deviceName) 16.80 +{ 16.81 + null_data *data; 16.82 + 16.83 + if(!deviceName) 16.84 + deviceName = nullDevice; 16.85 + else if(strcmp(deviceName, nullDevice) != 0) 16.86 + return ALC_FALSE; 16.87 + 16.88 + data = (null_data*)calloc(1, sizeof(*data)); 16.89 + 16.90 + device->szDeviceName = strdup(deviceName); 16.91 + device->ExtraData = data; 16.92 + return ALC_TRUE; 16.93 +} 16.94 + 16.95 +static void null_close_playback(ALCdevice *device) 16.96 +{ 16.97 + null_data *data = (null_data*)device->ExtraData; 16.98 + 16.99 + free(data); 16.100 + device->ExtraData = NULL; 16.101 +} 16.102 + 16.103 +static ALCboolean null_reset_playback(ALCdevice *device) 16.104 +{ 16.105 + null_data *data = (null_data*)device->ExtraData; 16.106 + 16.107 + SetDefaultWFXChannelOrder(device); 16.108 + 16.109 + data->thread = StartThread(NullProc, device); 16.110 + if(data->thread == NULL) 16.111 + return ALC_FALSE; 16.112 + 16.113 + return ALC_TRUE; 16.114 +} 16.115 + 16.116 +static void null_stop_playback(ALCdevice *device) 16.117 +{ 16.118 + null_data *data = (null_data*)device->ExtraData; 16.119 + 16.120 + if(!data->thread) 16.121 + return; 16.122 + 16.123 + data->killNow = 1; 16.124 + StopThread(data->thread); 16.125 + data->thread = NULL; 16.126 + 16.127 + data->killNow = 0; 16.128 +} 16.129 + 16.130 + 16.131 +static const BackendFuncs null_funcs = { 16.132 + null_open_playback, 16.133 + null_close_playback, 16.134 + null_reset_playback, 16.135 + null_stop_playback, 16.136 + NULL, 16.137 + NULL, 16.138 + NULL, 16.139 + NULL, 16.140 + NULL, 16.141 + NULL 16.142 +}; 16.143 + 16.144 +ALCboolean alc_null_init(BackendFuncs *func_list) 16.145 +{ 16.146 + *func_list = null_funcs; 16.147 + return ALC_TRUE; 16.148 +} 16.149 + 16.150 +void alc_null_deinit(void) 16.151 +{ 16.152 +} 16.153 + 16.154 +void alc_null_probe(enum DevProbe type) 16.155 +{ 16.156 + switch(type) 16.157 + { 16.158 + case DEVICE_PROBE: 16.159 + AppendDeviceList(nullDevice); 16.160 + break; 16.161 + case ALL_DEVICE_PROBE: 16.162 + AppendAllDeviceList(nullDevice); 16.163 + break; 16.164 + case CAPTURE_DEVICE_PROBE: 16.165 + break; 16.166 + } 16.167 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/Alc/backends/opensl.c Tue Oct 25 13:02:31 2011 -0700 17.3 @@ -0,0 +1,425 @@ 17.4 +/* 17.5 + * Copyright (C) 2011 The Android Open Source Project 17.6 + * 17.7 + * Licensed under the Apache License, Version 2.0 (the "License"); 17.8 + * you may not use this file except in compliance with the License. 17.9 + * You may obtain a copy of the License at 17.10 + * 17.11 + * http://www.apache.org/licenses/LICENSE-2.0 17.12 + * 17.13 + * Unless required by applicable law or agreed to in writing, software 17.14 + * distributed under the License is distributed on an "AS IS" BASIS, 17.15 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17.16 + * See the License for the specific language governing permissions and 17.17 + * limitations under the License. 17.18 + */ 17.19 + 17.20 +/* This is an OpenAL backend for Android using the native audio APIs based on 17.21 + * OpenSL ES 1.0.1. It is based on source code for the native-audio sample app 17.22 + * bundled with NDK. 17.23 + */ 17.24 + 17.25 +#include "config.h" 17.26 + 17.27 +#include <stdlib.h> 17.28 +#include "alMain.h" 17.29 +#include "AL/al.h" 17.30 +#include "AL/alc.h" 17.31 + 17.32 + 17.33 +#include <SLES/OpenSLES.h> 17.34 +#if 1 17.35 +#include <SLES/OpenSLES_Android.h> 17.36 +#else 17.37 +extern SLAPIENTRY const SLInterfaceID SL_IID_ANDROIDSIMPLEBUFFERQUEUE; 17.38 + 17.39 +struct SLAndroidSimpleBufferQueueItf_; 17.40 +typedef const struct SLAndroidSimpleBufferQueueItf_ * const * SLAndroidSimpleBufferQueueItf; 17.41 + 17.42 +typedef void (*slAndroidSimpleBufferQueueCallback)(SLAndroidSimpleBufferQueueItf caller, void *pContext); 17.43 + 17.44 +typedef struct SLAndroidSimpleBufferQueueState_ { 17.45 + SLuint32 count; 17.46 + SLuint32 index; 17.47 +} SLAndroidSimpleBufferQueueState; 17.48 + 17.49 + 17.50 +struct SLAndroidSimpleBufferQueueItf_ { 17.51 + SLresult (*Enqueue) ( 17.52 + SLAndroidSimpleBufferQueueItf self, 17.53 + const void *pBuffer, 17.54 + SLuint32 size 17.55 + ); 17.56 + SLresult (*Clear) ( 17.57 + SLAndroidSimpleBufferQueueItf self 17.58 + ); 17.59 + SLresult (*GetState) ( 17.60 + SLAndroidSimpleBufferQueueItf self, 17.61 + SLAndroidSimpleBufferQueueState *pState 17.62 + ); 17.63 + SLresult (*RegisterCallback) ( 17.64 + SLAndroidSimpleBufferQueueItf self, 17.65 + slAndroidSimpleBufferQueueCallback callback, 17.66 + void* pContext 17.67 + ); 17.68 +}; 17.69 + 17.70 +#define SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE ((SLuint32) 0x800007BD) 17.71 + 17.72 +typedef struct SLDataLocator_AndroidSimpleBufferQueue { 17.73 + SLuint32 locatorType; 17.74 + SLuint32 numBuffers; 17.75 +} SLDataLocator_AndroidSimpleBufferQueue; 17.76 + 17.77 +#endif 17.78 + 17.79 +/* Helper macros */ 17.80 +#define SLObjectItf_Realize(a,b) ((*(a))->Realize((a),(b))) 17.81 +#define SLObjectItf_GetInterface(a,b,c) ((*(a))->GetInterface((a),(b),(c))) 17.82 +#define SLObjectItf_Destroy(a) ((*(a))->Destroy((a))) 17.83 + 17.84 +#define SLEngineItf_CreateOutputMix(a,b,c,d,e) ((*(a))->CreateOutputMix((a),(b),(c),(d),(e))) 17.85 +#define SLEngineItf_CreateAudioPlayer(a,b,c,d,e,f,g) ((*(a))->CreateAudioPlayer((a),(b),(c),(d),(e),(f),(g))) 17.86 + 17.87 +#define SLPlayItf_SetPlayState(a,b) ((*(a))->SetPlayState((a),(b))) 17.88 + 17.89 + 17.90 +typedef struct { 17.91 + /* engine interfaces */ 17.92 + SLObjectItf engineObject; 17.93 + SLEngineItf engine; 17.94 + 17.95 + /* output mix interfaces */ 17.96 + SLObjectItf outputMix; 17.97 + 17.98 + /* buffer queue player interfaces */ 17.99 + SLObjectItf bufferQueueObject; 17.100 + 17.101 + void *buffer; 17.102 + ALuint bufferSize; 17.103 + 17.104 + ALuint frameSize; 17.105 +} osl_data; 17.106 + 17.107 + 17.108 +static const ALCchar opensl_device[] = "OpenSL"; 17.109 + 17.110 + 17.111 +static SLuint32 GetChannelMask(enum DevFmtChannels chans) 17.112 +{ 17.113 + switch(chans) 17.114 + { 17.115 + case DevFmtMono: return SL_SPEAKER_FRONT_CENTER; 17.116 + case DevFmtStereo: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT; 17.117 + case DevFmtQuad: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| 17.118 + SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT; 17.119 + case DevFmtX51: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| 17.120 + SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| 17.121 + SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT; 17.122 + case DevFmtX61: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| 17.123 + SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| 17.124 + SL_SPEAKER_BACK_CENTER| 17.125 + SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; 17.126 + case DevFmtX71: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| 17.127 + SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| 17.128 + SL_SPEAKER_BACK_LEFT|SL_SPEAKER_BACK_RIGHT| 17.129 + SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; 17.130 + case DevFmtX51Side: return SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT| 17.131 + SL_SPEAKER_FRONT_CENTER|SL_SPEAKER_LOW_FREQUENCY| 17.132 + SL_SPEAKER_SIDE_LEFT|SL_SPEAKER_SIDE_RIGHT; 17.133 + } 17.134 + return 0; 17.135 +} 17.136 + 17.137 +static const char *res_str(SLresult result) 17.138 +{ 17.139 + switch(result) 17.140 + { 17.141 + case SL_RESULT_SUCCESS: return "Success"; 17.142 + case SL_RESULT_PRECONDITIONS_VIOLATED: return "Preconditions violated"; 17.143 + case SL_RESULT_PARAMETER_INVALID: return "Parameter invalid"; 17.144 + case SL_RESULT_MEMORY_FAILURE: return "Memory failure"; 17.145 + case SL_RESULT_RESOURCE_ERROR: return "Resource error"; 17.146 + case SL_RESULT_RESOURCE_LOST: return "Resource lost"; 17.147 + case SL_RESULT_IO_ERROR: return "I/O error"; 17.148 + case SL_RESULT_BUFFER_INSUFFICIENT: return "Buffer insufficient"; 17.149 + case SL_RESULT_CONTENT_CORRUPTED: return "Content corrupted"; 17.150 + case SL_RESULT_CONTENT_UNSUPPORTED: return "Content unsupported"; 17.151 + case SL_RESULT_CONTENT_NOT_FOUND: return "Content not found"; 17.152 + case SL_RESULT_PERMISSION_DENIED: return "Permission denied"; 17.153 + case SL_RESULT_FEATURE_UNSUPPORTED: return "Feature unsupported"; 17.154 + case SL_RESULT_INTERNAL_ERROR: return "Internal error"; 17.155 + case SL_RESULT_UNKNOWN_ERROR: return "Unknown error"; 17.156 + case SL_RESULT_OPERATION_ABORTED: return "Operation aborted"; 17.157 + case SL_RESULT_CONTROL_LOST: return "Control lost"; 17.158 + case SL_RESULT_READONLY: return "ReadOnly"; 17.159 + case SL_RESULT_ENGINEOPTION_UNSUPPORTED: return "Engine option unsupported"; 17.160 + case SL_RESULT_SOURCE_SINK_INCOMPATIBLE: return "Source/Sink incompatible"; 17.161 + } 17.162 + return "Unknown error code"; 17.163 +} 17.164 + 17.165 +#define PRINTERR(x, s) do { \ 17.166 + if((x) != SL_RESULT_SUCCESS) \ 17.167 + ERR("%s: %s\n", (s), res_str((x))); \ 17.168 +} while(0) 17.169 + 17.170 +/* this callback handler is called every time a buffer finishes playing */ 17.171 +static void opensl_callback(SLAndroidSimpleBufferQueueItf bq, void *context) 17.172 +{ 17.173 + ALCdevice *Device = context; 17.174 + osl_data *data = Device->ExtraData; 17.175 + SLresult result; 17.176 + 17.177 + aluMixData(Device, data->buffer, data->bufferSize/data->frameSize); 17.178 + 17.179 + result = (*bq)->Enqueue(bq, data->buffer, data->bufferSize); 17.180 + PRINTERR(result, "bq->Enqueue"); 17.181 +} 17.182 + 17.183 + 17.184 +static ALCboolean opensl_open_playback(ALCdevice *Device, const ALCchar *deviceName) 17.185 +{ 17.186 + osl_data *data = NULL; 17.187 + SLresult result; 17.188 + 17.189 + if(!deviceName) 17.190 + deviceName = opensl_device; 17.191 + else if(strcmp(deviceName, opensl_device) != 0) 17.192 + return ALC_FALSE; 17.193 + 17.194 + data = calloc(1, sizeof(*data)); 17.195 + if(!data) 17.196 + { 17.197 + alcSetError(Device, ALC_OUT_OF_MEMORY); 17.198 + return ALC_FALSE; 17.199 + } 17.200 + 17.201 + // create engine 17.202 + result = slCreateEngine(&data->engineObject, 0, NULL, 0, NULL, NULL); 17.203 + PRINTERR(result, "slCreateEngine"); 17.204 + if(SL_RESULT_SUCCESS == result) 17.205 + { 17.206 + result = SLObjectItf_Realize(data->engineObject, SL_BOOLEAN_FALSE); 17.207 + PRINTERR(result, "engine->Realize"); 17.208 + } 17.209 + if(SL_RESULT_SUCCESS == result) 17.210 + { 17.211 + result = SLObjectItf_GetInterface(data->engineObject, SL_IID_ENGINE, &data->engine); 17.212 + PRINTERR(result, "engine->GetInterface"); 17.213 + } 17.214 + if(SL_RESULT_SUCCESS == result) 17.215 + { 17.216 + result = SLEngineItf_CreateOutputMix(data->engine, &data->outputMix, 0, NULL, NULL); 17.217 + PRINTERR(result, "engine->CreateOutputMix"); 17.218 + } 17.219 + if(SL_RESULT_SUCCESS == result) 17.220 + { 17.221 + result = SLObjectItf_Realize(data->outputMix, SL_BOOLEAN_FALSE); 17.222 + PRINTERR(result, "outputMix->Realize"); 17.223 + } 17.224 + 17.225 + if(SL_RESULT_SUCCESS != result) 17.226 + { 17.227 + if(data->outputMix != NULL) 17.228 + SLObjectItf_Destroy(data->outputMix); 17.229 + data->outputMix = NULL; 17.230 + 17.231 + if(data->engineObject != NULL) 17.232 + SLObjectItf_Destroy(data->engineObject); 17.233 + data->engineObject = NULL; 17.234 + data->engine = NULL; 17.235 + 17.236 + free(data); 17.237 + return ALC_FALSE; 17.238 + } 17.239 + 17.240 + Device->szDeviceName = strdup(deviceName); 17.241 + Device->ExtraData = data; 17.242 + 17.243 + return ALC_TRUE; 17.244 +} 17.245 + 17.246 + 17.247 +static void opensl_close_playback(ALCdevice *Device) 17.248 +{ 17.249 + osl_data *data = Device->ExtraData; 17.250 + 17.251 + SLObjectItf_Destroy(data->outputMix); 17.252 + data->outputMix = NULL; 17.253 + 17.254 + SLObjectItf_Destroy(data->engineObject); 17.255 + data->engineObject = NULL; 17.256 + data->engine = NULL; 17.257 + 17.258 + free(data); 17.259 + Device->ExtraData = NULL; 17.260 +} 17.261 + 17.262 +static ALCboolean opensl_reset_playback(ALCdevice *Device) 17.263 +{ 17.264 + osl_data *data = Device->ExtraData; 17.265 + SLDataLocator_AndroidSimpleBufferQueue loc_bufq; 17.266 + SLAndroidSimpleBufferQueueItf bufferQueue; 17.267 + SLDataLocator_OutputMix loc_outmix; 17.268 + SLDataFormat_PCM format_pcm; 17.269 + SLDataSource audioSrc; 17.270 + SLDataSink audioSnk; 17.271 + SLPlayItf player; 17.272 + SLInterfaceID id; 17.273 + SLboolean req; 17.274 + SLresult result; 17.275 + ALuint i; 17.276 + 17.277 + 17.278 + Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency; 17.279 + Device->UpdateSize = Device->UpdateSize * Device->NumUpdates / 2; 17.280 + Device->NumUpdates = 2; 17.281 + 17.282 + Device->Frequency = 44100; 17.283 + Device->FmtChans = DevFmtStereo; 17.284 + Device->FmtType = DevFmtShort; 17.285 + 17.286 + SetDefaultWFXChannelOrder(Device); 17.287 + 17.288 + 17.289 + id = SL_IID_ANDROIDSIMPLEBUFFERQUEUE; 17.290 + req = SL_BOOLEAN_TRUE; 17.291 + 17.292 + loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; 17.293 + loc_bufq.numBuffers = Device->NumUpdates; 17.294 + 17.295 + format_pcm.formatType = SL_DATAFORMAT_PCM; 17.296 + format_pcm.numChannels = ChannelsFromDevFmt(Device->FmtChans); 17.297 + format_pcm.samplesPerSec = Device->Frequency * 1000; 17.298 + format_pcm.bitsPerSample = BytesFromDevFmt(Device->FmtType) * 8; 17.299 + format_pcm.containerSize = format_pcm.bitsPerSample; 17.300 + format_pcm.channelMask = GetChannelMask(Device->FmtChans); 17.301 + format_pcm.endianness = SL_BYTEORDER_NATIVE; 17.302 + 17.303 + audioSrc.pLocator = &loc_bufq; 17.304 + audioSrc.pFormat = &format_pcm; 17.305 + 17.306 + loc_outmix.locatorType = SL_DATALOCATOR_OUTPUTMIX; 17.307 + loc_outmix.outputMix = data->outputMix; 17.308 + audioSnk.pLocator = &loc_outmix; 17.309 + audioSnk.pFormat = NULL; 17.310 + 17.311 + 17.312 + result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req); 17.313 + PRINTERR(result, "engine->CreateAudioPlayer"); 17.314 + if(SL_RESULT_SUCCESS == result) 17.315 + { 17.316 + result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE); 17.317 + PRINTERR(result, "bufferQueue->Realize"); 17.318 + } 17.319 + if(SL_RESULT_SUCCESS == result) 17.320 + { 17.321 + result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue); 17.322 + PRINTERR(result, "bufferQueue->GetInterface"); 17.323 + } 17.324 + if(SL_RESULT_SUCCESS == result) 17.325 + { 17.326 + result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device); 17.327 + PRINTERR(result, "bufferQueue->RegisterCallback"); 17.328 + } 17.329 + if(SL_RESULT_SUCCESS == result) 17.330 + { 17.331 + data->frameSize = FrameSizeFromDevFmt(Device->FmtChans, Device->FmtType); 17.332 + data->bufferSize = Device->UpdateSize * data->frameSize; 17.333 + data->buffer = calloc(1, data->bufferSize); 17.334 + if(!data->buffer) 17.335 + { 17.336 + result = SL_RESULT_MEMORY_FAILURE; 17.337 + PRINTERR(result, "calloc"); 17.338 + } 17.339 + } 17.340 + /* enqueue the first buffer to kick off the callbacks */ 17.341 + for(i = 0;i < Device->NumUpdates;i++) 17.342 + { 17.343 + if(SL_RESULT_SUCCESS == result) 17.344 + { 17.345 + result = (*bufferQueue)->Enqueue(bufferQueue, data->buffer, data->bufferSize); 17.346 + PRINTERR(result, "bufferQueue->Enqueue"); 17.347 + } 17.348 + } 17.349 + if(SL_RESULT_SUCCESS == result) 17.350 + { 17.351 + result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_PLAY, &player); 17.352 + PRINTERR(result, "bufferQueue->GetInterface"); 17.353 + } 17.354 + if(SL_RESULT_SUCCESS == result) 17.355 + { 17.356 + result = SLPlayItf_SetPlayState(player, SL_PLAYSTATE_PLAYING); 17.357 + PRINTERR(result, "player->SetPlayState"); 17.358 + } 17.359 + 17.360 + if(SL_RESULT_SUCCESS != result) 17.361 + { 17.362 + if(data->bufferQueueObject != NULL) 17.363 + SLObjectItf_Destroy(data->bufferQueueObject); 17.364 + data->bufferQueueObject = NULL; 17.365 + 17.366 + free(data->buffer); 17.367 + data->buffer = NULL; 17.368 + data->bufferSize = 0; 17.369 + 17.370 + return ALC_FALSE; 17.371 + } 17.372 + 17.373 + return ALC_TRUE; 17.374 +} 17.375 + 17.376 + 17.377 +static void opensl_stop_playback(ALCdevice *Device) 17.378 +{ 17.379 + osl_data *data = Device->ExtraData; 17.380 + 17.381 + if(data->bufferQueueObject != NULL) 17.382 + SLObjectItf_Destroy(data->bufferQueueObject); 17.383 + data->bufferQueueObject = NULL; 17.384 + 17.385 + free(data->buffer); 17.386 + data->buffer = NULL; 17.387 + data->bufferSize = 0; 17.388 +} 17.389 + 17.390 + 17.391 +static const BackendFuncs opensl_funcs = { 17.392 + opensl_open_playback, 17.393 + opensl_close_playback, 17.394 + opensl_reset_playback, 17.395 + opensl_stop_playback, 17.396 + NULL, 17.397 + NULL, 17.398 + NULL, 17.399 + NULL, 17.400 + NULL, 17.401 + NULL 17.402 +}; 17.403 + 17.404 + 17.405 +ALCboolean alc_opensl_init(BackendFuncs *func_list) 17.406 +{ 17.407 + *func_list = opensl_funcs; 17.408 + return ALC_TRUE; 17.409 +} 17.410 + 17.411 +void alc_opensl_deinit(void) 17.412 +{ 17.413 +} 17.414 + 17.415 +void alc_opensl_probe(enum DevProbe type) 17.416 +{ 17.417 + switch(type) 17.418 + { 17.419 + case DEVICE_PROBE: 17.420 + AppendDeviceList(opensl_device); 17.421 + break; 17.422 + case ALL_DEVICE_PROBE: 17.423 + AppendAllDeviceList(opensl_device); 17.424 + break; 17.425 + case CAPTURE_DEVICE_PROBE: 17.426 + break; 17.427 + } 17.428 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 18.2 +++ b/Alc/backends/oss.c Tue Oct 25 13:02:31 2011 -0700 18.3 @@ -0,0 +1,536 @@ 18.4 +/** 18.5 + * OpenAL cross platform audio library 18.6 + * Copyright (C) 1999-2007 by authors. 18.7 + * This library is free software; you can redistribute it and/or 18.8 + * modify it under the terms of the GNU Library General Public 18.9 + * License as published by the Free Software Foundation; either 18.10 + * version 2 of the License, or (at your option) any later version. 18.11 + * 18.12 + * This library is distributed in the hope that it will be useful, 18.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 18.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18.15 + * Library General Public License for more details. 18.16 + * 18.17 + * You should have received a copy of the GNU Library General Public 18.18 + * License along with this library; if not, write to the 18.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 18.20 + * Boston, MA 02111-1307, USA. 18.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 18.22 + */ 18.23 + 18.24 +#include "config.h" 18.25 + 18.26 +#include <sys/ioctl.h> 18.27 +#include <sys/types.h> 18.28 +#include <sys/stat.h> 18.29 +#include <fcntl.h> 18.30 +#include <stdlib.h> 18.31 +#include <stdio.h> 18.32 +#include <memory.h> 18.33 +#include <unistd.h> 18.34 +#include <errno.h> 18.35 +#include <math.h> 18.36 +#include "alMain.h" 18.37 +#include "AL/al.h" 18.38 +#include "AL/alc.h" 18.39 + 18.40 +#include <sys/soundcard.h> 18.41 + 18.42 +/* 18.43 + * The OSS documentation talks about SOUND_MIXER_READ, but the header 18.44 + * only contains MIXER_READ. Play safe. Same for WRITE. 18.45 + */ 18.46 +#ifndef SOUND_MIXER_READ 18.47 +#define SOUND_MIXER_READ MIXER_READ 18.48 +#endif 18.49 +#ifndef SOUND_MIXER_WRITE 18.50 +#define SOUND_MIXER_WRITE MIXER_WRITE 18.51 +#endif 18.52 + 18.53 +static const ALCchar oss_device[] = "OSS Default"; 18.54 + 18.55 +typedef struct { 18.56 + int fd; 18.57 + volatile int killNow; 18.58 + ALvoid *thread; 18.59 + 18.60 + ALubyte *mix_data; 18.61 + int data_size; 18.62 + 18.63 + RingBuffer *ring; 18.64 + int doCapture; 18.65 +} oss_data; 18.66 + 18.67 + 18.68 +static int log2i(ALCuint x) 18.69 +{ 18.70 + int y = 0; 18.71 + while (x > 1) 18.72 + { 18.73 + x >>= 1; 18.74 + y++; 18.75 + } 18.76 + return y; 18.77 +} 18.78 + 18.79 + 18.80 +static ALuint OSSProc(ALvoid *ptr) 18.81 +{ 18.82 + ALCdevice *pDevice = (ALCdevice*)ptr; 18.83 + oss_data *data = (oss_data*)pDevice->ExtraData; 18.84 + ALint frameSize; 18.85 + ssize_t wrote; 18.86 + 18.87 + SetRTPriority(); 18.88 + 18.89 + frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 18.90 + 18.91 + while(!data->killNow && pDevice->Connected) 18.92 + { 18.93 + ALint len = data->data_size; 18.94 + ALubyte *WritePtr = data->mix_data; 18.95 + 18.96 + aluMixData(pDevice, WritePtr, len/frameSize); 18.97 + while(len > 0 && !data->killNow) 18.98 + { 18.99 + wrote = write(data->fd, WritePtr, len); 18.100 + if(wrote < 0) 18.101 + { 18.102 + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) 18.103 + { 18.104 + ERR("write failed: %s\n", strerror(errno)); 18.105 + aluHandleDisconnect(pDevice); 18.106 + break; 18.107 + } 18.108 + 18.109 + Sleep(1); 18.110 + continue; 18.111 + } 18.112 + 18.113 + len -= wrote; 18.114 + WritePtr += wrote; 18.115 + } 18.116 + } 18.117 + 18.118 + return 0; 18.119 +} 18.120 + 18.121 +static ALuint OSSCaptureProc(ALvoid *ptr) 18.122 +{ 18.123 + ALCdevice *pDevice = (ALCdevice*)ptr; 18.124 + oss_data *data = (oss_data*)pDevice->ExtraData; 18.125 + int frameSize; 18.126 + int amt; 18.127 + 18.128 + SetRTPriority(); 18.129 + 18.130 + frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 18.131 + 18.132 + while(!data->killNow) 18.133 + { 18.134 + amt = read(data->fd, data->mix_data, data->data_size); 18.135 + if(amt < 0) 18.136 + { 18.137 + ERR("read failed: %s\n", strerror(errno)); 18.138 + aluHandleDisconnect(pDevice); 18.139 + break; 18.140 + } 18.141 + if(amt == 0) 18.142 + { 18.143 + Sleep(1); 18.144 + continue; 18.145 + } 18.146 + if(data->doCapture) 18.147 + WriteRingBuffer(data->ring, data->mix_data, amt/frameSize); 18.148 + } 18.149 + 18.150 + return 0; 18.151 +} 18.152 + 18.153 +static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName) 18.154 +{ 18.155 + char driver[64]; 18.156 + oss_data *data; 18.157 + 18.158 + strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1); 18.159 + driver[sizeof(driver)-1] = 0; 18.160 + if(!deviceName) 18.161 + deviceName = oss_device; 18.162 + else if(strcmp(deviceName, oss_device) != 0) 18.163 + return ALC_FALSE; 18.164 + 18.165 + data = (oss_data*)calloc(1, sizeof(oss_data)); 18.166 + data->killNow = 0; 18.167 + 18.168 + data->fd = open(driver, O_WRONLY); 18.169 + if(data->fd == -1) 18.170 + { 18.171 + free(data); 18.172 + ERR("Could not open %s: %s\n", driver, strerror(errno)); 18.173 + return ALC_FALSE; 18.174 + } 18.175 + 18.176 + device->szDeviceName = strdup(deviceName); 18.177 + device->ExtraData = data; 18.178 + return ALC_TRUE; 18.179 +} 18.180 + 18.181 +static void oss_close_playback(ALCdevice *device) 18.182 +{ 18.183 + oss_data *data = (oss_data*)device->ExtraData; 18.184 + 18.185 + close(data->fd); 18.186 + free(data); 18.187 + device->ExtraData = NULL; 18.188 +} 18.189 + 18.190 +static ALCboolean oss_reset_playback(ALCdevice *device) 18.191 +{ 18.192 + oss_data *data = (oss_data*)device->ExtraData; 18.193 + int numFragmentsLogSize; 18.194 + int log2FragmentSize; 18.195 + unsigned int periods; 18.196 + audio_buf_info info; 18.197 + ALuint frameSize; 18.198 + int numChannels; 18.199 + int ossFormat; 18.200 + int ossSpeed; 18.201 + char *err; 18.202 + 18.203 + switch(device->FmtType) 18.204 + { 18.205 + case DevFmtByte: 18.206 + ossFormat = AFMT_S8; 18.207 + break; 18.208 + case DevFmtUByte: 18.209 + ossFormat = AFMT_U8; 18.210 + break; 18.211 + case DevFmtUShort: 18.212 + case DevFmtFloat: 18.213 + device->FmtType = DevFmtShort; 18.214 + /* fall-through */ 18.215 + case DevFmtShort: 18.216 + ossFormat = AFMT_S16_NE; 18.217 + break; 18.218 + } 18.219 + 18.220 + periods = device->NumUpdates; 18.221 + numChannels = ChannelsFromDevFmt(device->FmtChans); 18.222 + frameSize = numChannels * BytesFromDevFmt(device->FmtType); 18.223 + 18.224 + ossSpeed = device->Frequency; 18.225 + log2FragmentSize = log2i(device->UpdateSize * frameSize); 18.226 + 18.227 + /* according to the OSS spec, 16 bytes are the minimum */ 18.228 + if (log2FragmentSize < 4) 18.229 + log2FragmentSize = 4; 18.230 + /* Subtract one period since the temp mixing buffer counts as one. Still 18.231 + * need at least two on the card, though. */ 18.232 + if(periods > 2) periods--; 18.233 + numFragmentsLogSize = (periods << 16) | log2FragmentSize; 18.234 + 18.235 +#define CHECKERR(func) if((func) < 0) { \ 18.236 + err = #func; \ 18.237 + goto err; \ 18.238 +} 18.239 + /* Don't fail if SETFRAGMENT fails. We can handle just about anything 18.240 + * that's reported back via GETOSPACE */ 18.241 + ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); 18.242 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat)); 18.243 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels)); 18.244 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed)); 18.245 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETOSPACE, &info)); 18.246 + if(0) 18.247 + { 18.248 + err: 18.249 + ERR("%s failed: %s\n", err, strerror(errno)); 18.250 + return ALC_FALSE; 18.251 + } 18.252 +#undef CHECKERR 18.253 + 18.254 + if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) 18.255 + { 18.256 + ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); 18.257 + return ALC_FALSE; 18.258 + } 18.259 + 18.260 + if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || 18.261 + (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || 18.262 + (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) 18.263 + { 18.264 + ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); 18.265 + return ALC_FALSE; 18.266 + } 18.267 + 18.268 + if(device->Frequency != (ALuint)ossSpeed) 18.269 + { 18.270 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 18.271 + ERR("Failed to set %dhz, got %dhz instead\n", device->Frequency, ossSpeed); 18.272 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 18.273 + device->Frequency = ossSpeed; 18.274 + } 18.275 + device->UpdateSize = info.fragsize / frameSize; 18.276 + device->NumUpdates = info.fragments + 1; 18.277 + 18.278 + data->data_size = device->UpdateSize * frameSize; 18.279 + data->mix_data = calloc(1, data->data_size); 18.280 + 18.281 + SetDefaultChannelOrder(device); 18.282 + 18.283 + data->thread = StartThread(OSSProc, device); 18.284 + if(data->thread == NULL) 18.285 + { 18.286 + free(data->mix_data); 18.287 + data->mix_data = NULL; 18.288 + return ALC_FALSE; 18.289 + } 18.290 + 18.291 + return ALC_TRUE; 18.292 +} 18.293 + 18.294 +static void oss_stop_playback(ALCdevice *device) 18.295 +{ 18.296 + oss_data *data = (oss_data*)device->ExtraData; 18.297 + 18.298 + if(!data->thread) 18.299 + return; 18.300 + 18.301 + data->killNow = 1; 18.302 + StopThread(data->thread); 18.303 + data->thread = NULL; 18.304 + 18.305 + data->killNow = 0; 18.306 + if(ioctl(data->fd, SNDCTL_DSP_RESET) != 0) 18.307 + ERR("Error resetting device: %s\n", strerror(errno)); 18.308 + 18.309 + free(data->mix_data); 18.310 + data->mix_data = NULL; 18.311 +} 18.312 + 18.313 + 18.314 +static ALCboolean oss_open_capture(ALCdevice *device, const ALCchar *deviceName) 18.315 +{ 18.316 + int numFragmentsLogSize; 18.317 + int log2FragmentSize; 18.318 + unsigned int periods; 18.319 + audio_buf_info info; 18.320 + ALuint frameSize; 18.321 + int numChannels; 18.322 + char driver[64]; 18.323 + oss_data *data; 18.324 + int ossFormat; 18.325 + int ossSpeed; 18.326 + char *err; 18.327 + 18.328 + strncpy(driver, GetConfigValue("oss", "capture", "/dev/dsp"), sizeof(driver)-1); 18.329 + driver[sizeof(driver)-1] = 0; 18.330 + if(!deviceName) 18.331 + deviceName = oss_device; 18.332 + else if(strcmp(deviceName, oss_device) != 0) 18.333 + return ALC_FALSE; 18.334 + 18.335 + data = (oss_data*)calloc(1, sizeof(oss_data)); 18.336 + data->killNow = 0; 18.337 + 18.338 + data->fd = open(driver, O_RDONLY); 18.339 + if(data->fd == -1) 18.340 + { 18.341 + free(data); 18.342 + ERR("Could not open %s: %s\n", driver, strerror(errno)); 18.343 + return ALC_FALSE; 18.344 + } 18.345 + 18.346 + switch(device->FmtType) 18.347 + { 18.348 + case DevFmtByte: 18.349 + ossFormat = AFMT_S8; 18.350 + break; 18.351 + case DevFmtUByte: 18.352 + ossFormat = AFMT_U8; 18.353 + break; 18.354 + case DevFmtShort: 18.355 + ossFormat = AFMT_S16_NE; 18.356 + break; 18.357 + case DevFmtUShort: 18.358 + case DevFmtFloat: 18.359 + free(data); 18.360 + ERR("%s capture samples not supported on OSS\n", DevFmtTypeString(device->FmtType)); 18.361 + return ALC_FALSE; 18.362 + } 18.363 + 18.364 + periods = 4; 18.365 + numChannels = ChannelsFromDevFmt(device->FmtChans); 18.366 + frameSize = numChannels * BytesFromDevFmt(device->FmtType); 18.367 + ossSpeed = device->Frequency; 18.368 + log2FragmentSize = log2i(device->UpdateSize * device->NumUpdates * 18.369 + frameSize / periods); 18.370 + 18.371 + /* according to the OSS spec, 16 bytes are the minimum */ 18.372 + if (log2FragmentSize < 4) 18.373 + log2FragmentSize = 4; 18.374 + numFragmentsLogSize = (periods << 16) | log2FragmentSize; 18.375 + 18.376 +#define CHECKERR(func) if((func) < 0) { \ 18.377 + err = #func; \ 18.378 + goto err; \ 18.379 +} 18.380 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize)); 18.381 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_SETFMT, &ossFormat)); 18.382 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_CHANNELS, &numChannels)); 18.383 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_SPEED, &ossSpeed)); 18.384 + CHECKERR(ioctl(data->fd, SNDCTL_DSP_GETISPACE, &info)); 18.385 + if(0) 18.386 + { 18.387 + err: 18.388 + ERR("%s failed: %s\n", err, strerror(errno)); 18.389 + close(data->fd); 18.390 + free(data); 18.391 + return ALC_FALSE; 18.392 + } 18.393 +#undef CHECKERR 18.394 + 18.395 + if((int)ChannelsFromDevFmt(device->FmtChans) != numChannels) 18.396 + { 18.397 + ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(device->FmtChans), numChannels); 18.398 + close(data->fd); 18.399 + free(data); 18.400 + return ALC_FALSE; 18.401 + } 18.402 + 18.403 + if(!((ossFormat == AFMT_S8 && device->FmtType == DevFmtByte) || 18.404 + (ossFormat == AFMT_U8 && device->FmtType == DevFmtUByte) || 18.405 + (ossFormat == AFMT_S16_NE && device->FmtType == DevFmtShort))) 18.406 + { 18.407 + ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(device->FmtType), ossFormat); 18.408 + close(data->fd); 18.409 + free(data); 18.410 + return ALC_FALSE; 18.411 + } 18.412 + 18.413 + data->ring = CreateRingBuffer(frameSize, device->UpdateSize * device->NumUpdates); 18.414 + if(!data->ring) 18.415 + { 18.416 + ERR("Ring buffer create failed\n"); 18.417 + close(data->fd); 18.418 + free(data); 18.419 + return ALC_FALSE; 18.420 + } 18.421 + 18.422 + data->data_size = info.fragsize; 18.423 + data->mix_data = calloc(1, data->data_size); 18.424 + 18.425 + device->ExtraData = data; 18.426 + data->thread = StartThread(OSSCaptureProc, device); 18.427 + if(data->thread == NULL) 18.428 + { 18.429 + device->ExtraData = NULL; 18.430 + free(data->mix_data); 18.431 + free(data); 18.432 + return ALC_FALSE; 18.433 + } 18.434 + 18.435 + device->szDeviceName = strdup(deviceName); 18.436 + return ALC_TRUE; 18.437 +} 18.438 + 18.439 +static void oss_close_capture(ALCdevice *device) 18.440 +{ 18.441 + oss_data *data = (oss_data*)device->ExtraData; 18.442 + data->killNow = 1; 18.443 + StopThread(data->thread); 18.444 + 18.445 + close(data->fd); 18.446 + 18.447 + DestroyRingBuffer(data->ring); 18.448 + 18.449 + free(data->mix_data); 18.450 + free(data); 18.451 + device->ExtraData = NULL; 18.452 +} 18.453 + 18.454 +static void oss_start_capture(ALCdevice *pDevice) 18.455 +{ 18.456 + oss_data *data = (oss_data*)pDevice->ExtraData; 18.457 + data->doCapture = 1; 18.458 +} 18.459 + 18.460 +static void oss_stop_capture(ALCdevice *pDevice) 18.461 +{ 18.462 + oss_data *data = (oss_data*)pDevice->ExtraData; 18.463 + data->doCapture = 0; 18.464 +} 18.465 + 18.466 +static void oss_capture_samples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) 18.467 +{ 18.468 + oss_data *data = (oss_data*)pDevice->ExtraData; 18.469 + if(lSamples <= (ALCuint)RingBufferSize(data->ring)) 18.470 + ReadRingBuffer(data->ring, pBuffer, lSamples); 18.471 + else 18.472 + alcSetError(pDevice, ALC_INVALID_VALUE); 18.473 +} 18.474 + 18.475 +static ALCuint oss_available_samples(ALCdevice *pDevice) 18.476 +{ 18.477 + oss_data *data = (oss_data*)pDevice->ExtraData; 18.478 + return RingBufferSize(data->ring); 18.479 +} 18.480 + 18.481 + 18.482 +static const BackendFuncs oss_funcs = { 18.483 + oss_open_playback, 18.484 + oss_close_playback, 18.485 + oss_reset_playback, 18.486 + oss_stop_playback, 18.487 + oss_open_capture, 18.488 + oss_close_capture, 18.489 + oss_start_capture, 18.490 + oss_stop_capture, 18.491 + oss_capture_samples, 18.492 + oss_available_samples 18.493 +}; 18.494 + 18.495 +ALCboolean alc_oss_init(BackendFuncs *func_list) 18.496 +{ 18.497 + *func_list = oss_funcs; 18.498 + return ALC_TRUE; 18.499 +} 18.500 + 18.501 +void alc_oss_deinit(void) 18.502 +{ 18.503 +} 18.504 + 18.505 +void alc_oss_probe(enum DevProbe type) 18.506 +{ 18.507 + switch(type) 18.508 + { 18.509 + case DEVICE_PROBE: 18.510 + { 18.511 +#ifdef HAVE_STAT 18.512 + struct stat buf; 18.513 + if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0) 18.514 +#endif 18.515 + AppendDeviceList(oss_device); 18.516 + } 18.517 + break; 18.518 + 18.519 + case ALL_DEVICE_PROBE: 18.520 + { 18.521 +#ifdef HAVE_STAT 18.522 + struct stat buf; 18.523 + if(stat(GetConfigValue("oss", "device", "/dev/dsp"), &buf) == 0) 18.524 +#endif 18.525 + AppendAllDeviceList(oss_device); 18.526 + } 18.527 + break; 18.528 + 18.529 + case CAPTURE_DEVICE_PROBE: 18.530 + { 18.531 +#ifdef HAVE_STAT 18.532 + struct stat buf; 18.533 + if(stat(GetConfigValue("oss", "capture", "/dev/dsp"), &buf) == 0) 18.534 +#endif 18.535 + AppendCaptureDeviceList(oss_device); 18.536 + } 18.537 + break; 18.538 + } 18.539 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 19.2 +++ b/Alc/backends/portaudio.c Tue Oct 25 13:02:31 2011 -0700 19.3 @@ -0,0 +1,449 @@ 19.4 +/** 19.5 + * OpenAL cross platform audio library 19.6 + * Copyright (C) 1999-2007 by authors. 19.7 + * This library is free software; you can redistribute it and/or 19.8 + * modify it under the terms of the GNU Library General Public 19.9 + * License as published by the Free Software Foundation; either 19.10 + * version 2 of the License, or (at your option) any later version. 19.11 + * 19.12 + * This library is distributed in the hope that it will be useful, 19.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 19.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19.15 + * Library General Public License for more details. 19.16 + * 19.17 + * You should have received a copy of the GNU Library General Public 19.18 + * License along with this library; if not, write to the 19.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 19.20 + * Boston, MA 02111-1307, USA. 19.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 19.22 + */ 19.23 + 19.24 +#include "config.h" 19.25 + 19.26 +#include <stdio.h> 19.27 +#include <stdlib.h> 19.28 +#include <string.h> 19.29 +#include "alMain.h" 19.30 +#include "AL/al.h" 19.31 +#include "AL/alc.h" 19.32 + 19.33 +#include <portaudio.h> 19.34 + 19.35 + 19.36 +static const ALCchar pa_device[] = "PortAudio Default"; 19.37 + 19.38 + 19.39 +static void *pa_handle; 19.40 +#ifdef HAVE_DYNLOAD 19.41 +#define MAKE_FUNC(x) static typeof(x) * p##x 19.42 +MAKE_FUNC(Pa_Initialize); 19.43 +MAKE_FUNC(Pa_Terminate); 19.44 +MAKE_FUNC(Pa_GetErrorText); 19.45 +MAKE_FUNC(Pa_StartStream); 19.46 +MAKE_FUNC(Pa_StopStream); 19.47 +MAKE_FUNC(Pa_OpenStream); 19.48 +MAKE_FUNC(Pa_CloseStream); 19.49 +MAKE_FUNC(Pa_GetDefaultOutputDevice); 19.50 +MAKE_FUNC(Pa_GetStreamInfo); 19.51 +#undef MAKE_FUNC 19.52 + 19.53 +#define Pa_Initialize pPa_Initialize 19.54 +#define Pa_Terminate pPa_Terminate 19.55 +#define Pa_GetErrorText pPa_GetErrorText 19.56 +#define Pa_StartStream pPa_StartStream 19.57 +#define Pa_StopStream pPa_StopStream 19.58 +#define Pa_OpenStream pPa_OpenStream 19.59 +#define Pa_CloseStream pPa_CloseStream 19.60 +#define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice 19.61 +#define Pa_GetStreamInfo pPa_GetStreamInfo 19.62 +#endif 19.63 + 19.64 +static ALCboolean pa_load(void) 19.65 +{ 19.66 + if(!pa_handle) 19.67 + { 19.68 + PaError err; 19.69 + 19.70 +#ifdef HAVE_DYNLOAD 19.71 +#ifdef _WIN32 19.72 +# define PALIB "portaudio.dll" 19.73 +#elif defined(__APPLE__) && defined(__MACH__) 19.74 +# define PALIB "libportaudio.2.dylib" 19.75 +#elif defined(__OpenBSD__) 19.76 +# define PALIB "libportaudio.so" 19.77 +#else 19.78 +# define PALIB "libportaudio.so.2" 19.79 +#endif 19.80 + 19.81 + pa_handle = LoadLib(PALIB); 19.82 + if(!pa_handle) 19.83 + return ALC_FALSE; 19.84 + 19.85 +#define LOAD_FUNC(f) do { \ 19.86 + p##f = GetSymbol(pa_handle, #f); \ 19.87 + if(p##f == NULL) \ 19.88 + { \ 19.89 + CloseLib(pa_handle); \ 19.90 + pa_handle = NULL; \ 19.91 + return ALC_FALSE; \ 19.92 + } \ 19.93 +} while(0) 19.94 + LOAD_FUNC(Pa_Initialize); 19.95 + LOAD_FUNC(Pa_Terminate); 19.96 + LOAD_FUNC(Pa_GetErrorText); 19.97 + LOAD_FUNC(Pa_StartStream); 19.98 + LOAD_FUNC(Pa_StopStream); 19.99 + LOAD_FUNC(Pa_OpenStream); 19.100 + LOAD_FUNC(Pa_CloseStream); 19.101 + LOAD_FUNC(Pa_GetDefaultOutputDevice); 19.102 + LOAD_FUNC(Pa_GetStreamInfo); 19.103 +#undef LOAD_FUNC 19.104 +#else 19.105 + pa_handle = (void*)0xDEADBEEF; 19.106 +#endif 19.107 + 19.108 + if((err=Pa_Initialize()) != paNoError) 19.109 + { 19.110 + ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err)); 19.111 + CloseLib(pa_handle); 19.112 + pa_handle = NULL; 19.113 + return ALC_FALSE; 19.114 + } 19.115 + } 19.116 + return ALC_TRUE; 19.117 +} 19.118 + 19.119 + 19.120 +typedef struct { 19.121 + PaStream *stream; 19.122 + ALuint update_size; 19.123 + 19.124 + RingBuffer *ring; 19.125 +} pa_data; 19.126 + 19.127 + 19.128 +static int pa_callback(const void *inputBuffer, void *outputBuffer, 19.129 + unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, 19.130 + const PaStreamCallbackFlags statusFlags, void *userData) 19.131 +{ 19.132 + ALCdevice *device = (ALCdevice*)userData; 19.133 + 19.134 + (void)inputBuffer; 19.135 + (void)timeInfo; 19.136 + (void)statusFlags; 19.137 + 19.138 + aluMixData(device, outputBuffer, framesPerBuffer); 19.139 + return 0; 19.140 +} 19.141 + 19.142 +static int pa_capture_cb(const void *inputBuffer, void *outputBuffer, 19.143 + unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, 19.144 + const PaStreamCallbackFlags statusFlags, void *userData) 19.145 +{ 19.146 + ALCdevice *device = (ALCdevice*)userData; 19.147 + pa_data *data = (pa_data*)device->ExtraData; 19.148 + 19.149 + (void)outputBuffer; 19.150 + (void)timeInfo; 19.151 + (void)statusFlags; 19.152 + 19.153 + WriteRingBuffer(data->ring, inputBuffer, framesPerBuffer); 19.154 + return 0; 19.155 +} 19.156 + 19.157 + 19.158 +static ALCboolean pa_open_playback(ALCdevice *device, const ALCchar *deviceName) 19.159 +{ 19.160 + PaStreamParameters outParams; 19.161 + pa_data *data; 19.162 + PaError err; 19.163 + 19.164 + if(!deviceName) 19.165 + deviceName = pa_device; 19.166 + else if(strcmp(deviceName, pa_device) != 0) 19.167 + return ALC_FALSE; 19.168 + 19.169 + data = (pa_data*)calloc(1, sizeof(pa_data)); 19.170 + data->update_size = device->UpdateSize; 19.171 + 19.172 + device->ExtraData = data; 19.173 + 19.174 + outParams.device = GetConfigValueInt("port", "device", -1); 19.175 + if(outParams.device < 0) 19.176 + outParams.device = Pa_GetDefaultOutputDevice(); 19.177 + outParams.suggestedLatency = (device->UpdateSize*device->NumUpdates) / 19.178 + (float)device->Frequency; 19.179 + outParams.hostApiSpecificStreamInfo = NULL; 19.180 + 19.181 + switch(device->FmtType) 19.182 + { 19.183 + case DevFmtByte: 19.184 + outParams.sampleFormat = paInt8; 19.185 + break; 19.186 + case DevFmtUByte: 19.187 + outParams.sampleFormat = paUInt8; 19.188 + break; 19.189 + case DevFmtUShort: 19.190 + device->FmtType = DevFmtShort; 19.191 + /* fall-through */ 19.192 + case DevFmtShort: 19.193 + outParams.sampleFormat = paInt16; 19.194 + break; 19.195 + case DevFmtFloat: 19.196 + outParams.sampleFormat = paFloat32; 19.197 + break; 19.198 + } 19.199 + outParams.channelCount = ((device->FmtChans == DevFmtMono) ? 1 : 2); 19.200 + 19.201 + SetDefaultChannelOrder(device); 19.202 + 19.203 + err = Pa_OpenStream(&data->stream, NULL, &outParams, device->Frequency, 19.204 + device->UpdateSize, paNoFlag, pa_callback, device); 19.205 + if(err != paNoError) 19.206 + { 19.207 + ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); 19.208 + device->ExtraData = NULL; 19.209 + free(data); 19.210 + return ALC_FALSE; 19.211 + } 19.212 + 19.213 + device->szDeviceName = strdup(deviceName); 19.214 + 19.215 + if((ALuint)outParams.channelCount != ChannelsFromDevFmt(device->FmtChans)) 19.216 + { 19.217 + if(outParams.channelCount != 1 && outParams.channelCount != 2) 19.218 + { 19.219 + ERR("Unhandled channel count: %u\n", outParams.channelCount); 19.220 + Pa_CloseStream(data->stream); 19.221 + device->ExtraData = NULL; 19.222 + free(data); 19.223 + return ALC_FALSE; 19.224 + } 19.225 + if((device->Flags&DEVICE_CHANNELS_REQUEST)) 19.226 + ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), outParams.channelCount); 19.227 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 19.228 + device->FmtChans = ((outParams.channelCount==1) ? DevFmtMono : DevFmtStereo); 19.229 + } 19.230 + 19.231 + return ALC_TRUE; 19.232 +} 19.233 + 19.234 +static void pa_close_playback(ALCdevice *device) 19.235 +{ 19.236 + pa_data *data = (pa_data*)device->ExtraData; 19.237 + PaError err; 19.238 + 19.239 + err = Pa_CloseStream(data->stream); 19.240 + if(err != paNoError) 19.241 + ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); 19.242 + 19.243 + free(data); 19.244 + device->ExtraData = NULL; 19.245 +} 19.246 + 19.247 +static ALCboolean pa_reset_playback(ALCdevice *device) 19.248 +{ 19.249 + pa_data *data = (pa_data*)device->ExtraData; 19.250 + const PaStreamInfo *streamInfo; 19.251 + PaError err; 19.252 + 19.253 + streamInfo = Pa_GetStreamInfo(data->stream); 19.254 + if(device->Frequency != streamInfo->sampleRate) 19.255 + { 19.256 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 19.257 + ERR("PortAudio does not support changing sample rates (wanted %dhz, got %.1fhz)\n", device->Frequency, streamInfo->sampleRate); 19.258 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 19.259 + device->Frequency = streamInfo->sampleRate; 19.260 + } 19.261 + device->UpdateSize = data->update_size; 19.262 + 19.263 + err = Pa_StartStream(data->stream); 19.264 + if(err != paNoError) 19.265 + { 19.266 + ERR("Pa_StartStream() returned an error: %s\n", Pa_GetErrorText(err)); 19.267 + return ALC_FALSE; 19.268 + } 19.269 + 19.270 + return ALC_TRUE; 19.271 +} 19.272 + 19.273 +static void pa_stop_playback(ALCdevice *device) 19.274 +{ 19.275 + pa_data *data = (pa_data*)device->ExtraData; 19.276 + PaError err; 19.277 + 19.278 + err = Pa_StopStream(data->stream); 19.279 + if(err != paNoError) 19.280 + ERR("Error stopping stream: %s\n", Pa_GetErrorText(err)); 19.281 +} 19.282 + 19.283 + 19.284 +static ALCboolean pa_open_capture(ALCdevice *device, const ALCchar *deviceName) 19.285 +{ 19.286 + PaStreamParameters inParams; 19.287 + ALuint frame_size; 19.288 + pa_data *data; 19.289 + PaError err; 19.290 + 19.291 + if(!deviceName) 19.292 + deviceName = pa_device; 19.293 + else if(strcmp(deviceName, pa_device) != 0) 19.294 + return ALC_FALSE; 19.295 + 19.296 + data = (pa_data*)calloc(1, sizeof(pa_data)); 19.297 + if(data == NULL) 19.298 + { 19.299 + alcSetError(device, ALC_OUT_OF_MEMORY); 19.300 + return ALC_FALSE; 19.301 + } 19.302 + 19.303 + frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 19.304 + data->ring = CreateRingBuffer(frame_size, device->UpdateSize*device->NumUpdates); 19.305 + if(data->ring == NULL) 19.306 + { 19.307 + alcSetError(device, ALC_OUT_OF_MEMORY); 19.308 + goto error; 19.309 + } 19.310 + 19.311 + inParams.device = GetConfigValueInt("port", "capture", -1); 19.312 + if(inParams.device < 0) 19.313 + inParams.device = Pa_GetDefaultOutputDevice(); 19.314 + inParams.suggestedLatency = 0.0f; 19.315 + inParams.hostApiSpecificStreamInfo = NULL; 19.316 + 19.317 + switch(device->FmtType) 19.318 + { 19.319 + case DevFmtByte: 19.320 + inParams.sampleFormat = paInt8; 19.321 + break; 19.322 + case DevFmtUByte: 19.323 + inParams.sampleFormat = paUInt8; 19.324 + break; 19.325 + case DevFmtShort: 19.326 + inParams.sampleFormat = paInt16; 19.327 + break; 19.328 + case DevFmtFloat: 19.329 + inParams.sampleFormat = paFloat32; 19.330 + break; 19.331 + case DevFmtUShort: 19.332 + ERR("Unsigned short samples not supported\n"); 19.333 + goto error; 19.334 + } 19.335 + inParams.channelCount = ChannelsFromDevFmt(device->FmtChans); 19.336 + 19.337 + err = Pa_OpenStream(&data->stream, &inParams, NULL, device->Frequency, 19.338 + paFramesPerBufferUnspecified, paNoFlag, pa_capture_cb, device); 19.339 + if(err != paNoError) 19.340 + { 19.341 + ERR("Pa_OpenStream() returned an error: %s\n", Pa_GetErrorText(err)); 19.342 + goto error; 19.343 + } 19.344 + 19.345 + device->szDeviceName = strdup(deviceName); 19.346 + 19.347 + device->ExtraData = data; 19.348 + return ALC_TRUE; 19.349 + 19.350 +error: 19.351 + DestroyRingBuffer(data->ring); 19.352 + free(data); 19.353 + return ALC_FALSE; 19.354 +} 19.355 + 19.356 +static void pa_close_capture(ALCdevice *device) 19.357 +{ 19.358 + pa_data *data = (pa_data*)device->ExtraData; 19.359 + PaError err; 19.360 + 19.361 + err = Pa_CloseStream(data->stream); 19.362 + if(err != paNoError) 19.363 + ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); 19.364 + 19.365 + free(data); 19.366 + device->ExtraData = NULL; 19.367 +} 19.368 + 19.369 +static void pa_start_capture(ALCdevice *device) 19.370 +{ 19.371 + pa_data *data = device->ExtraData; 19.372 + PaError err; 19.373 + 19.374 + err = Pa_StartStream(data->stream); 19.375 + if(err != paNoError) 19.376 + ERR("Error starting stream: %s\n", Pa_GetErrorText(err)); 19.377 +} 19.378 + 19.379 +static void pa_stop_capture(ALCdevice *device) 19.380 +{ 19.381 + pa_data *data = (pa_data*)device->ExtraData; 19.382 + PaError err; 19.383 + 19.384 + err = Pa_StopStream(data->stream); 19.385 + if(err != paNoError) 19.386 + ERR("Error stopping stream: %s\n", Pa_GetErrorText(err)); 19.387 +} 19.388 + 19.389 +static void pa_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) 19.390 +{ 19.391 + pa_data *data = device->ExtraData; 19.392 + if(samples <= (ALCuint)RingBufferSize(data->ring)) 19.393 + ReadRingBuffer(data->ring, buffer, samples); 19.394 + else 19.395 + alcSetError(device, ALC_INVALID_VALUE); 19.396 +} 19.397 + 19.398 +static ALCuint pa_available_samples(ALCdevice *device) 19.399 +{ 19.400 + pa_data *data = device->ExtraData; 19.401 + return RingBufferSize(data->ring); 19.402 +} 19.403 + 19.404 + 19.405 +static const BackendFuncs pa_funcs = { 19.406 + pa_open_playback, 19.407 + pa_close_playback, 19.408 + pa_reset_playback, 19.409 + pa_stop_playback, 19.410 + pa_open_capture, 19.411 + pa_close_capture, 19.412 + pa_start_capture, 19.413 + pa_stop_capture, 19.414 + pa_capture_samples, 19.415 + pa_available_samples 19.416 +}; 19.417 + 19.418 +ALCboolean alc_pa_init(BackendFuncs *func_list) 19.419 +{ 19.420 + if(!pa_load()) 19.421 + return ALC_FALSE; 19.422 + *func_list = pa_funcs; 19.423 + return ALC_TRUE; 19.424 +} 19.425 + 19.426 +void alc_pa_deinit(void) 19.427 +{ 19.428 + if(pa_handle) 19.429 + { 19.430 + Pa_Terminate(); 19.431 +#ifdef HAVE_DYNLOAD 19.432 + CloseLib(pa_handle); 19.433 +#endif 19.434 + pa_handle = NULL; 19.435 + } 19.436 +} 19.437 + 19.438 +void alc_pa_probe(enum DevProbe type) 19.439 +{ 19.440 + switch(type) 19.441 + { 19.442 + case DEVICE_PROBE: 19.443 + AppendDeviceList(pa_device); 19.444 + break; 19.445 + case ALL_DEVICE_PROBE: 19.446 + AppendAllDeviceList(pa_device); 19.447 + break; 19.448 + case CAPTURE_DEVICE_PROBE: 19.449 + AppendCaptureDeviceList(pa_device); 19.450 + break; 19.451 + } 19.452 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 20.2 +++ b/Alc/backends/pulseaudio.c Tue Oct 25 13:02:31 2011 -0700 20.3 @@ -0,0 +1,1418 @@ 20.4 +/** 20.5 + * OpenAL cross platform audio library 20.6 + * Copyright (C) 2009 by Konstantinos Natsakis <konstantinos.natsakis@gmail.com> 20.7 + * Copyright (C) 2010 by Chris Robinson <chris.kcat@gmail.com> 20.8 + * This library is free software; you can redistribute it and/or 20.9 + * modify it under the terms of the GNU Library General Public 20.10 + * License as published by the Free Software Foundation; either 20.11 + * version 2 of the License, or (at your option) any later version. 20.12 + * 20.13 + * This library is distributed in the hope that it will be useful, 20.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 20.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20.16 + * Library General Public License for more details. 20.17 + * 20.18 + * You should have received a copy of the GNU Library General Public 20.19 + * License along with this library; if not, write to the 20.20 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 20.21 + * Boston, MA 02111-1307, USA. 20.22 + * Or go to http://www.gnu.org/copyleft/lgpl.html 20.23 + */ 20.24 + 20.25 +#include "config.h" 20.26 + 20.27 +#include "alMain.h" 20.28 + 20.29 +#include <pulse/pulseaudio.h> 20.30 + 20.31 +#if PA_API_VERSION == 11 20.32 +#define PA_STREAM_ADJUST_LATENCY 0x2000U 20.33 +#define PA_STREAM_EARLY_REQUESTS 0x4000U 20.34 +static __inline int PA_STREAM_IS_GOOD(pa_stream_state_t x) 20.35 +{ 20.36 + return (x == PA_STREAM_CREATING || x == PA_STREAM_READY); 20.37 +} 20.38 +static __inline int PA_CONTEXT_IS_GOOD(pa_context_state_t x) 20.39 +{ 20.40 + return (x == PA_CONTEXT_CONNECTING || x == PA_CONTEXT_AUTHORIZING || 20.41 + x == PA_CONTEXT_SETTING_NAME || x == PA_CONTEXT_READY); 20.42 +} 20.43 +#define PA_STREAM_IS_GOOD PA_STREAM_IS_GOOD 20.44 +#define PA_CONTEXT_IS_GOOD PA_CONTEXT_IS_GOOD 20.45 +#elif PA_API_VERSION != 12 20.46 +#error Invalid PulseAudio API version 20.47 +#endif 20.48 + 20.49 +#ifndef PA_CHECK_VERSION 20.50 +#define PA_CHECK_VERSION(major,minor,micro) \ 20.51 + ((PA_MAJOR > (major)) || \ 20.52 + (PA_MAJOR == (major) && PA_MINOR > (minor)) || \ 20.53 + (PA_MAJOR == (major) && PA_MINOR == (minor) && PA_MICRO >= (micro))) 20.54 +#endif 20.55 + 20.56 +static void *pa_handle; 20.57 +#ifdef HAVE_DYNLOAD 20.58 +#define MAKE_FUNC(x) static typeof(x) * p##x 20.59 +MAKE_FUNC(pa_context_unref); 20.60 +MAKE_FUNC(pa_sample_spec_valid); 20.61 +MAKE_FUNC(pa_stream_drop); 20.62 +MAKE_FUNC(pa_strerror); 20.63 +MAKE_FUNC(pa_context_get_state); 20.64 +MAKE_FUNC(pa_stream_get_state); 20.65 +MAKE_FUNC(pa_threaded_mainloop_signal); 20.66 +MAKE_FUNC(pa_stream_peek); 20.67 +MAKE_FUNC(pa_threaded_mainloop_wait); 20.68 +MAKE_FUNC(pa_threaded_mainloop_unlock); 20.69 +MAKE_FUNC(pa_threaded_mainloop_in_thread); 20.70 +MAKE_FUNC(pa_context_new); 20.71 +MAKE_FUNC(pa_threaded_mainloop_stop); 20.72 +MAKE_FUNC(pa_context_disconnect); 20.73 +MAKE_FUNC(pa_threaded_mainloop_start); 20.74 +MAKE_FUNC(pa_threaded_mainloop_get_api); 20.75 +MAKE_FUNC(pa_context_set_state_callback); 20.76 +MAKE_FUNC(pa_stream_write); 20.77 +MAKE_FUNC(pa_xfree); 20.78 +MAKE_FUNC(pa_stream_connect_record); 20.79 +MAKE_FUNC(pa_stream_connect_playback); 20.80 +MAKE_FUNC(pa_stream_readable_size); 20.81 +MAKE_FUNC(pa_stream_writable_size); 20.82 +MAKE_FUNC(pa_stream_cork); 20.83 +MAKE_FUNC(pa_stream_is_suspended); 20.84 +MAKE_FUNC(pa_stream_get_device_name); 20.85 +MAKE_FUNC(pa_path_get_filename); 20.86 +MAKE_FUNC(pa_get_binary_name); 20.87 +MAKE_FUNC(pa_threaded_mainloop_free); 20.88 +MAKE_FUNC(pa_context_errno); 20.89 +MAKE_FUNC(pa_xmalloc); 20.90 +MAKE_FUNC(pa_stream_unref); 20.91 +MAKE_FUNC(pa_threaded_mainloop_accept); 20.92 +MAKE_FUNC(pa_stream_set_write_callback); 20.93 +MAKE_FUNC(pa_threaded_mainloop_new); 20.94 +MAKE_FUNC(pa_context_connect); 20.95 +MAKE_FUNC(pa_stream_set_buffer_attr); 20.96 +MAKE_FUNC(pa_stream_get_buffer_attr); 20.97 +MAKE_FUNC(pa_stream_get_sample_spec); 20.98 +MAKE_FUNC(pa_stream_get_time); 20.99 +MAKE_FUNC(pa_stream_set_read_callback); 20.100 +MAKE_FUNC(pa_stream_set_state_callback); 20.101 +MAKE_FUNC(pa_stream_set_moved_callback); 20.102 +MAKE_FUNC(pa_stream_set_underflow_callback); 20.103 +MAKE_FUNC(pa_stream_new); 20.104 +MAKE_FUNC(pa_stream_disconnect); 20.105 +MAKE_FUNC(pa_threaded_mainloop_lock); 20.106 +MAKE_FUNC(pa_channel_map_init_auto); 20.107 +MAKE_FUNC(pa_channel_map_parse); 20.108 +MAKE_FUNC(pa_channel_map_snprint); 20.109 +MAKE_FUNC(pa_channel_map_equal); 20.110 +MAKE_FUNC(pa_context_get_server_info); 20.111 +MAKE_FUNC(pa_context_get_sink_info_by_name); 20.112 +MAKE_FUNC(pa_context_get_sink_info_list); 20.113 +MAKE_FUNC(pa_context_get_source_info_list); 20.114 +MAKE_FUNC(pa_operation_get_state); 20.115 +MAKE_FUNC(pa_operation_unref); 20.116 +#if PA_CHECK_VERSION(0,9,15) 20.117 +MAKE_FUNC(pa_channel_map_superset); 20.118 +MAKE_FUNC(pa_stream_set_buffer_attr_callback); 20.119 +#endif 20.120 +#if PA_CHECK_VERSION(0,9,16) 20.121 +MAKE_FUNC(pa_stream_begin_write); 20.122 +#endif 20.123 +#undef MAKE_FUNC 20.124 + 20.125 +#define pa_context_unref ppa_context_unref 20.126 +#define pa_sample_spec_valid ppa_sample_spec_valid 20.127 +#define pa_stream_drop ppa_stream_drop 20.128 +#define pa_strerror ppa_strerror 20.129 +#define pa_context_get_state ppa_context_get_state 20.130 +#define pa_stream_get_state ppa_stream_get_state 20.131 +#define pa_threaded_mainloop_signal ppa_threaded_mainloop_signal 20.132 +#define pa_stream_peek ppa_stream_peek 20.133 +#define pa_threaded_mainloop_wait ppa_threaded_mainloop_wait 20.134 +#define pa_threaded_mainloop_unlock ppa_threaded_mainloop_unlock 20.135 +#define pa_threaded_mainloop_in_thread ppa_threaded_mainloop_in_thread 20.136 +#define pa_context_new ppa_context_new 20.137 +#define pa_threaded_mainloop_stop ppa_threaded_mainloop_stop 20.138 +#define pa_context_disconnect ppa_context_disconnect 20.139 +#define pa_threaded_mainloop_start ppa_threaded_mainloop_start 20.140 +#define pa_threaded_mainloop_get_api ppa_threaded_mainloop_get_api 20.141 +#define pa_context_set_state_callback ppa_context_set_state_callback 20.142 +#define pa_stream_write ppa_stream_write 20.143 +#define pa_xfree ppa_xfree 20.144 +#define pa_stream_connect_record ppa_stream_connect_record 20.145 +#define pa_stream_connect_playback ppa_stream_connect_playback 20.146 +#define pa_stream_readable_size ppa_stream_readable_size 20.147 +#define pa_stream_writable_size ppa_stream_writable_size 20.148 +#define pa_stream_cork ppa_stream_cork 20.149 +#define pa_stream_is_suspended ppa_stream_is_suspended 20.150 +#define pa_stream_get_device_name ppa_stream_get_device_name 20.151 +#define pa_path_get_filename ppa_path_get_filename 20.152 +#define pa_get_binary_name ppa_get_binary_name 20.153 +#define pa_threaded_mainloop_free ppa_threaded_mainloop_free 20.154 +#define pa_context_errno ppa_context_errno 20.155 +#define pa_xmalloc ppa_xmalloc 20.156 +#define pa_stream_unref ppa_stream_unref 20.157 +#define pa_threaded_mainloop_accept ppa_threaded_mainloop_accept 20.158 +#define pa_stream_set_write_callback ppa_stream_set_write_callback 20.159 +#define pa_threaded_mainloop_new ppa_threaded_mainloop_new 20.160 +#define pa_context_connect ppa_context_connect 20.161 +#define pa_stream_set_buffer_attr ppa_stream_set_buffer_attr 20.162 +#define pa_stream_get_buffer_attr ppa_stream_get_buffer_attr 20.163 +#define pa_stream_get_sample_spec ppa_stream_get_sample_spec 20.164 +#define pa_stream_get_time ppa_stream_get_time 20.165 +#define pa_stream_set_read_callback ppa_stream_set_read_callback 20.166 +#define pa_stream_set_state_callback ppa_stream_set_state_callback 20.167 +#define pa_stream_set_moved_callback ppa_stream_set_moved_callback 20.168 +#define pa_stream_set_underflow_callback ppa_stream_set_underflow_callback 20.169 +#define pa_stream_new ppa_stream_new 20.170 +#define pa_stream_disconnect ppa_stream_disconnect 20.171 +#define pa_threaded_mainloop_lock ppa_threaded_mainloop_lock 20.172 +#define pa_channel_map_init_auto ppa_channel_map_init_auto 20.173 +#define pa_channel_map_parse ppa_channel_map_parse 20.174 +#define pa_channel_map_snprint ppa_channel_map_snprint 20.175 +#define pa_channel_map_equal ppa_channel_map_equal 20.176 +#define pa_context_get_server_info ppa_context_get_server_info 20.177 +#define pa_context_get_sink_info_by_name ppa_context_get_sink_info_by_name 20.178 +#define pa_context_get_sink_info_list ppa_context_get_sink_info_list 20.179 +#define pa_context_get_source_info_list ppa_context_get_source_info_list 20.180 +#define pa_operation_get_state ppa_operation_get_state 20.181 +#define pa_operation_unref ppa_operation_unref 20.182 +#if PA_CHECK_VERSION(0,9,15) 20.183 +#define pa_channel_map_superset ppa_channel_map_superset 20.184 +#define pa_stream_set_buffer_attr_callback ppa_stream_set_buffer_attr_callback 20.185 +#endif 20.186 +#if PA_CHECK_VERSION(0,9,16) 20.187 +#define pa_stream_begin_write ppa_stream_begin_write 20.188 +#endif 20.189 + 20.190 +#endif 20.191 + 20.192 +#ifndef PATH_MAX 20.193 +#define PATH_MAX 4096 20.194 +#endif 20.195 + 20.196 +typedef struct { 20.197 + char *device_name; 20.198 + 20.199 + ALCuint samples; 20.200 + ALCuint frame_size; 20.201 + 20.202 + RingBuffer *ring; 20.203 + 20.204 + pa_buffer_attr attr; 20.205 + pa_sample_spec spec; 20.206 + 20.207 + pa_threaded_mainloop *loop; 20.208 + 20.209 + ALvoid *thread; 20.210 + volatile ALboolean killNow; 20.211 + 20.212 + pa_stream *stream; 20.213 + pa_context *context; 20.214 +} pulse_data; 20.215 + 20.216 +typedef struct { 20.217 + char *name; 20.218 + char *device_name; 20.219 +} DevMap; 20.220 + 20.221 + 20.222 +static const ALCchar pulse_device[] = "PulseAudio Default"; 20.223 +static DevMap *allDevNameMap; 20.224 +static ALuint numDevNames; 20.225 +static DevMap *allCaptureDevNameMap; 20.226 +static ALuint numCaptureDevNames; 20.227 +static pa_context_flags_t pulse_ctx_flags; 20.228 + 20.229 + 20.230 +static void context_state_callback(pa_context *context, void *pdata) 20.231 +{ 20.232 + pa_threaded_mainloop *loop = pdata; 20.233 + pa_context_state_t state; 20.234 + 20.235 + state = pa_context_get_state(context); 20.236 + if(state == PA_CONTEXT_READY || !PA_CONTEXT_IS_GOOD(state)) 20.237 + pa_threaded_mainloop_signal(loop, 0); 20.238 +} 20.239 + 20.240 +static pa_context *connect_context(pa_threaded_mainloop *loop, ALboolean silent) 20.241 +{ 20.242 + const char *name = "OpenAL Soft"; 20.243 + char path_name[PATH_MAX]; 20.244 + pa_context_state_t state; 20.245 + pa_context *context; 20.246 + int err; 20.247 + 20.248 + if(pa_get_binary_name(path_name, sizeof(path_name))) 20.249 + name = pa_path_get_filename(path_name); 20.250 + 20.251 + context = pa_context_new(pa_threaded_mainloop_get_api(loop), name); 20.252 + if(!context) 20.253 + { 20.254 + ERR("pa_context_new() failed\n"); 20.255 + return NULL; 20.256 + } 20.257 + 20.258 + pa_context_set_state_callback(context, context_state_callback, loop); 20.259 + 20.260 + if((err=pa_context_connect(context, NULL, pulse_ctx_flags, NULL)) >= 0) 20.261 + { 20.262 + while((state=pa_context_get_state(context)) != PA_CONTEXT_READY) 20.263 + { 20.264 + if(!PA_CONTEXT_IS_GOOD(state)) 20.265 + { 20.266 + err = pa_context_errno(context); 20.267 + if(err > 0) err = -err; 20.268 + break; 20.269 + } 20.270 + 20.271 + pa_threaded_mainloop_wait(loop); 20.272 + } 20.273 + } 20.274 + pa_context_set_state_callback(context, NULL, NULL); 20.275 + 20.276 + if(err < 0) 20.277 + { 20.278 + if(!silent) 20.279 + ERR("Context did not connect: %s\n", pa_strerror(err)); 20.280 + pa_context_unref(context); 20.281 + return NULL; 20.282 + } 20.283 + 20.284 + return context; 20.285 +} 20.286 + 20.287 + 20.288 +static ALCboolean pulse_load(void) //{{{ 20.289 +{ 20.290 + ALCboolean ret = ALC_FALSE; 20.291 + if(!pa_handle) 20.292 + { 20.293 + pa_threaded_mainloop *loop; 20.294 + 20.295 +#ifdef HAVE_DYNLOAD 20.296 + 20.297 +#ifdef _WIN32 20.298 +#define PALIB "libpulse-0.dll" 20.299 +#elif defined(__APPLE__) && defined(__MACH__) 20.300 +#define PALIB "libpulse.0.dylib" 20.301 +#else 20.302 +#define PALIB "libpulse.so.0" 20.303 +#endif 20.304 + pa_handle = LoadLib(PALIB); 20.305 + if(!pa_handle) 20.306 + return ALC_FALSE; 20.307 + 20.308 +#define LOAD_FUNC(x) do { \ 20.309 + p##x = GetSymbol(pa_handle, #x); \ 20.310 + if(!(p##x)) { \ 20.311 + CloseLib(pa_handle); \ 20.312 + pa_handle = NULL; \ 20.313 + return ALC_FALSE; \ 20.314 + } \ 20.315 +} while(0) 20.316 + LOAD_FUNC(pa_context_unref); 20.317 + LOAD_FUNC(pa_sample_spec_valid); 20.318 + LOAD_FUNC(pa_stream_drop); 20.319 + LOAD_FUNC(pa_strerror); 20.320 + LOAD_FUNC(pa_context_get_state); 20.321 + LOAD_FUNC(pa_stream_get_state); 20.322 + LOAD_FUNC(pa_threaded_mainloop_signal); 20.323 + LOAD_FUNC(pa_stream_peek); 20.324 + LOAD_FUNC(pa_threaded_mainloop_wait); 20.325 + LOAD_FUNC(pa_threaded_mainloop_unlock); 20.326 + LOAD_FUNC(pa_threaded_mainloop_in_thread); 20.327 + LOAD_FUNC(pa_context_new); 20.328 + LOAD_FUNC(pa_threaded_mainloop_stop); 20.329 + LOAD_FUNC(pa_context_disconnect); 20.330 + LOAD_FUNC(pa_threaded_mainloop_start); 20.331 + LOAD_FUNC(pa_threaded_mainloop_get_api); 20.332 + LOAD_FUNC(pa_context_set_state_callback); 20.333 + LOAD_FUNC(pa_stream_write); 20.334 + LOAD_FUNC(pa_xfree); 20.335 + LOAD_FUNC(pa_stream_connect_record); 20.336 + LOAD_FUNC(pa_stream_connect_playback); 20.337 + LOAD_FUNC(pa_stream_readable_size); 20.338 + LOAD_FUNC(pa_stream_writable_size); 20.339 + LOAD_FUNC(pa_stream_cork); 20.340 + LOAD_FUNC(pa_stream_is_suspended); 20.341 + LOAD_FUNC(pa_stream_get_device_name); 20.342 + LOAD_FUNC(pa_path_get_filename); 20.343 + LOAD_FUNC(pa_get_binary_name); 20.344 + LOAD_FUNC(pa_threaded_mainloop_free); 20.345 + LOAD_FUNC(pa_context_errno); 20.346 + LOAD_FUNC(pa_xmalloc); 20.347 + LOAD_FUNC(pa_stream_unref); 20.348 + LOAD_FUNC(pa_threaded_mainloop_accept); 20.349 + LOAD_FUNC(pa_stream_set_write_callback); 20.350 + LOAD_FUNC(pa_threaded_mainloop_new); 20.351 + LOAD_FUNC(pa_context_connect); 20.352 + LOAD_FUNC(pa_stream_set_buffer_attr); 20.353 + LOAD_FUNC(pa_stream_get_buffer_attr); 20.354 + LOAD_FUNC(pa_stream_get_sample_spec); 20.355 + LOAD_FUNC(pa_stream_get_time); 20.356 + LOAD_FUNC(pa_stream_set_read_callback); 20.357 + LOAD_FUNC(pa_stream_set_state_callback); 20.358 + LOAD_FUNC(pa_stream_set_moved_callback); 20.359 + LOAD_FUNC(pa_stream_set_underflow_callback); 20.360 + LOAD_FUNC(pa_stream_new); 20.361 + LOAD_FUNC(pa_stream_disconnect); 20.362 + LOAD_FUNC(pa_threaded_mainloop_lock); 20.363 + LOAD_FUNC(pa_channel_map_init_auto); 20.364 + LOAD_FUNC(pa_channel_map_parse); 20.365 + LOAD_FUNC(pa_channel_map_snprint); 20.366 + LOAD_FUNC(pa_channel_map_equal); 20.367 + LOAD_FUNC(pa_context_get_server_info); 20.368 + LOAD_FUNC(pa_context_get_sink_info_by_name); 20.369 + LOAD_FUNC(pa_context_get_sink_info_list); 20.370 + LOAD_FUNC(pa_context_get_source_info_list); 20.371 + LOAD_FUNC(pa_operation_get_state); 20.372 + LOAD_FUNC(pa_operation_unref); 20.373 +#undef LOAD_FUNC 20.374 +#define LOAD_OPTIONAL_FUNC(x) do { \ 20.375 + p##x = GetSymbol(pa_handle, #x); \ 20.376 +} while(0) 20.377 +#if PA_CHECK_VERSION(0,9,15) 20.378 + LOAD_OPTIONAL_FUNC(pa_channel_map_superset); 20.379 + LOAD_OPTIONAL_FUNC(pa_stream_set_buffer_attr_callback); 20.380 +#endif 20.381 +#if PA_CHECK_VERSION(0,9,16) 20.382 + LOAD_OPTIONAL_FUNC(pa_stream_begin_write); 20.383 +#endif 20.384 +#undef LOAD_OPTIONAL_FUNC 20.385 + 20.386 +#else /* HAVE_DYNLOAD */ 20.387 + pa_handle = (void*)0xDEADBEEF; 20.388 +#endif 20.389 + 20.390 + if((loop=pa_threaded_mainloop_new()) && 20.391 + pa_threaded_mainloop_start(loop) >= 0) 20.392 + { 20.393 + pa_context *context; 20.394 + 20.395 + pa_threaded_mainloop_lock(loop); 20.396 + context = connect_context(loop, AL_TRUE); 20.397 + if(context) 20.398 + { 20.399 + ret = ALC_TRUE; 20.400 + 20.401 + pa_context_disconnect(context); 20.402 + pa_context_unref(context); 20.403 + } 20.404 + pa_threaded_mainloop_unlock(loop); 20.405 + pa_threaded_mainloop_stop(loop); 20.406 + } 20.407 + if(loop) 20.408 + pa_threaded_mainloop_free(loop); 20.409 + 20.410 + if(!ret) 20.411 + { 20.412 +#ifdef HAVE_DYNLOAD 20.413 + CloseLib(pa_handle); 20.414 +#endif 20.415 + pa_handle = NULL; 20.416 + } 20.417 + } 20.418 + return ret; 20.419 +} //}}} 20.420 + 20.421 +// PulseAudio Event Callbacks //{{{ 20.422 +static void stream_state_callback(pa_stream *stream, void *pdata) //{{{ 20.423 +{ 20.424 + pa_threaded_mainloop *loop = pdata; 20.425 + pa_stream_state_t state; 20.426 + 20.427 + state = pa_stream_get_state(stream); 20.428 + if(state == PA_STREAM_READY || !PA_STREAM_IS_GOOD(state)) 20.429 + pa_threaded_mainloop_signal(loop, 0); 20.430 +}//}}} 20.431 + 20.432 +static void stream_signal_callback(pa_stream *stream, void *pdata) //{{{ 20.433 +{ 20.434 + ALCdevice *Device = pdata; 20.435 + pulse_data *data = Device->ExtraData; 20.436 + (void)stream; 20.437 + 20.438 + pa_threaded_mainloop_signal(data->loop, 0); 20.439 +}//}}} 20.440 + 20.441 +static void stream_buffer_attr_callback(pa_stream *stream, void *pdata) //{{{ 20.442 +{ 20.443 + ALCdevice *Device = pdata; 20.444 + pulse_data *data = Device->ExtraData; 20.445 + 20.446 + LockDevice(Device); 20.447 + 20.448 + data->attr = *(pa_stream_get_buffer_attr(stream)); 20.449 + Device->UpdateSize = data->attr.minreq / data->frame_size; 20.450 + Device->NumUpdates = (data->attr.tlength/data->frame_size) / Device->UpdateSize; 20.451 + if(Device->NumUpdates <= 1) 20.452 + { 20.453 + Device->NumUpdates = 1; 20.454 + ERR("PulseAudio returned minreq > tlength/2; expect break up\n"); 20.455 + } 20.456 + 20.457 + UnlockDevice(Device); 20.458 +}//}}} 20.459 + 20.460 +static void stream_device_callback(pa_stream *stream, void *pdata) //{{{ 20.461 +{ 20.462 + ALCdevice *Device = pdata; 20.463 + pulse_data *data = Device->ExtraData; 20.464 + 20.465 + free(data->device_name); 20.466 + data->device_name = strdup(pa_stream_get_device_name(stream)); 20.467 +}//}}} 20.468 + 20.469 +static void context_state_callback2(pa_context *context, void *pdata) //{{{ 20.470 +{ 20.471 + ALCdevice *Device = pdata; 20.472 + pulse_data *data = Device->ExtraData; 20.473 + 20.474 + if(pa_context_get_state(context) == PA_CONTEXT_FAILED) 20.475 + { 20.476 + ERR("Received context failure!\n"); 20.477 + aluHandleDisconnect(Device); 20.478 + } 20.479 + pa_threaded_mainloop_signal(data->loop, 0); 20.480 +}//}}} 20.481 + 20.482 +static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{ 20.483 +{ 20.484 + ALCdevice *Device = pdata; 20.485 + pulse_data *data = Device->ExtraData; 20.486 + 20.487 + if(pa_stream_get_state(stream) == PA_STREAM_FAILED) 20.488 + { 20.489 + ERR("Received stream failure!\n"); 20.490 + aluHandleDisconnect(Device); 20.491 + } 20.492 + pa_threaded_mainloop_signal(data->loop, 0); 20.493 +}//}}} 20.494 + 20.495 +static void stream_success_callback(pa_stream *stream, int success, void *pdata) //{{{ 20.496 +{ 20.497 + ALCdevice *Device = pdata; 20.498 + pulse_data *data = Device->ExtraData; 20.499 + (void)stream; 20.500 + (void)success; 20.501 + 20.502 + pa_threaded_mainloop_signal(data->loop, 0); 20.503 +}//}}} 20.504 + 20.505 +static void sink_info_callback(pa_context *context, const pa_sink_info *info, int eol, void *pdata) //{{{ 20.506 +{ 20.507 + ALCdevice *device = pdata; 20.508 + pulse_data *data = device->ExtraData; 20.509 + char chanmap_str[256] = ""; 20.510 + const struct { 20.511 + const char *str; 20.512 + enum DevFmtChannels chans; 20.513 + } chanmaps[] = { 20.514 + { "front-left,front-right,front-center,lfe,rear-left,rear-right,side-left,side-right", 20.515 + DevFmtX71 }, 20.516 + { "front-left,front-right,front-center,lfe,rear-center,side-left,side-right", 20.517 + DevFmtX61 }, 20.518 + { "front-left,front-right,front-center,lfe,rear-left,rear-right", 20.519 + DevFmtX51 }, 20.520 + { "front-left,front-right,front-center,lfe,side-left,side-right", 20.521 + DevFmtX51Side }, 20.522 + { "front-left,front-right,rear-left,rear-right", DevFmtQuad }, 20.523 + { "front-left,front-right", DevFmtStereo }, 20.524 + { "mono", DevFmtMono }, 20.525 + { NULL, 0 } 20.526 + }; 20.527 + int i; 20.528 + (void)context; 20.529 + 20.530 + if(eol) 20.531 + { 20.532 + pa_threaded_mainloop_signal(data->loop, 0); 20.533 + return; 20.534 + } 20.535 + 20.536 + for(i = 0;chanmaps[i].str;i++) 20.537 + { 20.538 + pa_channel_map map; 20.539 + if(!pa_channel_map_parse(&map, chanmaps[i].str)) 20.540 + continue; 20.541 + 20.542 + if(pa_channel_map_equal(&info->channel_map, &map) 20.543 +#if PA_CHECK_VERSION(0,9,15) 20.544 + || (pa_channel_map_superset && 20.545 + pa_channel_map_superset(&info->channel_map, &map)) 20.546 +#endif 20.547 + ) 20.548 + { 20.549 + device->FmtChans = chanmaps[i].chans; 20.550 + return; 20.551 + } 20.552 + } 20.553 + 20.554 + pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map); 20.555 + ERR("Failed to find format for channel map:\n %s\n", chanmap_str); 20.556 +}//}}} 20.557 + 20.558 +static void sink_device_callback(pa_context *context, const pa_sink_info *info, int eol, void *pdata) //{{{ 20.559 +{ 20.560 + pa_threaded_mainloop *loop = pdata; 20.561 + char str[1024]; 20.562 + void *temp; 20.563 + int count; 20.564 + ALuint i; 20.565 + 20.566 + (void)context; 20.567 + 20.568 + if(eol) 20.569 + { 20.570 + pa_threaded_mainloop_signal(loop, 0); 20.571 + return; 20.572 + } 20.573 + 20.574 + count = 0; 20.575 + do { 20.576 + if(count == 0) 20.577 + snprintf(str, sizeof(str), "%s", info->description); 20.578 + else 20.579 + snprintf(str, sizeof(str), "%s #%d", info->description, count+1); 20.580 + count++; 20.581 + 20.582 + for(i = 0;i < numDevNames;i++) 20.583 + { 20.584 + if(strcmp(str, allDevNameMap[i].name) == 0) 20.585 + break; 20.586 + } 20.587 + } while(i != numDevNames); 20.588 + 20.589 + temp = realloc(allDevNameMap, (numDevNames+1) * sizeof(*allDevNameMap)); 20.590 + if(temp) 20.591 + { 20.592 + allDevNameMap = temp; 20.593 + allDevNameMap[numDevNames].name = strdup(str); 20.594 + allDevNameMap[numDevNames].device_name = strdup(info->name); 20.595 + numDevNames++; 20.596 + } 20.597 +}//}}} 20.598 + 20.599 +static void source_device_callback(pa_context *context, const pa_source_info *info, int eol, void *pdata) //{{{ 20.600 +{ 20.601 + pa_threaded_mainloop *loop = pdata; 20.602 + char str[1024]; 20.603 + void *temp; 20.604 + int count; 20.605 + ALuint i; 20.606 + 20.607 + (void)context; 20.608 + 20.609 + if(eol) 20.610 + { 20.611 + pa_threaded_mainloop_signal(loop, 0); 20.612 + return; 20.613 + } 20.614 + 20.615 + count = 0; 20.616 + do { 20.617 + if(count == 0) 20.618 + snprintf(str, sizeof(str), "%s", info->description); 20.619 + else 20.620 + snprintf(str, sizeof(str), "%s #%d", info->description, count+1); 20.621 + count++; 20.622 + 20.623 + for(i = 0;i < numCaptureDevNames;i++) 20.624 + { 20.625 + if(strcmp(str, allCaptureDevNameMap[i].name) == 0) 20.626 + break; 20.627 + } 20.628 + } while(i != numCaptureDevNames); 20.629 + 20.630 + temp = realloc(allCaptureDevNameMap, (numCaptureDevNames+1) * sizeof(*allCaptureDevNameMap)); 20.631 + if(temp) 20.632 + { 20.633 + allCaptureDevNameMap = temp; 20.634 + allCaptureDevNameMap[numCaptureDevNames].name = strdup(str); 20.635 + allCaptureDevNameMap[numCaptureDevNames].device_name = strdup(info->name); 20.636 + numCaptureDevNames++; 20.637 + } 20.638 +}//}}} 20.639 +//}}} 20.640 + 20.641 +// PulseAudio I/O Callbacks //{{{ 20.642 +static void stream_write_callback(pa_stream *stream, size_t len, void *pdata) //{{{ 20.643 +{ 20.644 + ALCdevice *Device = pdata; 20.645 + pulse_data *data = Device->ExtraData; 20.646 + (void)stream; 20.647 + (void)len; 20.648 + 20.649 + pa_threaded_mainloop_signal(data->loop, 0); 20.650 +} //}}} 20.651 +//}}} 20.652 + 20.653 +static ALuint PulseProc(ALvoid *param) 20.654 +{ 20.655 + ALCdevice *Device = param; 20.656 + pulse_data *data = Device->ExtraData; 20.657 + ssize_t len; 20.658 + 20.659 + SetRTPriority(); 20.660 + 20.661 + pa_threaded_mainloop_lock(data->loop); 20.662 + do { 20.663 + len = (Device->Connected ? pa_stream_writable_size(data->stream) : 0); 20.664 + len -= len%(Device->UpdateSize*data->frame_size); 20.665 + if(len == 0) 20.666 + { 20.667 + pa_threaded_mainloop_wait(data->loop); 20.668 + continue; 20.669 + } 20.670 + 20.671 + while(len > 0) 20.672 + { 20.673 + size_t newlen = len; 20.674 + void *buf; 20.675 + pa_free_cb_t free_func = NULL; 20.676 + 20.677 +#if PA_CHECK_VERSION(0,9,16) 20.678 + if(!pa_stream_begin_write || 20.679 + pa_stream_begin_write(data->stream, &buf, &newlen) < 0) 20.680 +#endif 20.681 + { 20.682 + buf = pa_xmalloc(newlen); 20.683 + free_func = pa_xfree; 20.684 + } 20.685 + pa_threaded_mainloop_unlock(data->loop); 20.686 + 20.687 + aluMixData(Device, buf, newlen/data->frame_size); 20.688 + 20.689 + pa_threaded_mainloop_lock(data->loop); 20.690 + pa_stream_write(data->stream, buf, newlen, free_func, 0, PA_SEEK_RELATIVE); 20.691 + len -= newlen; 20.692 + } 20.693 + } while(Device->Connected && !data->killNow); 20.694 + pa_threaded_mainloop_unlock(data->loop); 20.695 + 20.696 + return 0; 20.697 +} 20.698 + 20.699 +static pa_stream *connect_playback_stream(ALCdevice *device, 20.700 + pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, 20.701 + pa_channel_map *chanmap) 20.702 +{ 20.703 + pulse_data *data = device->ExtraData; 20.704 + pa_stream_state_t state; 20.705 + pa_stream *stream; 20.706 + 20.707 + stream = pa_stream_new(data->context, "Playback Stream", spec, chanmap); 20.708 + if(!stream) 20.709 + { 20.710 + ERR("pa_stream_new() failed: %s\n", 20.711 + pa_strerror(pa_context_errno(data->context))); 20.712 + return NULL; 20.713 + } 20.714 + 20.715 + pa_stream_set_state_callback(stream, stream_state_callback, data->loop); 20.716 + 20.717 + if(pa_stream_connect_playback(stream, data->device_name, attr, flags, NULL, NULL) < 0) 20.718 + { 20.719 + ERR("Stream did not connect: %s\n", 20.720 + pa_strerror(pa_context_errno(data->context))); 20.721 + pa_stream_unref(stream); 20.722 + return NULL; 20.723 + } 20.724 + 20.725 + while((state=pa_stream_get_state(stream)) != PA_STREAM_READY) 20.726 + { 20.727 + if(!PA_STREAM_IS_GOOD(state)) 20.728 + { 20.729 + ERR("Stream did not get ready: %s\n", 20.730 + pa_strerror(pa_context_errno(data->context))); 20.731 + pa_stream_unref(stream); 20.732 + return NULL; 20.733 + } 20.734 + 20.735 + pa_threaded_mainloop_wait(data->loop); 20.736 + } 20.737 + pa_stream_set_state_callback(stream, NULL, NULL); 20.738 + 20.739 + return stream; 20.740 +} 20.741 + 20.742 +static void probe_devices(ALboolean capture) 20.743 +{ 20.744 + pa_threaded_mainloop *loop; 20.745 + 20.746 + if(capture == AL_FALSE) 20.747 + allDevNameMap = malloc(sizeof(DevMap) * 1); 20.748 + else 20.749 + allCaptureDevNameMap = malloc(sizeof(DevMap) * 1); 20.750 + 20.751 + if((loop=pa_threaded_mainloop_new()) && 20.752 + pa_threaded_mainloop_start(loop) >= 0) 20.753 + { 20.754 + pa_context *context; 20.755 + 20.756 + pa_threaded_mainloop_lock(loop); 20.757 + context = connect_context(loop, AL_FALSE); 20.758 + if(context) 20.759 + { 20.760 + pa_operation *o; 20.761 + 20.762 + if(capture == AL_FALSE) 20.763 + o = pa_context_get_sink_info_list(context, sink_device_callback, loop); 20.764 + else 20.765 + o = pa_context_get_source_info_list(context, source_device_callback, loop); 20.766 + while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) 20.767 + pa_threaded_mainloop_wait(loop); 20.768 + pa_operation_unref(o); 20.769 + 20.770 + pa_context_disconnect(context); 20.771 + pa_context_unref(context); 20.772 + } 20.773 + pa_threaded_mainloop_unlock(loop); 20.774 + pa_threaded_mainloop_stop(loop); 20.775 + } 20.776 + if(loop) 20.777 + pa_threaded_mainloop_free(loop); 20.778 +} 20.779 + 20.780 + 20.781 +static ALCboolean pulse_open(ALCdevice *device, const ALCchar *device_name) //{{{ 20.782 +{ 20.783 + pulse_data *data = pa_xmalloc(sizeof(pulse_data)); 20.784 + memset(data, 0, sizeof(*data)); 20.785 + 20.786 + if(!(data->loop = pa_threaded_mainloop_new())) 20.787 + { 20.788 + ERR("pa_threaded_mainloop_new() failed!\n"); 20.789 + goto out; 20.790 + } 20.791 + if(pa_threaded_mainloop_start(data->loop) < 0) 20.792 + { 20.793 + ERR("pa_threaded_mainloop_start() failed\n"); 20.794 + goto out; 20.795 + } 20.796 + 20.797 + pa_threaded_mainloop_lock(data->loop); 20.798 + device->ExtraData = data; 20.799 + 20.800 + data->context = connect_context(data->loop, AL_FALSE); 20.801 + if(!data->context) 20.802 + { 20.803 + pa_threaded_mainloop_unlock(data->loop); 20.804 + goto out; 20.805 + } 20.806 + pa_context_set_state_callback(data->context, context_state_callback2, device); 20.807 + 20.808 + device->szDeviceName = strdup(device_name); 20.809 + 20.810 + pa_threaded_mainloop_unlock(data->loop); 20.811 + return ALC_TRUE; 20.812 + 20.813 +out: 20.814 + if(data->loop) 20.815 + { 20.816 + pa_threaded_mainloop_stop(data->loop); 20.817 + pa_threaded_mainloop_free(data->loop); 20.818 + } 20.819 + 20.820 + device->ExtraData = NULL; 20.821 + pa_xfree(data); 20.822 + return ALC_FALSE; 20.823 +} //}}} 20.824 + 20.825 +static void pulse_close(ALCdevice *device) //{{{ 20.826 +{ 20.827 + pulse_data *data = device->ExtraData; 20.828 + 20.829 + pa_threaded_mainloop_lock(data->loop); 20.830 + 20.831 + if(data->stream) 20.832 + { 20.833 + pa_stream_disconnect(data->stream); 20.834 + pa_stream_unref(data->stream); 20.835 + } 20.836 + 20.837 + pa_context_disconnect(data->context); 20.838 + pa_context_unref(data->context); 20.839 + 20.840 + pa_threaded_mainloop_unlock(data->loop); 20.841 + 20.842 + pa_threaded_mainloop_stop(data->loop); 20.843 + pa_threaded_mainloop_free(data->loop); 20.844 + 20.845 + DestroyRingBuffer(data->ring); 20.846 + free(data->device_name); 20.847 + 20.848 + device->ExtraData = NULL; 20.849 + pa_xfree(data); 20.850 +} //}}} 20.851 +//}}} 20.852 + 20.853 +// OpenAL {{{ 20.854 +static ALCboolean pulse_open_playback(ALCdevice *device, const ALCchar *device_name) //{{{ 20.855 +{ 20.856 + char *pulse_name = NULL; 20.857 + pa_sample_spec spec; 20.858 + pulse_data *data; 20.859 + 20.860 + if(!allDevNameMap) 20.861 + probe_devices(AL_FALSE); 20.862 + 20.863 + if(!device_name) 20.864 + device_name = pulse_device; 20.865 + else if(strcmp(device_name, pulse_device) != 0) 20.866 + { 20.867 + ALuint i; 20.868 + 20.869 + for(i = 0;i < numDevNames;i++) 20.870 + { 20.871 + if(strcmp(device_name, allDevNameMap[i].name) == 0) 20.872 + { 20.873 + pulse_name = allDevNameMap[i].device_name; 20.874 + break; 20.875 + } 20.876 + } 20.877 + if(i == numDevNames) 20.878 + return ALC_FALSE; 20.879 + } 20.880 + 20.881 + if(pulse_open(device, device_name) == ALC_FALSE) 20.882 + return ALC_FALSE; 20.883 + 20.884 + data = device->ExtraData; 20.885 + 20.886 + pa_threaded_mainloop_lock(data->loop); 20.887 + 20.888 + spec.format = PA_SAMPLE_S16NE; 20.889 + spec.rate = 44100; 20.890 + spec.channels = 2; 20.891 + 20.892 + data->device_name = pulse_name; 20.893 + pa_stream *stream = connect_playback_stream(device, 0, NULL, &spec, NULL); 20.894 + if(!stream) 20.895 + { 20.896 + pa_threaded_mainloop_unlock(data->loop); 20.897 + goto fail; 20.898 + } 20.899 + 20.900 + if(pa_stream_is_suspended(stream)) 20.901 + { 20.902 + ERR("Device is suspended\n"); 20.903 + pa_stream_disconnect(stream); 20.904 + pa_stream_unref(stream); 20.905 + pa_threaded_mainloop_unlock(data->loop); 20.906 + goto fail; 20.907 + } 20.908 + data->device_name = strdup(pa_stream_get_device_name(stream)); 20.909 + 20.910 + pa_stream_disconnect(stream); 20.911 + pa_stream_unref(stream); 20.912 + 20.913 + pa_threaded_mainloop_unlock(data->loop); 20.914 + 20.915 + return ALC_TRUE; 20.916 + 20.917 +fail: 20.918 + pulse_close(device); 20.919 + return ALC_FALSE; 20.920 +} //}}} 20.921 + 20.922 +static void pulse_close_playback(ALCdevice *device) //{{{ 20.923 +{ 20.924 + pulse_close(device); 20.925 +} //}}} 20.926 + 20.927 +static ALCboolean pulse_reset_playback(ALCdevice *device) //{{{ 20.928 +{ 20.929 + pulse_data *data = device->ExtraData; 20.930 + pa_stream_flags_t flags = 0; 20.931 + pa_channel_map chanmap; 20.932 + 20.933 + pa_threaded_mainloop_lock(data->loop); 20.934 + 20.935 + if(!(device->Flags&DEVICE_CHANNELS_REQUEST)) 20.936 + { 20.937 + pa_operation *o; 20.938 + o = pa_context_get_sink_info_by_name(data->context, data->device_name, sink_info_callback, device); 20.939 + while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) 20.940 + pa_threaded_mainloop_wait(data->loop); 20.941 + pa_operation_unref(o); 20.942 + } 20.943 + if(!(device->Flags&DEVICE_FREQUENCY_REQUEST)) 20.944 + flags |= PA_STREAM_FIX_RATE; 20.945 + 20.946 + data->frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 20.947 + data->attr.prebuf = -1; 20.948 + data->attr.fragsize = -1; 20.949 + data->attr.minreq = device->UpdateSize * data->frame_size; 20.950 + data->attr.tlength = data->attr.minreq * device->NumUpdates; 20.951 + if(data->attr.tlength < data->attr.minreq*2) 20.952 + data->attr.tlength = data->attr.minreq*2; 20.953 + data->attr.maxlength = data->attr.tlength; 20.954 + flags |= PA_STREAM_EARLY_REQUESTS; 20.955 + flags |= PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE; 20.956 + 20.957 + switch(device->FmtType) 20.958 + { 20.959 + case DevFmtByte: 20.960 + device->FmtType = DevFmtUByte; 20.961 + /* fall-through */ 20.962 + case DevFmtUByte: 20.963 + data->spec.format = PA_SAMPLE_U8; 20.964 + break; 20.965 + case DevFmtUShort: 20.966 + device->FmtType = DevFmtShort; 20.967 + /* fall-through */ 20.968 + case DevFmtShort: 20.969 + data->spec.format = PA_SAMPLE_S16NE; 20.970 + break; 20.971 + case DevFmtFloat: 20.972 + data->spec.format = PA_SAMPLE_FLOAT32NE; 20.973 + break; 20.974 + } 20.975 + data->spec.rate = device->Frequency; 20.976 + data->spec.channels = ChannelsFromDevFmt(device->FmtChans); 20.977 + 20.978 + if(pa_sample_spec_valid(&data->spec) == 0) 20.979 + { 20.980 + ERR("Invalid sample format\n"); 20.981 + pa_threaded_mainloop_unlock(data->loop); 20.982 + return ALC_FALSE; 20.983 + } 20.984 + 20.985 + if(!pa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX)) 20.986 + { 20.987 + ERR("Couldn't build map for channel count (%d)!\n", data->spec.channels); 20.988 + pa_threaded_mainloop_unlock(data->loop); 20.989 + return ALC_FALSE; 20.990 + } 20.991 + SetDefaultWFXChannelOrder(device); 20.992 + 20.993 + data->stream = connect_playback_stream(device, flags, &data->attr, &data->spec, &chanmap); 20.994 + if(!data->stream) 20.995 + { 20.996 + pa_threaded_mainloop_unlock(data->loop); 20.997 + return ALC_FALSE; 20.998 + } 20.999 + 20.1000 + pa_stream_set_state_callback(data->stream, stream_state_callback2, device); 20.1001 + 20.1002 + data->spec = *(pa_stream_get_sample_spec(data->stream)); 20.1003 + if(device->Frequency != data->spec.rate) 20.1004 + { 20.1005 + pa_operation *o; 20.1006 + 20.1007 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 20.1008 + ERR("Failed to set frequency %dhz, got %dhz instead\n", device->Frequency, data->spec.rate); 20.1009 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 20.1010 + 20.1011 + /* Server updated our playback rate, so modify the buffer attribs 20.1012 + * accordingly. */ 20.1013 + data->attr.minreq = (ALuint64)(data->attr.minreq/data->frame_size) * 20.1014 + data->spec.rate / device->Frequency * data->frame_size; 20.1015 + data->attr.tlength = data->attr.minreq * device->NumUpdates; 20.1016 + data->attr.maxlength = data->attr.tlength; 20.1017 + 20.1018 + o = pa_stream_set_buffer_attr(data->stream, &data->attr, 20.1019 + stream_success_callback, device); 20.1020 + while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) 20.1021 + pa_threaded_mainloop_wait(data->loop); 20.1022 + pa_operation_unref(o); 20.1023 + 20.1024 + device->Frequency = data->spec.rate; 20.1025 + } 20.1026 + 20.1027 + stream_buffer_attr_callback(data->stream, device); 20.1028 +#if PA_CHECK_VERSION(0,9,15) 20.1029 + if(pa_stream_set_buffer_attr_callback) 20.1030 + pa_stream_set_buffer_attr_callback(data->stream, stream_buffer_attr_callback, device); 20.1031 +#endif 20.1032 + pa_stream_set_moved_callback(data->stream, stream_device_callback, device); 20.1033 + pa_stream_set_write_callback(data->stream, stream_write_callback, device); 20.1034 + pa_stream_set_underflow_callback(data->stream, stream_signal_callback, device); 20.1035 + 20.1036 + data->thread = StartThread(PulseProc, device); 20.1037 + if(!data->thread) 20.1038 + { 20.1039 +#if PA_CHECK_VERSION(0,9,15) 20.1040 + if(pa_stream_set_buffer_attr_callback) 20.1041 + pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL); 20.1042 +#endif 20.1043 + pa_stream_set_moved_callback(data->stream, NULL, NULL); 20.1044 + pa_stream_set_write_callback(data->stream, NULL, NULL); 20.1045 + pa_stream_set_underflow_callback(data->stream, NULL, NULL); 20.1046 + pa_stream_disconnect(data->stream); 20.1047 + pa_stream_unref(data->stream); 20.1048 + data->stream = NULL; 20.1049 + 20.1050 + pa_threaded_mainloop_unlock(data->loop); 20.1051 + return ALC_FALSE; 20.1052 + } 20.1053 + 20.1054 + pa_threaded_mainloop_unlock(data->loop); 20.1055 + return ALC_TRUE; 20.1056 +} //}}} 20.1057 + 20.1058 +static void pulse_stop_playback(ALCdevice *device) //{{{ 20.1059 +{ 20.1060 + pulse_data *data = device->ExtraData; 20.1061 + 20.1062 + if(!data->stream) 20.1063 + return; 20.1064 + 20.1065 + data->killNow = AL_TRUE; 20.1066 + if(data->thread) 20.1067 + { 20.1068 + pa_threaded_mainloop_signal(data->loop, 0); 20.1069 + StopThread(data->thread); 20.1070 + data->thread = NULL; 20.1071 + } 20.1072 + data->killNow = AL_FALSE; 20.1073 + 20.1074 + pa_threaded_mainloop_lock(data->loop); 20.1075 + 20.1076 +#if PA_CHECK_VERSION(0,9,15) 20.1077 + if(pa_stream_set_buffer_attr_callback) 20.1078 + pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL); 20.1079 +#endif 20.1080 + pa_stream_set_moved_callback(data->stream, NULL, NULL); 20.1081 + pa_stream_set_write_callback(data->stream, NULL, NULL); 20.1082 + pa_stream_set_underflow_callback(data->stream, NULL, NULL); 20.1083 + pa_stream_disconnect(data->stream); 20.1084 + pa_stream_unref(data->stream); 20.1085 + data->stream = NULL; 20.1086 + 20.1087 + pa_threaded_mainloop_unlock(data->loop); 20.1088 +} //}}} 20.1089 + 20.1090 + 20.1091 +static ALCboolean pulse_open_capture(ALCdevice *device, const ALCchar *device_name) //{{{ 20.1092 +{ 20.1093 + char *pulse_name = NULL; 20.1094 + pulse_data *data; 20.1095 + pa_stream_flags_t flags = 0; 20.1096 + pa_stream_state_t state; 20.1097 + pa_channel_map chanmap; 20.1098 + 20.1099 + if(!allCaptureDevNameMap) 20.1100 + probe_devices(AL_TRUE); 20.1101 + 20.1102 + if(!device_name) 20.1103 + device_name = pulse_device; 20.1104 + else if(strcmp(device_name, pulse_device) != 0) 20.1105 + { 20.1106 + ALuint i; 20.1107 + 20.1108 + for(i = 0;i < numCaptureDevNames;i++) 20.1109 + { 20.1110 + if(strcmp(device_name, allCaptureDevNameMap[i].name) == 0) 20.1111 + { 20.1112 + pulse_name = allCaptureDevNameMap[i].device_name; 20.1113 + break; 20.1114 + } 20.1115 + } 20.1116 + if(i == numCaptureDevNames) 20.1117 + return ALC_FALSE; 20.1118 + } 20.1119 + 20.1120 + if(pulse_open(device, device_name) == ALC_FALSE) 20.1121 + return ALC_FALSE; 20.1122 + 20.1123 + data = device->ExtraData; 20.1124 + pa_threaded_mainloop_lock(data->loop); 20.1125 + 20.1126 + data->samples = device->UpdateSize * device->NumUpdates; 20.1127 + data->frame_size = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 20.1128 + if(data->samples < 100 * device->Frequency / 1000) 20.1129 + data->samples = 100 * device->Frequency / 1000; 20.1130 + 20.1131 + if(!(data->ring = CreateRingBuffer(data->frame_size, data->samples))) 20.1132 + { 20.1133 + pa_threaded_mainloop_unlock(data->loop); 20.1134 + goto fail; 20.1135 + } 20.1136 + 20.1137 + data->attr.minreq = -1; 20.1138 + data->attr.prebuf = -1; 20.1139 + data->attr.maxlength = data->samples * data->frame_size; 20.1140 + data->attr.tlength = -1; 20.1141 + data->attr.fragsize = minu(data->samples, 50*device->Frequency/1000) * 20.1142 + data->frame_size; 20.1143 + 20.1144 + data->spec.rate = device->Frequency; 20.1145 + data->spec.channels = ChannelsFromDevFmt(device->FmtChans); 20.1146 + 20.1147 + switch(device->FmtType) 20.1148 + { 20.1149 + case DevFmtUByte: 20.1150 + data->spec.format = PA_SAMPLE_U8; 20.1151 + break; 20.1152 + case DevFmtShort: 20.1153 + data->spec.format = PA_SAMPLE_S16NE; 20.1154 + break; 20.1155 + case DevFmtFloat: 20.1156 + data->spec.format = PA_SAMPLE_FLOAT32NE; 20.1157 + break; 20.1158 + case DevFmtByte: 20.1159 + case DevFmtUShort: 20.1160 + ERR("Capture format type %#x capture not supported on PulseAudio\n", device->FmtType); 20.1161 + pa_threaded_mainloop_unlock(data->loop); 20.1162 + goto fail; 20.1163 + } 20.1164 + 20.1165 + if(pa_sample_spec_valid(&data->spec) == 0) 20.1166 + { 20.1167 + ERR("Invalid sample format\n"); 20.1168 + pa_threaded_mainloop_unlock(data->loop); 20.1169 + goto fail; 20.1170 + } 20.1171 + 20.1172 + if(!pa_channel_map_init_auto(&chanmap, data->spec.channels, PA_CHANNEL_MAP_WAVEEX)) 20.1173 + { 20.1174 + ERR("Couldn't build map for channel count (%d)!\n", data->spec.channels); 20.1175 + pa_threaded_mainloop_unlock(data->loop); 20.1176 + goto fail; 20.1177 + } 20.1178 + 20.1179 + data->stream = pa_stream_new(data->context, "Capture Stream", &data->spec, &chanmap); 20.1180 + if(!data->stream) 20.1181 + { 20.1182 + ERR("pa_stream_new() failed: %s\n", 20.1183 + pa_strerror(pa_context_errno(data->context))); 20.1184 + 20.1185 + pa_threaded_mainloop_unlock(data->loop); 20.1186 + goto fail; 20.1187 + } 20.1188 + 20.1189 + pa_stream_set_state_callback(data->stream, stream_state_callback, data->loop); 20.1190 + 20.1191 + flags |= PA_STREAM_START_CORKED|PA_STREAM_ADJUST_LATENCY; 20.1192 + if(pa_stream_connect_record(data->stream, pulse_name, &data->attr, flags) < 0) 20.1193 + { 20.1194 + ERR("Stream did not connect: %s\n", 20.1195 + pa_strerror(pa_context_errno(data->context))); 20.1196 + 20.1197 + pa_stream_unref(data->stream); 20.1198 + data->stream = NULL; 20.1199 + 20.1200 + pa_threaded_mainloop_unlock(data->loop); 20.1201 + goto fail; 20.1202 + } 20.1203 + 20.1204 + while((state=pa_stream_get_state(data->stream)) != PA_STREAM_READY) 20.1205 + { 20.1206 + if(!PA_STREAM_IS_GOOD(state)) 20.1207 + { 20.1208 + ERR("Stream did not get ready: %s\n", 20.1209 + pa_strerror(pa_context_errno(data->context))); 20.1210 + 20.1211 + pa_stream_unref(data->stream); 20.1212 + data->stream = NULL; 20.1213 + 20.1214 + pa_threaded_mainloop_unlock(data->loop); 20.1215 + goto fail; 20.1216 + } 20.1217 + 20.1218 + pa_threaded_mainloop_wait(data->loop); 20.1219 + } 20.1220 + pa_stream_set_state_callback(data->stream, stream_state_callback2, device); 20.1221 + 20.1222 + pa_threaded_mainloop_unlock(data->loop); 20.1223 + return ALC_TRUE; 20.1224 + 20.1225 +fail: 20.1226 + pulse_close(device); 20.1227 + return ALC_FALSE; 20.1228 +} //}}} 20.1229 + 20.1230 +static void pulse_close_capture(ALCdevice *device) //{{{ 20.1231 +{ 20.1232 + pulse_close(device); 20.1233 +} //}}} 20.1234 + 20.1235 +static void pulse_start_capture(ALCdevice *device) //{{{ 20.1236 +{ 20.1237 + pulse_data *data = device->ExtraData; 20.1238 + pa_operation *o; 20.1239 + 20.1240 + pa_threaded_mainloop_lock(data->loop); 20.1241 + o = pa_stream_cork(data->stream, 0, stream_success_callback, device); 20.1242 + while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) 20.1243 + pa_threaded_mainloop_wait(data->loop); 20.1244 + pa_operation_unref(o); 20.1245 + pa_threaded_mainloop_unlock(data->loop); 20.1246 +} //}}} 20.1247 + 20.1248 +static void pulse_stop_capture(ALCdevice *device) //{{{ 20.1249 +{ 20.1250 + pulse_data *data = device->ExtraData; 20.1251 + pa_operation *o; 20.1252 + 20.1253 + pa_threaded_mainloop_lock(data->loop); 20.1254 + o = pa_stream_cork(data->stream, 1, stream_success_callback, device); 20.1255 + while(pa_operation_get_state(o) == PA_OPERATION_RUNNING) 20.1256 + pa_threaded_mainloop_wait(data->loop); 20.1257 + pa_operation_unref(o); 20.1258 + pa_threaded_mainloop_unlock(data->loop); 20.1259 +} //}}} 20.1260 + 20.1261 +static ALCuint pulse_available_samples(ALCdevice *device) //{{{ 20.1262 +{ 20.1263 + pulse_data *data = device->ExtraData; 20.1264 + size_t samples; 20.1265 + 20.1266 + pa_threaded_mainloop_lock(data->loop); 20.1267 + /* Capture is done in fragment-sized chunks, so we loop until we get all 20.1268 + * that's available */ 20.1269 + samples = (device->Connected ? pa_stream_readable_size(data->stream) : 0); 20.1270 + while(samples > 0) 20.1271 + { 20.1272 + const void *buf; 20.1273 + size_t length; 20.1274 + 20.1275 + if(pa_stream_peek(data->stream, &buf, &length) < 0) 20.1276 + { 20.1277 + ERR("pa_stream_peek() failed: %s\n", 20.1278 + pa_strerror(pa_context_errno(data->context))); 20.1279 + break; 20.1280 + } 20.1281 + 20.1282 + WriteRingBuffer(data->ring, buf, length/data->frame_size); 20.1283 + samples -= length; 20.1284 + 20.1285 + pa_stream_drop(data->stream); 20.1286 + } 20.1287 + pa_threaded_mainloop_unlock(data->loop); 20.1288 + 20.1289 + return RingBufferSize(data->ring); 20.1290 +} //}}} 20.1291 + 20.1292 +static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) //{{{ 20.1293 +{ 20.1294 + pulse_data *data = device->ExtraData; 20.1295 + 20.1296 + if(pulse_available_samples(device) >= samples) 20.1297 + ReadRingBuffer(data->ring, buffer, samples); 20.1298 + else 20.1299 + alcSetError(device, ALC_INVALID_VALUE); 20.1300 +} //}}} 20.1301 + 20.1302 + 20.1303 +static const BackendFuncs pulse_funcs = { //{{{ 20.1304 + pulse_open_playback, 20.1305 + pulse_close_playback, 20.1306 + pulse_reset_playback, 20.1307 + pulse_stop_playback, 20.1308 + pulse_open_capture, 20.1309 + pulse_close_capture, 20.1310 + pulse_start_capture, 20.1311 + pulse_stop_capture, 20.1312 + pulse_capture_samples, 20.1313 + pulse_available_samples 20.1314 +}; //}}} 20.1315 + 20.1316 +ALCboolean alc_pulse_init(BackendFuncs *func_list) //{{{ 20.1317 +{ 20.1318 + if(!pulse_load()) 20.1319 + return ALC_FALSE; 20.1320 + 20.1321 + *func_list = pulse_funcs; 20.1322 + 20.1323 + pulse_ctx_flags = 0; 20.1324 + if(!GetConfigValueBool("pulse", "spawn-server", 0)) 20.1325 + pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN; 20.1326 + 20.1327 + return ALC_TRUE; 20.1328 +} //}}} 20.1329 + 20.1330 +void alc_pulse_deinit(void) //{{{ 20.1331 +{ 20.1332 + ALuint i; 20.1333 + 20.1334 + for(i = 0;i < numDevNames;++i) 20.1335 + { 20.1336 + free(allDevNameMap[i].name); 20.1337 + free(allDevNameMap[i].device_name); 20.1338 + } 20.1339 + free(allDevNameMap); 20.1340 + allDevNameMap = NULL; 20.1341 + numDevNames = 0; 20.1342 + 20.1343 + for(i = 0;i < numCaptureDevNames;++i) 20.1344 + { 20.1345 + free(allCaptureDevNameMap[i].name); 20.1346 + free(allCaptureDevNameMap[i].device_name); 20.1347 + } 20.1348 + free(allCaptureDevNameMap); 20.1349 + allCaptureDevNameMap = NULL; 20.1350 + numCaptureDevNames = 0; 20.1351 + 20.1352 +#ifdef HAVE_DYNLOAD 20.1353 + if(pa_handle) 20.1354 + CloseLib(pa_handle); 20.1355 + pa_handle = NULL; 20.1356 +#endif 20.1357 +} //}}} 20.1358 + 20.1359 +void alc_pulse_probe(enum DevProbe type) //{{{ 20.1360 +{ 20.1361 + pa_threaded_mainloop *loop; 20.1362 + ALuint i; 20.1363 + 20.1364 + switch(type) 20.1365 + { 20.1366 + case DEVICE_PROBE: 20.1367 + if((loop=pa_threaded_mainloop_new()) && 20.1368 + pa_threaded_mainloop_start(loop) >= 0) 20.1369 + { 20.1370 + pa_context *context; 20.1371 + 20.1372 + pa_threaded_mainloop_lock(loop); 20.1373 + context = connect_context(loop, AL_FALSE); 20.1374 + if(context) 20.1375 + { 20.1376 + AppendDeviceList(pulse_device); 20.1377 + 20.1378 + pa_context_disconnect(context); 20.1379 + pa_context_unref(context); 20.1380 + } 20.1381 + pa_threaded_mainloop_unlock(loop); 20.1382 + pa_threaded_mainloop_stop(loop); 20.1383 + } 20.1384 + if(loop) 20.1385 + pa_threaded_mainloop_free(loop); 20.1386 + break; 20.1387 + 20.1388 + case ALL_DEVICE_PROBE: 20.1389 + for(i = 0;i < numDevNames;++i) 20.1390 + { 20.1391 + free(allDevNameMap[i].name); 20.1392 + free(allDevNameMap[i].device_name); 20.1393 + } 20.1394 + free(allDevNameMap); 20.1395 + allDevNameMap = NULL; 20.1396 + numDevNames = 0; 20.1397 + 20.1398 + probe_devices(AL_FALSE); 20.1399 + 20.1400 + for(i = 0;i < numDevNames;i++) 20.1401 + AppendAllDeviceList(allDevNameMap[i].name); 20.1402 + break; 20.1403 + 20.1404 + case CAPTURE_DEVICE_PROBE: 20.1405 + for(i = 0;i < numCaptureDevNames;++i) 20.1406 + { 20.1407 + free(allCaptureDevNameMap[i].name); 20.1408 + free(allCaptureDevNameMap[i].device_name); 20.1409 + } 20.1410 + free(allCaptureDevNameMap); 20.1411 + allCaptureDevNameMap = NULL; 20.1412 + numCaptureDevNames = 0; 20.1413 + 20.1414 + probe_devices(AL_TRUE); 20.1415 + 20.1416 + for(i = 0;i < numCaptureDevNames;i++) 20.1417 + AppendCaptureDeviceList(allCaptureDevNameMap[i].name); 20.1418 + break; 20.1419 + } 20.1420 +} //}}} 20.1421 +//}}}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 21.2 +++ b/Alc/backends/send.c Tue Oct 25 13:02:31 2011 -0700 21.3 @@ -0,0 +1,472 @@ 21.4 +#include "config.h" 21.5 +#include <stdlib.h> 21.6 +#include "alMain.h" 21.7 +#include "AL/al.h" 21.8 +#include "AL/alc.h" 21.9 +#include "alSource.h" 21.10 +#include <jni.h> 21.11 + 21.12 +//////////////////// Summary 21.13 + 21.14 +struct send_data; 21.15 +struct context_data; 21.16 + 21.17 +static void addContext(ALCdevice *, ALCcontext *); 21.18 +static void syncContexts(ALCcontext *master, ALCcontext *slave); 21.19 +static void syncSources(ALsource *master, ALsource *slave, 21.20 + ALCcontext *masterCtx, ALCcontext *slaveCtx); 21.21 + 21.22 +static void syncSourcei(ALuint master, ALuint slave, 21.23 + ALCcontext *masterCtx, ALCcontext *ctx2, ALenum param); 21.24 +static void syncSourcef(ALuint master, ALuint slave, 21.25 + ALCcontext *masterCtx, ALCcontext *ctx2, ALenum param); 21.26 +static void syncSource3f(ALuint master, ALuint slave, 21.27 + ALCcontext *masterCtx, ALCcontext *ctx2, ALenum param); 21.28 + 21.29 +static void swapInContext(ALCdevice *, struct context_data *); 21.30 +static void saveContext(ALCdevice *, struct context_data *); 21.31 +static void limitContext(ALCdevice *, ALCcontext *); 21.32 +static void unLimitContext(ALCdevice *); 21.33 + 21.34 +static void init(ALCdevice *); 21.35 +static void renderData(ALCdevice *, int samples); 21.36 + 21.37 +#define UNUSED(x) (void)(x) 21.38 + 21.39 +//////////////////// State 21.40 + 21.41 +typedef struct context_data { 21.42 + ALfloat ClickRemoval[MAXCHANNELS]; 21.43 + ALfloat PendingClicks[MAXCHANNELS]; 21.44 + ALvoid *renderBuffer; 21.45 + ALCcontext *ctx; 21.46 +} context_data; 21.47 + 21.48 +typedef struct send_data { 21.49 + ALuint size; 21.50 + context_data **contexts; 21.51 + ALuint numContexts; 21.52 + ALuint maxContexts; 21.53 +} send_data; 21.54 + 21.55 + 21.56 + 21.57 +//////////////////// Context Creation / Synchronization 21.58 + 21.59 +#define _MAKE_SYNC(NAME, INIT_EXPR, GET_EXPR, SET_EXPR) \ 21.60 + void NAME (ALuint sourceID1, ALuint sourceID2, \ 21.61 + ALCcontext *ctx1, ALCcontext *ctx2, \ 21.62 + ALenum param){ \ 21.63 + INIT_EXPR; \ 21.64 + ALCcontext *current = alcGetCurrentContext(); \ 21.65 + alcMakeContextCurrent(ctx1); \ 21.66 + GET_EXPR; \ 21.67 + alcMakeContextCurrent(ctx2); \ 21.68 + SET_EXPR; \ 21.69 + alcMakeContextCurrent(current); \ 21.70 + } 21.71 + 21.72 +#define MAKE_SYNC(NAME, TYPE, GET, SET) \ 21.73 + _MAKE_SYNC(NAME, \ 21.74 + TYPE value, \ 21.75 + GET(sourceID1, param, &value), \ 21.76 + SET(sourceID2, param, value)) 21.77 + 21.78 +#define MAKE_SYNC3(NAME, TYPE, GET, SET) \ 21.79 + _MAKE_SYNC(NAME, \ 21.80 + TYPE value1; TYPE value2; TYPE value3;, \ 21.81 + GET(sourceID1, param, &value1, &value2, &value3), \ 21.82 + SET(sourceID2, param, value1, value2, value3)) 21.83 + 21.84 +MAKE_SYNC( syncSourcei, ALint, alGetSourcei, alSourcei); 21.85 +MAKE_SYNC( syncSourcef, ALfloat, alGetSourcef, alSourcef); 21.86 +MAKE_SYNC3(syncSource3i, ALint, alGetSource3i, alSource3i); 21.87 +MAKE_SYNC3(syncSource3f, ALfloat, alGetSource3f, alSource3f); 21.88 + 21.89 +void syncSources(ALsource *masterSource, ALsource *slaveSource, 21.90 + ALCcontext *masterCtx, ALCcontext *slaveCtx){ 21.91 + ALuint master = masterSource->source; 21.92 + ALuint slave = slaveSource->source; 21.93 + ALCcontext *current = alcGetCurrentContext(); 21.94 + 21.95 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_PITCH); 21.96 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_GAIN); 21.97 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_MAX_DISTANCE); 21.98 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_ROLLOFF_FACTOR); 21.99 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_REFERENCE_DISTANCE); 21.100 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_MIN_GAIN); 21.101 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_MAX_GAIN); 21.102 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_CONE_OUTER_GAIN); 21.103 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_CONE_INNER_ANGLE); 21.104 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_CONE_OUTER_ANGLE); 21.105 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_SEC_OFFSET); 21.106 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_SAMPLE_OFFSET); 21.107 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_BYTE_OFFSET); 21.108 + 21.109 + syncSource3f(master,slave,masterCtx,slaveCtx,AL_POSITION); 21.110 + syncSource3f(master,slave,masterCtx,slaveCtx,AL_VELOCITY); 21.111 + syncSource3f(master,slave,masterCtx,slaveCtx,AL_DIRECTION); 21.112 + 21.113 + syncSourcei(master,slave,masterCtx,slaveCtx,AL_SOURCE_RELATIVE); 21.114 + syncSourcei(master,slave,masterCtx,slaveCtx,AL_LOOPING); 21.115 + 21.116 + alcMakeContextCurrent(masterCtx); 21.117 + ALint source_type; 21.118 + alGetSourcei(master, AL_SOURCE_TYPE, &source_type); 21.119 + 21.120 + // Only static sources are currently synchronized! 21.121 + if (AL_STATIC == source_type){ 21.122 + ALint master_buffer; 21.123 + ALint slave_buffer; 21.124 + alGetSourcei(master, AL_BUFFER, &master_buffer); 21.125 + alcMakeContextCurrent(slaveCtx); 21.126 + alGetSourcei(slave, AL_BUFFER, &slave_buffer); 21.127 + if (master_buffer != slave_buffer){ 21.128 + alSourcei(slave, AL_BUFFER, master_buffer); 21.129 + } 21.130 + } 21.131 + 21.132 + // Synchronize the state of the two sources. 21.133 + alcMakeContextCurrent(masterCtx); 21.134 + ALint masterState; 21.135 + ALint slaveState; 21.136 + 21.137 + alGetSourcei(master, AL_SOURCE_STATE, &masterState); 21.138 + alcMakeContextCurrent(slaveCtx); 21.139 + alGetSourcei(slave, AL_SOURCE_STATE, &slaveState); 21.140 + 21.141 + if (masterState != slaveState){ 21.142 + switch (masterState){ 21.143 + case AL_INITIAL : alSourceRewind(slave); break; 21.144 + case AL_PLAYING : alSourcePlay(slave); break; 21.145 + case AL_PAUSED : alSourcePause(slave); break; 21.146 + case AL_STOPPED : alSourceStop(slave); break; 21.147 + } 21.148 + } 21.149 + // Restore whatever context was previously active. 21.150 + alcMakeContextCurrent(current); 21.151 +} 21.152 + 21.153 + 21.154 +void syncContexts(ALCcontext *master, ALCcontext *slave){ 21.155 + /* If there aren't sufficient sources in slave to mirror 21.156 + the sources in master, create them. */ 21.157 + ALCcontext *current = alcGetCurrentContext(); 21.158 + 21.159 + UIntMap *masterSourceMap = &(master->SourceMap); 21.160 + UIntMap *slaveSourceMap = &(slave->SourceMap); 21.161 + ALuint numMasterSources = masterSourceMap->size; 21.162 + ALuint numSlaveSources = slaveSourceMap->size; 21.163 + 21.164 + alcMakeContextCurrent(slave); 21.165 + if (numSlaveSources < numMasterSources){ 21.166 + ALuint numMissingSources = numMasterSources - numSlaveSources; 21.167 + ALuint newSources[numMissingSources]; 21.168 + alGenSources(numMissingSources, newSources); 21.169 + } 21.170 + 21.171 + /* Now, slave is gauranteed to have at least as many sources 21.172 + as master. Sync each source from master to the corresponding 21.173 + source in slave. */ 21.174 + int i; 21.175 + for(i = 0; i < masterSourceMap->size; i++){ 21.176 + syncSources((ALsource*)masterSourceMap->array[i].value, 21.177 + (ALsource*)slaveSourceMap->array[i].value, 21.178 + master, slave); 21.179 + } 21.180 + alcMakeContextCurrent(current); 21.181 +} 21.182 + 21.183 +static void addContext(ALCdevice *Device, ALCcontext *context){ 21.184 + send_data *data = (send_data*)Device->ExtraData; 21.185 + // expand array if necessary 21.186 + if (data->numContexts >= data->maxContexts){ 21.187 + ALuint newMaxContexts = data->maxContexts*2 + 1; 21.188 + data->contexts = realloc(data->contexts, newMaxContexts*sizeof(context_data)); 21.189 + data->maxContexts = newMaxContexts; 21.190 + } 21.191 + // create context_data and add it to the main array 21.192 + context_data *ctxData; 21.193 + ctxData = (context_data*)calloc(1, sizeof(*ctxData)); 21.194 + ctxData->renderBuffer = malloc(data->size); 21.195 + ctxData->ctx = context; 21.196 + 21.197 + data->contexts[data->numContexts] = ctxData; 21.198 + data->numContexts++; 21.199 +} 21.200 + 21.201 + 21.202 +//////////////////// Context Switching 21.203 + 21.204 +/* A device brings along with it two pieces of state 21.205 + * which have to be swapped in and out with each context. 21.206 + */ 21.207 +static void swapInContext(ALCdevice *Device, context_data *ctxData){ 21.208 + memcpy(Device->ClickRemoval, ctxData->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); 21.209 + memcpy(Device->PendingClicks, ctxData->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); 21.210 +} 21.211 + 21.212 +static void saveContext(ALCdevice *Device, context_data *ctxData){ 21.213 + memcpy(ctxData->ClickRemoval, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); 21.214 + memcpy(ctxData->PendingClicks, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); 21.215 +} 21.216 + 21.217 +static ALCcontext **currentContext; 21.218 +static ALuint currentNumContext; 21.219 + 21.220 +/* By default, all contexts are rendered at once for each call to aluMixData. 21.221 + * This function uses the internals of the ALCdecice struct to temporarly 21.222 + * cause aluMixData to only render the chosen context. 21.223 + */ 21.224 +static void limitContext(ALCdevice *Device, ALCcontext *ctx){ 21.225 + currentContext = Device->Contexts; 21.226 + currentNumContext = Device->NumContexts; 21.227 + Device->Contexts = &ctx; 21.228 + Device->NumContexts = 1; 21.229 +} 21.230 + 21.231 +static void unLimitContext(ALCdevice *Device){ 21.232 + Device->Contexts = currentContext; 21.233 + Device->NumContexts = currentNumContext; 21.234 +} 21.235 + 21.236 + 21.237 +//////////////////// Main Device Loop 21.238 + 21.239 +/* Establish the LWJGL context as the main context, which will 21.240 + * be synchronized to all the slave contexts 21.241 + */ 21.242 +static void init(ALCdevice *Device){ 21.243 + ALCcontext *masterContext = alcGetCurrentContext(); 21.244 + addContext(Device, masterContext); 21.245 +} 21.246 + 21.247 + 21.248 +static void renderData(ALCdevice *Device, int samples){ 21.249 + if(!Device->Connected){return;} 21.250 + send_data *data = (send_data*)Device->ExtraData; 21.251 + ALCcontext *current = alcGetCurrentContext(); 21.252 + 21.253 + ALuint i; 21.254 + for (i = 1; i < data->numContexts; i++){ 21.255 + syncContexts(data->contexts[0]->ctx , data->contexts[i]->ctx); 21.256 + } 21.257 + 21.258 + if ((uint) samples > Device->UpdateSize){ 21.259 + printf("exceeding internal buffer size; dropping samples\n"); 21.260 + printf("requested %d; available %d\n", samples, Device->UpdateSize); 21.261 + samples = (int) Device->UpdateSize; 21.262 + } 21.263 + 21.264 + for (i = 0; i < data->numContexts; i++){ 21.265 + context_data *ctxData = data->contexts[i]; 21.266 + ALCcontext *ctx = ctxData->ctx; 21.267 + alcMakeContextCurrent(ctx); 21.268 + limitContext(Device, ctx); 21.269 + swapInContext(Device, ctxData); 21.270 + aluMixData(Device, ctxData->renderBuffer, samples); 21.271 + saveContext(Device, ctxData); 21.272 + unLimitContext(Device); 21.273 + } 21.274 + alcMakeContextCurrent(current); 21.275 +} 21.276 + 21.277 + 21.278 +//////////////////// JNI Methods 21.279 + 21.280 +#include "com_aurellem_capture_AudioSend.h" 21.281 + 21.282 +/* 21.283 + * Class: com_aurellem_capture_AudioSend 21.284 + * Method: nstep 21.285 + * Signature: (JI)V 21.286 + */ 21.287 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_nstep 21.288 +(JNIEnv *env, jclass clazz, jlong device, jint samples){ 21.289 + UNUSED(env);UNUSED(clazz);UNUSED(device); 21.290 + renderData((ALCdevice*)((intptr_t)device), samples); 21.291 +} 21.292 + 21.293 +/* 21.294 + * Class: com_aurellem_capture_AudioSend 21.295 + * Method: ngetSamples 21.296 + * Signature: (JLjava/nio/ByteBuffer;III)V 21.297 + */ 21.298 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_ngetSamples 21.299 +(JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position, 21.300 + jint samples, jint n){ 21.301 + UNUSED(clazz); 21.302 + 21.303 + ALvoid *buffer_address = 21.304 + ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); 21.305 + ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); 21.306 + send_data *data = (send_data*)recorder->ExtraData; 21.307 + if ((ALuint)n > data->numContexts){return;} 21.308 + if ((uint) samples > data->size){ 21.309 + samples = (int) data->size; 21.310 + } 21.311 + memcpy(buffer_address, data->contexts[n]->renderBuffer, samples*sizeof(ALfloat)); 21.312 +} 21.313 + 21.314 +/* 21.315 + * Class: com_aurellem_capture_AudioSend 21.316 + * Method: naddListener 21.317 + * Signature: (J)V 21.318 + */ 21.319 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_naddListener 21.320 +(JNIEnv *env, jclass clazz, jlong device){ 21.321 + UNUSED(env); UNUSED(clazz); 21.322 + printf("creating new context via naddListener\n"); 21.323 + ALCdevice *Device = (ALCdevice*) ((intptr_t)device); 21.324 + ALCcontext *new = alcCreateContext(Device, NULL); 21.325 + addContext(Device, new); 21.326 +} 21.327 + 21.328 +/* 21.329 + * Class: com_aurellem_capture_AudioSend 21.330 + * Method: nsetNthListener3f 21.331 + * Signature: (IFFFJI)V 21.332 + */ 21.333 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_nsetNthListener3f 21.334 + (JNIEnv *env, jclass clazz, jint param, 21.335 + jfloat v1, jfloat v2, jfloat v3, jlong device, jint contextNum){ 21.336 + UNUSED(env);UNUSED(clazz); 21.337 + 21.338 + ALCdevice *Device = (ALCdevice*) ((intptr_t)device); 21.339 + send_data *data = (send_data*)Device->ExtraData; 21.340 + 21.341 + ALCcontext *current = alcGetCurrentContext(); 21.342 + if ((ALuint)contextNum > data->numContexts){return;} 21.343 + alcMakeContextCurrent(data->contexts[contextNum]->ctx); 21.344 + alListener3f(param, v1, v2, v3); 21.345 + alcMakeContextCurrent(current); 21.346 +} 21.347 + 21.348 +/* 21.349 + * Class: com_aurellem_capture_AudioSend 21.350 + * Method: nsetNthListenerf 21.351 + * Signature: (IFJI)V 21.352 + */ 21.353 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_nsetNthListenerf 21.354 +(JNIEnv *env, jclass clazz, jint param, jfloat v1, jlong device, 21.355 + jint contextNum){ 21.356 + 21.357 + UNUSED(env);UNUSED(clazz); 21.358 + 21.359 + ALCdevice *Device = (ALCdevice*) ((intptr_t)device); 21.360 + send_data *data = (send_data*)Device->ExtraData; 21.361 + 21.362 + ALCcontext *current = alcGetCurrentContext(); 21.363 + if ((ALuint)contextNum > data->numContexts){return;} 21.364 + alcMakeContextCurrent(data->contexts[contextNum]->ctx); 21.365 + alListenerf(param, v1); 21.366 + alcMakeContextCurrent(current); 21.367 +} 21.368 + 21.369 +/* 21.370 + * Class: com_aurellem_capture_AudioSend 21.371 + * Method: ninitDevice 21.372 + * Signature: (J)V 21.373 + */ 21.374 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_ninitDevice 21.375 +(JNIEnv *env, jclass clazz, jlong device){ 21.376 + UNUSED(env);UNUSED(clazz); 21.377 + 21.378 + ALCdevice *Device = (ALCdevice*) ((intptr_t)device); 21.379 + init(Device); 21.380 + 21.381 +} 21.382 + 21.383 + 21.384 +//////////////////// Device Initilization / Management 21.385 + 21.386 +static const ALCchar sendDevice[] = "Multiple Audio Send"; 21.387 + 21.388 +static ALCboolean send_open_playback(ALCdevice *device, 21.389 + const ALCchar *deviceName) 21.390 +{ 21.391 + send_data *data; 21.392 + // stop any buffering for stdout, so that I can 21.393 + // see the printf statements in my terminal immediatley 21.394 + setbuf(stdout, NULL); 21.395 + 21.396 + if(!deviceName) 21.397 + deviceName = sendDevice; 21.398 + else if(strcmp(deviceName, sendDevice) != 0) 21.399 + return ALC_FALSE; 21.400 + data = (send_data*)calloc(1, sizeof(*data)); 21.401 + device->szDeviceName = strdup(deviceName); 21.402 + device->ExtraData = data; 21.403 + return ALC_TRUE; 21.404 +} 21.405 + 21.406 +static void send_close_playback(ALCdevice *device) 21.407 +{ 21.408 + send_data *data = (send_data*)device->ExtraData; 21.409 + alcMakeContextCurrent(NULL); 21.410 + ALuint i; 21.411 + // Destroy all slave contexts. LWJGL will take care of 21.412 + // its own context. 21.413 + for (i = 1; i < data->numContexts; i++){ 21.414 + context_data *ctxData = data->contexts[i]; 21.415 + alcDestroyContext(ctxData->ctx); 21.416 + free(ctxData->renderBuffer); 21.417 + free(ctxData); 21.418 + } 21.419 + free(data); 21.420 + device->ExtraData = NULL; 21.421 +} 21.422 + 21.423 +static ALCboolean send_reset_playback(ALCdevice *device) 21.424 +{ 21.425 + send_data *data = (send_data*)device->ExtraData; 21.426 + ALuint channels=0, bits=0; 21.427 + device->FmtType = DevFmtShort; 21.428 + bits = BytesFromDevFmt(device->FmtType) * 8; 21.429 + channels = ChannelsFromDevFmt(device->FmtChans); 21.430 + data->size = device->UpdateSize * channels * bits / 8; 21.431 + 21.432 + return ALC_TRUE; 21.433 +} 21.434 + 21.435 +static void send_stop_playback(ALCdevice *Device){ 21.436 + UNUSED(Device); 21.437 +} 21.438 + 21.439 +static const BackendFuncs send_funcs = { 21.440 + send_open_playback, 21.441 + send_close_playback, 21.442 + send_reset_playback, 21.443 + send_stop_playback, 21.444 + NULL, 21.445 + NULL, /* These would be filled with functions to */ 21.446 + NULL, /* handle capturing audio if we we into that */ 21.447 + NULL, /* sort of thing... */ 21.448 + NULL, 21.449 + NULL 21.450 +}; 21.451 + 21.452 +ALCboolean alc_send_init(BackendFuncs *func_list){ 21.453 + *func_list = send_funcs; 21.454 + return ALC_TRUE; 21.455 +} 21.456 + 21.457 +void alc_send_deinit(void){} 21.458 + 21.459 +void alc_send_probe(enum DevProbe type) 21.460 +{ 21.461 + switch(type) 21.462 + { 21.463 + case DEVICE_PROBE: 21.464 + AppendDeviceList(sendDevice); 21.465 + break; 21.466 + case ALL_DEVICE_PROBE: 21.467 + AppendAllDeviceList(sendDevice); 21.468 + break; 21.469 + case CAPTURE_DEVICE_PROBE: 21.470 + break; 21.471 + } 21.472 +} 21.473 + 21.474 + 21.475 +
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 22.2 +++ b/Alc/backends/sndio.c Tue Oct 25 13:02:31 2011 -0700 22.3 @@ -0,0 +1,381 @@ 22.4 +/** 22.5 + * OpenAL cross platform audio library 22.6 + * Copyright (C) 1999-2007 by authors. 22.7 + * This library is free software; you can redistribute it and/or 22.8 + * modify it under the terms of the GNU Library General Public 22.9 + * License as published by the Free Software Foundation; either 22.10 + * version 2 of the License, or (at your option) any later version. 22.11 + * 22.12 + * This library is distributed in the hope that it will be useful, 22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22.15 + * Library General Public License for more details. 22.16 + * 22.17 + * You should have received a copy of the GNU Library General Public 22.18 + * License along with this library; if not, write to the 22.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 22.20 + * Boston, MA 02111-1307, USA. 22.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 22.22 + */ 22.23 + 22.24 +#include "config.h" 22.25 + 22.26 +#include <stdio.h> 22.27 +#include <stdlib.h> 22.28 +#include <string.h> 22.29 +#include "alMain.h" 22.30 +#include "AL/al.h" 22.31 +#include "AL/alc.h" 22.32 + 22.33 +#include <sndio.h> 22.34 + 22.35 + 22.36 +static const ALCchar sndio_device[] = "SndIO Default"; 22.37 + 22.38 + 22.39 +static void *sndio_handle; 22.40 +#ifdef HAVE_DYNLOAD 22.41 +#define MAKE_FUNC(x) static typeof(x) * p##x 22.42 +MAKE_FUNC(sio_initpar); 22.43 +MAKE_FUNC(sio_open); 22.44 +MAKE_FUNC(sio_close); 22.45 +MAKE_FUNC(sio_setpar); 22.46 +MAKE_FUNC(sio_getpar); 22.47 +MAKE_FUNC(sio_getcap); 22.48 +MAKE_FUNC(sio_onmove); 22.49 +MAKE_FUNC(sio_write); 22.50 +MAKE_FUNC(sio_read); 22.51 +MAKE_FUNC(sio_start); 22.52 +MAKE_FUNC(sio_stop); 22.53 +MAKE_FUNC(sio_nfds); 22.54 +MAKE_FUNC(sio_pollfd); 22.55 +MAKE_FUNC(sio_revents); 22.56 +MAKE_FUNC(sio_eof); 22.57 +MAKE_FUNC(sio_setvol); 22.58 +MAKE_FUNC(sio_onvol); 22.59 + 22.60 +#define sio_initpar psio_initpar 22.61 +#define sio_open psio_open 22.62 +#define sio_close psio_close 22.63 +#define sio_setpar psio_setpar 22.64 +#define sio_getpar psio_getpar 22.65 +#define sio_getcap psio_getcap 22.66 +#define sio_onmove psio_onmove 22.67 +#define sio_write psio_write 22.68 +#define sio_read psio_read 22.69 +#define sio_start psio_start 22.70 +#define sio_stop psio_stop 22.71 +#define sio_nfds psio_nfds 22.72 +#define sio_pollfd psio_pollfd 22.73 +#define sio_revents psio_revents 22.74 +#define sio_eof psio_eof 22.75 +#define sio_setvol psio_setvol 22.76 +#define sio_onvol psio_onvol 22.77 +#endif 22.78 + 22.79 + 22.80 +static ALCboolean sndio_load(void) 22.81 +{ 22.82 + if(!sndio_handle) 22.83 + { 22.84 +#ifdef HAVE_DYNLOAD 22.85 + sndio_handle = LoadLib("libsndio.so"); 22.86 + if(!sndio_handle) 22.87 + return ALC_FALSE; 22.88 + 22.89 +#define LOAD_FUNC(f) do { \ 22.90 + p##f = GetSymbol(sndio_handle, #f); \ 22.91 + if(p##f == NULL) { \ 22.92 + CloseLib(sndio_handle); \ 22.93 + sndio_handle = NULL; \ 22.94 + return ALC_FALSE; \ 22.95 + } \ 22.96 +} while(0) 22.97 + LOAD_FUNC(sio_initpar); 22.98 + LOAD_FUNC(sio_open); 22.99 + LOAD_FUNC(sio_close); 22.100 + LOAD_FUNC(sio_setpar); 22.101 + LOAD_FUNC(sio_getpar); 22.102 + LOAD_FUNC(sio_getcap); 22.103 + LOAD_FUNC(sio_onmove); 22.104 + LOAD_FUNC(sio_write); 22.105 + LOAD_FUNC(sio_read); 22.106 + LOAD_FUNC(sio_start); 22.107 + LOAD_FUNC(sio_stop); 22.108 + LOAD_FUNC(sio_nfds); 22.109 + LOAD_FUNC(sio_pollfd); 22.110 + LOAD_FUNC(sio_revents); 22.111 + LOAD_FUNC(sio_eof); 22.112 + LOAD_FUNC(sio_setvol); 22.113 + LOAD_FUNC(sio_onvol); 22.114 +#undef LOAD_FUNC 22.115 +#else 22.116 + sndio_handle = (void*)0xDEADBEEF; 22.117 +#endif 22.118 + } 22.119 + return ALC_TRUE; 22.120 +} 22.121 + 22.122 + 22.123 +typedef struct { 22.124 + struct sio_hdl *sndHandle; 22.125 + 22.126 + ALvoid *mix_data; 22.127 + ALsizei data_size; 22.128 + 22.129 + volatile int killNow; 22.130 + ALvoid *thread; 22.131 +} sndio_data; 22.132 + 22.133 + 22.134 +static ALuint sndio_proc(ALvoid *ptr) 22.135 +{ 22.136 + ALCdevice *device = ptr; 22.137 + sndio_data *data = device->ExtraData; 22.138 + ALsizei frameSize; 22.139 + size_t wrote; 22.140 + 22.141 + SetRTPriority(); 22.142 + 22.143 + frameSize = FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 22.144 + 22.145 + while(!data->killNow && device->Connected) 22.146 + { 22.147 + ALsizei len = data->data_size; 22.148 + ALubyte *WritePtr = data->mix_data; 22.149 + 22.150 + aluMixData(device, WritePtr, len/frameSize); 22.151 + while(len > 0 && !data->killNow) 22.152 + { 22.153 + wrote = sio_write(data->sndHandle, WritePtr, len); 22.154 + if(wrote == 0) 22.155 + { 22.156 + ERR("sio_write failed\n"); 22.157 + aluHandleDisconnect(device); 22.158 + break; 22.159 + } 22.160 + 22.161 + len -= wrote; 22.162 + WritePtr += wrote; 22.163 + } 22.164 + } 22.165 + 22.166 + return 0; 22.167 +} 22.168 + 22.169 + 22.170 + 22.171 +static ALCboolean sndio_open_playback(ALCdevice *device, const ALCchar *deviceName) 22.172 +{ 22.173 + sndio_data *data; 22.174 + 22.175 + if(!deviceName) 22.176 + deviceName = sndio_device; 22.177 + else if(strcmp(deviceName, sndio_device) != 0) 22.178 + return ALC_FALSE; 22.179 + 22.180 + data = calloc(1, sizeof(*data)); 22.181 + data->killNow = 0; 22.182 + 22.183 + data->sndHandle = sio_open(NULL, SIO_PLAY, 0); 22.184 + if(data->sndHandle == NULL) 22.185 + { 22.186 + free(data); 22.187 + ERR("Could not open device\n"); 22.188 + return ALC_FALSE; 22.189 + } 22.190 + 22.191 + device->szDeviceName = strdup(deviceName); 22.192 + device->ExtraData = data; 22.193 + 22.194 + return ALC_TRUE; 22.195 +} 22.196 + 22.197 +static void sndio_close_playback(ALCdevice *device) 22.198 +{ 22.199 + sndio_data *data = device->ExtraData; 22.200 + 22.201 + sio_close(data->sndHandle); 22.202 + free(data); 22.203 + device->ExtraData = NULL; 22.204 +} 22.205 + 22.206 +static ALCboolean sndio_reset_playback(ALCdevice *device) 22.207 +{ 22.208 + sndio_data *data = device->ExtraData; 22.209 + struct sio_par par; 22.210 + 22.211 + sio_initpar(&par); 22.212 + 22.213 + par.rate = device->Frequency; 22.214 + 22.215 + par.pchan = ((device->FmtChans != DevFmtMono) ? 2 : 1); 22.216 + 22.217 + switch(device->FmtType) 22.218 + { 22.219 + case DevFmtByte: 22.220 + par.bits = 8; 22.221 + par.sig = 1; 22.222 + break; 22.223 + case DevFmtUByte: 22.224 + par.bits = 8; 22.225 + par.sig = 0; 22.226 + break; 22.227 + case DevFmtFloat: 22.228 + device->FmtType = DevFmtShort; 22.229 + /* fall-through */ 22.230 + case DevFmtShort: 22.231 + par.bits = 16; 22.232 + par.sig = 1; 22.233 + break; 22.234 + case DevFmtUShort: 22.235 + par.bits = 16; 22.236 + par.sig = 0; 22.237 + break; 22.238 + } 22.239 + par.le = SIO_LE_NATIVE; 22.240 + 22.241 + par.round = device->UpdateSize; 22.242 + par.appbufsz = device->UpdateSize * (device->NumUpdates-1); 22.243 + if(!par.appbufsz) par.appbufsz = device->UpdateSize; 22.244 + 22.245 + 22.246 + if(!sio_setpar(data->sndHandle, &par) || !sio_getpar(data->sndHandle, &par)) 22.247 + { 22.248 + ERR("Failed to set device parameters\n"); 22.249 + return ALC_FALSE; 22.250 + } 22.251 + 22.252 + if(par.rate != device->Frequency) 22.253 + { 22.254 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 22.255 + ERR("Failed to set frequency %uhz, got %uhz instead\n", device->Frequency, par.rate); 22.256 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 22.257 + device->Frequency = par.rate; 22.258 + } 22.259 + 22.260 + if(par.pchan != ChannelsFromDevFmt(device->FmtChans)) 22.261 + { 22.262 + if(par.pchan != 1 && par.pchan != 2) 22.263 + { 22.264 + ERR("Unhandled channel count: %u\n", par.pchan); 22.265 + return ALC_FALSE; 22.266 + } 22.267 + if((device->Flags&DEVICE_CHANNELS_REQUEST)) 22.268 + ERR("Failed to set %s, got %u channels instead\n", DevFmtChannelsString(device->FmtChans), par.pchan); 22.269 + device->Flags &= ~DEVICE_CHANNELS_REQUEST; 22.270 + device->FmtChans = ((par.pchan==1) ? DevFmtMono : DevFmtStereo); 22.271 + } 22.272 + 22.273 + if(par.bits != par.bps*8) 22.274 + { 22.275 + ERR("Padded samples not supported (%u of %u bits)\n", par.bits, par.bps*8); 22.276 + return ALC_FALSE; 22.277 + } 22.278 + 22.279 + if(par.bits == 8 && par.sig == 1) 22.280 + device->FmtType = DevFmtByte; 22.281 + else if(par.bits == 8 && par.sig == 0) 22.282 + device->FmtType = DevFmtUByte; 22.283 + else if(par.bits == 16 && par.sig == 1) 22.284 + device->FmtType = DevFmtShort; 22.285 + else if(par.bits == 16 && par.sig == 0) 22.286 + device->FmtType = DevFmtUShort; 22.287 + else 22.288 + { 22.289 + ERR("Unhandled sample format: %s %u-bit\n", (par.sig?"signed":"unsigned"), par.bits); 22.290 + return ALC_FALSE; 22.291 + } 22.292 + 22.293 + 22.294 + device->UpdateSize = par.round; 22.295 + device->NumUpdates = (par.bufsz/par.round) + 1; 22.296 + 22.297 + SetDefaultChannelOrder(device); 22.298 + 22.299 + 22.300 + if(!sio_start(data->sndHandle)) 22.301 + { 22.302 + ERR("Error starting playback\n"); 22.303 + return ALC_FALSE; 22.304 + } 22.305 + 22.306 + data->data_size = device->UpdateSize * par.bps * par.pchan; 22.307 + data->mix_data = calloc(1, data->data_size); 22.308 + 22.309 + data->thread = StartThread(sndio_proc, device); 22.310 + if(data->thread == NULL) 22.311 + { 22.312 + sio_stop(data->sndHandle); 22.313 + free(data->mix_data); 22.314 + data->mix_data = NULL; 22.315 + return ALC_FALSE; 22.316 + } 22.317 + 22.318 + return ALC_TRUE; 22.319 +} 22.320 + 22.321 +static void sndio_stop_playback(ALCdevice *device) 22.322 +{ 22.323 + sndio_data *data = device->ExtraData; 22.324 + 22.325 + if(!data->thread) 22.326 + return; 22.327 + 22.328 + data->killNow = 1; 22.329 + StopThread(data->thread); 22.330 + data->thread = NULL; 22.331 + 22.332 + data->killNow = 0; 22.333 + if(!sio_stop(data->sndHandle)) 22.334 + ERR("Error stopping device\n"); 22.335 + 22.336 + free(data->mix_data); 22.337 + data->mix_data = NULL; 22.338 +} 22.339 + 22.340 + 22.341 +static const BackendFuncs sndio_funcs = { 22.342 + sndio_open_playback, 22.343 + sndio_close_playback, 22.344 + sndio_reset_playback, 22.345 + sndio_stop_playback, 22.346 + NULL, 22.347 + NULL, 22.348 + NULL, 22.349 + NULL, 22.350 + NULL, 22.351 + NULL 22.352 +}; 22.353 + 22.354 +ALCboolean alc_sndio_init(BackendFuncs *func_list) 22.355 +{ 22.356 + if(!sndio_load()) 22.357 + return ALC_FALSE; 22.358 + *func_list = sndio_funcs; 22.359 + return ALC_TRUE; 22.360 +} 22.361 + 22.362 +void alc_sndio_deinit(void) 22.363 +{ 22.364 +#ifdef HAVE_DYNLOAD 22.365 + if(sndio_handle) 22.366 + CloseLib(sndio_handle); 22.367 + sndio_handle = NULL; 22.368 +#endif 22.369 +} 22.370 + 22.371 +void alc_sndio_probe(enum DevProbe type) 22.372 +{ 22.373 + switch(type) 22.374 + { 22.375 + case DEVICE_PROBE: 22.376 + AppendDeviceList(sndio_device); 22.377 + break; 22.378 + case ALL_DEVICE_PROBE: 22.379 + AppendAllDeviceList(sndio_device); 22.380 + break; 22.381 + case CAPTURE_DEVICE_PROBE: 22.382 + break; 22.383 + } 22.384 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 23.2 +++ b/Alc/backends/solaris.c Tue Oct 25 13:02:31 2011 -0700 23.3 @@ -0,0 +1,282 @@ 23.4 +/** 23.5 + * OpenAL cross platform audio library 23.6 + * Copyright (C) 1999-2007 by authors. 23.7 + * This library is free software; you can redistribute it and/or 23.8 + * modify it under the terms of the GNU Library General Public 23.9 + * License as published by the Free Software Foundation; either 23.10 + * version 2 of the License, or (at your option) any later version. 23.11 + * 23.12 + * This library is distributed in the hope that it will be useful, 23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23.15 + * Library General Public License for more details. 23.16 + * 23.17 + * You should have received a copy of the GNU Library General Public 23.18 + * License along with this library; if not, write to the 23.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23.20 + * Boston, MA 02111-1307, USA. 23.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 23.22 + */ 23.23 + 23.24 +#include "config.h" 23.25 + 23.26 +#include <sys/ioctl.h> 23.27 +#include <sys/types.h> 23.28 +#include <sys/stat.h> 23.29 +#include <fcntl.h> 23.30 +#include <stdlib.h> 23.31 +#include <stdio.h> 23.32 +#include <memory.h> 23.33 +#include <unistd.h> 23.34 +#include <errno.h> 23.35 +#include <math.h> 23.36 +#include "alMain.h" 23.37 +#include "AL/al.h" 23.38 +#include "AL/alc.h" 23.39 + 23.40 +#include <sys/audioio.h> 23.41 + 23.42 + 23.43 +static const ALCchar solaris_device[] = "Solaris Default"; 23.44 + 23.45 +typedef struct { 23.46 + int fd; 23.47 + volatile int killNow; 23.48 + ALvoid *thread; 23.49 + 23.50 + ALubyte *mix_data; 23.51 + int data_size; 23.52 +} solaris_data; 23.53 + 23.54 + 23.55 +static ALuint SolarisProc(ALvoid *ptr) 23.56 +{ 23.57 + ALCdevice *pDevice = (ALCdevice*)ptr; 23.58 + solaris_data *data = (solaris_data*)pDevice->ExtraData; 23.59 + ALint frameSize; 23.60 + int wrote; 23.61 + 23.62 + SetRTPriority(); 23.63 + 23.64 + frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 23.65 + 23.66 + while(!data->killNow && pDevice->Connected) 23.67 + { 23.68 + ALint len = data->data_size; 23.69 + ALubyte *WritePtr = data->mix_data; 23.70 + 23.71 + aluMixData(pDevice, WritePtr, len/frameSize); 23.72 + while(len > 0 && !data->killNow) 23.73 + { 23.74 + wrote = write(data->fd, WritePtr, len); 23.75 + if(wrote < 0) 23.76 + { 23.77 + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) 23.78 + { 23.79 + ERR("write failed: %s\n", strerror(errno)); 23.80 + aluHandleDisconnect(pDevice); 23.81 + break; 23.82 + } 23.83 + 23.84 + Sleep(1); 23.85 + continue; 23.86 + } 23.87 + 23.88 + len -= wrote; 23.89 + WritePtr += wrote; 23.90 + } 23.91 + } 23.92 + 23.93 + return 0; 23.94 +} 23.95 + 23.96 + 23.97 +static ALCboolean solaris_open_playback(ALCdevice *device, const ALCchar *deviceName) 23.98 +{ 23.99 + char driver[64]; 23.100 + solaris_data *data; 23.101 + 23.102 + strncpy(driver, GetConfigValue("solaris", "device", "/dev/audio"), sizeof(driver)-1); 23.103 + driver[sizeof(driver)-1] = 0; 23.104 + 23.105 + if(!deviceName) 23.106 + deviceName = solaris_device; 23.107 + else if(strcmp(deviceName, solaris_device) != 0) 23.108 + return ALC_FALSE; 23.109 + 23.110 + data = (solaris_data*)calloc(1, sizeof(solaris_data)); 23.111 + data->killNow = 0; 23.112 + 23.113 + data->fd = open(driver, O_WRONLY); 23.114 + if(data->fd == -1) 23.115 + { 23.116 + free(data); 23.117 + ERR("Could not open %s: %s\n", driver, strerror(errno)); 23.118 + return ALC_FALSE; 23.119 + } 23.120 + 23.121 + device->szDeviceName = strdup(deviceName); 23.122 + device->ExtraData = data; 23.123 + return ALC_TRUE; 23.124 +} 23.125 + 23.126 +static void solaris_close_playback(ALCdevice *device) 23.127 +{ 23.128 + solaris_data *data = (solaris_data*)device->ExtraData; 23.129 + 23.130 + close(data->fd); 23.131 + free(data); 23.132 + device->ExtraData = NULL; 23.133 +} 23.134 + 23.135 +static ALCboolean solaris_reset_playback(ALCdevice *device) 23.136 +{ 23.137 + solaris_data *data = (solaris_data*)device->ExtraData; 23.138 + audio_info_t info; 23.139 + ALuint frameSize; 23.140 + int numChannels; 23.141 + 23.142 + AUDIO_INITINFO(&info); 23.143 + 23.144 + info.play.sample_rate = device->Frequency; 23.145 + 23.146 + if(device->FmtChans != DevFmtMono) 23.147 + device->FmtChans = DevFmtStereo; 23.148 + numChannels = ChannelsFromDevFmt(device->FmtChans); 23.149 + info.play.channels = numChannels; 23.150 + 23.151 + switch(device->FmtType) 23.152 + { 23.153 + case DevFmtByte: 23.154 + info.play.precision = 8; 23.155 + info.play.encoding = AUDIO_ENCODING_LINEAR; 23.156 + break; 23.157 + case DevFmtUByte: 23.158 + info.play.precision = 8; 23.159 + info.play.encoding = AUDIO_ENCODING_LINEAR8; 23.160 + break; 23.161 + case DevFmtUShort: 23.162 + case DevFmtFloat: 23.163 + device->FmtType = DevFmtShort; 23.164 + /* fall-through */ 23.165 + case DevFmtShort: 23.166 + info.play.precision = 16; 23.167 + info.play.encoding = AUDIO_ENCODING_LINEAR; 23.168 + break; 23.169 + } 23.170 + 23.171 + frameSize = numChannels * BytesFromDevFmt(device->FmtType); 23.172 + info.play.buffer_size = device->UpdateSize*device->NumUpdates * frameSize; 23.173 + 23.174 + if(ioctl(data->fd, AUDIO_SETINFO, &info) < 0) 23.175 + { 23.176 + ERR("ioctl failed: %s\n", strerror(errno)); 23.177 + return ALC_FALSE; 23.178 + } 23.179 + 23.180 + if(ChannelsFromDevFmt(device->FmtChans) != info.play.channels) 23.181 + { 23.182 + ERR("Could not set %d channels, got %d instead\n", ChannelsFromDevFmt(device->FmtChans), info.play.channels); 23.183 + return ALC_FALSE; 23.184 + } 23.185 + 23.186 + if(!((info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR && 23.187 + device->FmtType == DevFmtByte) || 23.188 + (info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8 && 23.189 + device->FmtType == DevFmtUByte) || 23.190 + (info.play.precision == 16 && info.play.encoding == AUDIO_ENCODING_LINEAR && 23.191 + device->FmtType == DevFmtShort))) 23.192 + { 23.193 + ERR("Could not set %#x sample type, got %d (%#x)\n", 23.194 + device->FmtType, info.play.precision, info.play.encoding); 23.195 + return ALC_FALSE; 23.196 + } 23.197 + 23.198 + if(device->Frequency != info.play.sample_rate) 23.199 + { 23.200 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 23.201 + ERR("Failed to set requested frequency %dhz, got %dhz instead\n", device->Frequency, info.play.sample_rate); 23.202 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 23.203 + device->Frequency = info.play.sample_rate; 23.204 + } 23.205 + device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1; 23.206 + 23.207 + data->data_size = device->UpdateSize * frameSize; 23.208 + data->mix_data = calloc(1, data->data_size); 23.209 + 23.210 + SetDefaultChannelOrder(device); 23.211 + 23.212 + data->thread = StartThread(SolarisProc, device); 23.213 + if(data->thread == NULL) 23.214 + { 23.215 + free(data->mix_data); 23.216 + data->mix_data = NULL; 23.217 + return ALC_FALSE; 23.218 + } 23.219 + 23.220 + return ALC_TRUE; 23.221 +} 23.222 + 23.223 +static void solaris_stop_playback(ALCdevice *device) 23.224 +{ 23.225 + solaris_data *data = (solaris_data*)device->ExtraData; 23.226 + 23.227 + if(!data->thread) 23.228 + return; 23.229 + 23.230 + data->killNow = 1; 23.231 + StopThread(data->thread); 23.232 + data->thread = NULL; 23.233 + 23.234 + data->killNow = 0; 23.235 + if(ioctl(data->fd, AUDIO_DRAIN) < 0) 23.236 + ERR("Error draining device: %s\n", strerror(errno)); 23.237 + 23.238 + free(data->mix_data); 23.239 + data->mix_data = NULL; 23.240 +} 23.241 + 23.242 + 23.243 +static const BackendFuncs solaris_funcs = { 23.244 + solaris_open_playback, 23.245 + solaris_close_playback, 23.246 + solaris_reset_playback, 23.247 + solaris_stop_playback, 23.248 + NULL, 23.249 + NULL, 23.250 + NULL, 23.251 + NULL, 23.252 + NULL, 23.253 + NULL 23.254 +}; 23.255 + 23.256 +ALCboolean alc_solaris_init(BackendFuncs *func_list) 23.257 +{ 23.258 + *func_list = solaris_funcs; 23.259 + return ALC_TRUE; 23.260 +} 23.261 + 23.262 +void alc_solaris_deinit(void) 23.263 +{ 23.264 +} 23.265 + 23.266 +void alc_solaris_probe(enum DevProbe type) 23.267 +{ 23.268 +#ifdef HAVE_STAT 23.269 + struct stat buf; 23.270 + if(stat(GetConfigValue("solaris", "device", "/dev/audio"), &buf) != 0) 23.271 + return; 23.272 +#endif 23.273 + 23.274 + switch(type) 23.275 + { 23.276 + case DEVICE_PROBE: 23.277 + AppendDeviceList(solaris_device); 23.278 + break; 23.279 + case ALL_DEVICE_PROBE: 23.280 + AppendAllDeviceList(solaris_device); 23.281 + break; 23.282 + case CAPTURE_DEVICE_PROBE: 23.283 + break; 23.284 + } 23.285 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 24.2 +++ b/Alc/backends/wave.c Tue Oct 25 13:02:31 2011 -0700 24.3 @@ -0,0 +1,357 @@ 24.4 +/** 24.5 + * OpenAL cross platform audio library 24.6 + * Copyright (C) 1999-2007 by authors. 24.7 + * This library is free software; you can redistribute it and/or 24.8 + * modify it under the terms of the GNU Library General Public 24.9 + * License as published by the Free Software Foundation; either 24.10 + * version 2 of the License, or (at your option) any later version. 24.11 + * 24.12 + * This library is distributed in the hope that it will be useful, 24.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 24.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24.15 + * Library General Public License for more details. 24.16 + * 24.17 + * You should have received a copy of the GNU Library General Public 24.18 + * License along with this library; if not, write to the 24.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 24.20 + * Boston, MA 02111-1307, USA. 24.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 24.22 + */ 24.23 + 24.24 +#include "config.h" 24.25 + 24.26 +#include <stdlib.h> 24.27 +#include <stdio.h> 24.28 +#include <memory.h> 24.29 +#include "alMain.h" 24.30 +#include "AL/al.h" 24.31 +#include "AL/alc.h" 24.32 + 24.33 + 24.34 +typedef struct { 24.35 + FILE *f; 24.36 + long DataStart; 24.37 + 24.38 + ALvoid *buffer; 24.39 + ALuint size; 24.40 + 24.41 + volatile int killNow; 24.42 + ALvoid *thread; 24.43 +} wave_data; 24.44 + 24.45 + 24.46 +static const ALCchar waveDevice[] = "Wave File Writer"; 24.47 + 24.48 +static const ALubyte SUBTYPE_PCM[] = { 24.49 + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 24.50 + 0x00, 0x38, 0x9b, 0x71 24.51 +}; 24.52 +static const ALubyte SUBTYPE_FLOAT[] = { 24.53 + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 24.54 + 0x00, 0x38, 0x9b, 0x71 24.55 +}; 24.56 + 24.57 +static const ALuint channel_masks[] = { 24.58 + 0, /* invalid */ 24.59 + 0x4, /* Mono */ 24.60 + 0x1 | 0x2, /* Stereo */ 24.61 + 0, /* 3 channel */ 24.62 + 0x1 | 0x2 | 0x10 | 0x20, /* Quad */ 24.63 + 0, /* 5 channel */ 24.64 + 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20, /* 5.1 */ 24.65 + 0x1 | 0x2 | 0x4 | 0x8 | 0x100 | 0x200 | 0x400, /* 6.1 */ 24.66 + 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x200 | 0x400, /* 7.1 */ 24.67 +}; 24.68 + 24.69 + 24.70 +static void fwrite16le(ALushort val, FILE *f) 24.71 +{ 24.72 + fputc(val&0xff, f); 24.73 + fputc((val>>8)&0xff, f); 24.74 +} 24.75 + 24.76 +static void fwrite32le(ALuint val, FILE *f) 24.77 +{ 24.78 + fputc(val&0xff, f); 24.79 + fputc((val>>8)&0xff, f); 24.80 + fputc((val>>16)&0xff, f); 24.81 + fputc((val>>24)&0xff, f); 24.82 +} 24.83 + 24.84 + 24.85 +static ALuint WaveProc(ALvoid *ptr) 24.86 +{ 24.87 + ALCdevice *pDevice = (ALCdevice*)ptr; 24.88 + wave_data *data = (wave_data*)pDevice->ExtraData; 24.89 + ALuint frameSize; 24.90 + ALuint now, start; 24.91 + ALuint64 avail, done; 24.92 + size_t fs; 24.93 + union { 24.94 + short s; 24.95 + char b[sizeof(short)]; 24.96 + } uSB; 24.97 + const ALuint restTime = (ALuint64)pDevice->UpdateSize * 1000 / 24.98 + pDevice->Frequency / 2; 24.99 + 24.100 + uSB.s = 1; 24.101 + frameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 24.102 + 24.103 + done = 0; 24.104 + start = timeGetTime(); 24.105 + while(!data->killNow && pDevice->Connected) 24.106 + { 24.107 + now = timeGetTime(); 24.108 + 24.109 + avail = (ALuint64)(now-start) * pDevice->Frequency / 1000; 24.110 + if(avail < done) 24.111 + { 24.112 + /* Timer wrapped. Add the remainder of the cycle to the available 24.113 + * count and reset the number of samples done */ 24.114 + avail += (ALuint64)0xFFFFFFFFu*pDevice->Frequency/1000 - done; 24.115 + done = 0; 24.116 + } 24.117 + if(avail-done < pDevice->UpdateSize) 24.118 + { 24.119 + Sleep(restTime); 24.120 + continue; 24.121 + } 24.122 + 24.123 + while(avail-done >= pDevice->UpdateSize) 24.124 + { 24.125 + aluMixData(pDevice, data->buffer, pDevice->UpdateSize); 24.126 + done += pDevice->UpdateSize; 24.127 + 24.128 + if(uSB.b[0] != 1) 24.129 + { 24.130 + ALuint bytesize = BytesFromDevFmt(pDevice->FmtType); 24.131 + ALubyte *bytes = data->buffer; 24.132 + ALuint i; 24.133 + 24.134 + if(bytesize == 1) 24.135 + { 24.136 + for(i = 0;i < data->size;i++) 24.137 + fputc(bytes[i], data->f); 24.138 + } 24.139 + else if(bytesize == 2) 24.140 + { 24.141 + for(i = 0;i < data->size;i++) 24.142 + fputc(bytes[i^1], data->f); 24.143 + } 24.144 + else if(bytesize == 4) 24.145 + { 24.146 + for(i = 0;i < data->size;i++) 24.147 + fputc(bytes[i^3], data->f); 24.148 + } 24.149 + } 24.150 + else 24.151 + fs = fwrite(data->buffer, frameSize, pDevice->UpdateSize, 24.152 + data->f); 24.153 + if(ferror(data->f)) 24.154 + { 24.155 + ERR("Error writing to file\n"); 24.156 + aluHandleDisconnect(pDevice); 24.157 + break; 24.158 + } 24.159 + } 24.160 + } 24.161 + 24.162 + return 0; 24.163 +} 24.164 + 24.165 +static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName) 24.166 +{ 24.167 + wave_data *data; 24.168 + const char *fname; 24.169 + 24.170 + fname = GetConfigValue("wave", "file", ""); 24.171 + if(!fname[0]) 24.172 + return ALC_FALSE; 24.173 + 24.174 + if(!deviceName) 24.175 + deviceName = waveDevice; 24.176 + else if(strcmp(deviceName, waveDevice) != 0) 24.177 + return ALC_FALSE; 24.178 + 24.179 + data = (wave_data*)calloc(1, sizeof(wave_data)); 24.180 + 24.181 + data->f = fopen(fname, "wb"); 24.182 + if(!data->f) 24.183 + { 24.184 + free(data); 24.185 + ERR("Could not open file '%s': %s\n", fname, strerror(errno)); 24.186 + return ALC_FALSE; 24.187 + } 24.188 + 24.189 + device->szDeviceName = strdup(deviceName); 24.190 + device->ExtraData = data; 24.191 + return ALC_TRUE; 24.192 +} 24.193 + 24.194 +static void wave_close_playback(ALCdevice *device) 24.195 +{ 24.196 + wave_data *data = (wave_data*)device->ExtraData; 24.197 + 24.198 + fclose(data->f); 24.199 + free(data); 24.200 + device->ExtraData = NULL; 24.201 +} 24.202 + 24.203 +static ALCboolean wave_reset_playback(ALCdevice *device) 24.204 +{ 24.205 + wave_data *data = (wave_data*)device->ExtraData; 24.206 + ALuint channels=0, bits=0; 24.207 + size_t val; 24.208 + 24.209 + fseek(data->f, 0, SEEK_SET); 24.210 + clearerr(data->f); 24.211 + 24.212 + switch(device->FmtType) 24.213 + { 24.214 + case DevFmtByte: 24.215 + device->FmtType = DevFmtUByte; 24.216 + break; 24.217 + case DevFmtUShort: 24.218 + device->FmtType = DevFmtShort; 24.219 + break; 24.220 + case DevFmtUByte: 24.221 + case DevFmtShort: 24.222 + case DevFmtFloat: 24.223 + break; 24.224 + } 24.225 + bits = BytesFromDevFmt(device->FmtType) * 8; 24.226 + channels = ChannelsFromDevFmt(device->FmtChans); 24.227 + 24.228 + fprintf(data->f, "RIFF"); 24.229 + fwrite32le(0xFFFFFFFF, data->f); // 'RIFF' header len; filled in at close 24.230 + 24.231 + fprintf(data->f, "WAVE"); 24.232 + 24.233 + fprintf(data->f, "fmt "); 24.234 + fwrite32le(40, data->f); // 'fmt ' header len; 40 bytes for EXTENSIBLE 24.235 + 24.236 + // 16-bit val, format type id (extensible: 0xFFFE) 24.237 + fwrite16le(0xFFFE, data->f); 24.238 + // 16-bit val, channel count 24.239 + fwrite16le(channels, data->f); 24.240 + // 32-bit val, frequency 24.241 + fwrite32le(device->Frequency, data->f); 24.242 + // 32-bit val, bytes per second 24.243 + fwrite32le(device->Frequency * channels * bits / 8, data->f); 24.244 + // 16-bit val, frame size 24.245 + fwrite16le(channels * bits / 8, data->f); 24.246 + // 16-bit val, bits per sample 24.247 + fwrite16le(bits, data->f); 24.248 + // 16-bit val, extra byte count 24.249 + fwrite16le(22, data->f); 24.250 + // 16-bit val, valid bits per sample 24.251 + fwrite16le(bits, data->f); 24.252 + // 32-bit val, channel mask 24.253 + fwrite32le(channel_masks[channels], data->f); 24.254 + // 16 byte GUID, sub-type format 24.255 + val = fwrite(((bits==32) ? SUBTYPE_FLOAT : SUBTYPE_PCM), 1, 16, data->f); 24.256 + 24.257 + fprintf(data->f, "data"); 24.258 + fwrite32le(0xFFFFFFFF, data->f); // 'data' header len; filled in at close 24.259 + 24.260 + if(ferror(data->f)) 24.261 + { 24.262 + ERR("Error writing header: %s\n", strerror(errno)); 24.263 + return ALC_FALSE; 24.264 + } 24.265 + 24.266 + data->DataStart = ftell(data->f); 24.267 + 24.268 + data->size = device->UpdateSize * channels * bits / 8; 24.269 + data->buffer = malloc(data->size); 24.270 + if(!data->buffer) 24.271 + { 24.272 + ERR("Buffer malloc failed\n"); 24.273 + return ALC_FALSE; 24.274 + } 24.275 + 24.276 + SetDefaultWFXChannelOrder(device); 24.277 + 24.278 + data->thread = StartThread(WaveProc, device); 24.279 + if(data->thread == NULL) 24.280 + { 24.281 + free(data->buffer); 24.282 + data->buffer = NULL; 24.283 + return ALC_FALSE; 24.284 + } 24.285 + 24.286 + return ALC_TRUE; 24.287 +} 24.288 + 24.289 +static void wave_stop_playback(ALCdevice *device) 24.290 +{ 24.291 + wave_data *data = (wave_data*)device->ExtraData; 24.292 + ALuint dataLen; 24.293 + long size; 24.294 + 24.295 + if(!data->thread) 24.296 + return; 24.297 + 24.298 + data->killNow = 1; 24.299 + StopThread(data->thread); 24.300 + data->thread = NULL; 24.301 + 24.302 + data->killNow = 0; 24.303 + 24.304 + free(data->buffer); 24.305 + data->buffer = NULL; 24.306 + 24.307 + size = ftell(data->f); 24.308 + if(size > 0) 24.309 + { 24.310 + dataLen = size - data->DataStart; 24.311 + if(fseek(data->f, data->DataStart-4, SEEK_SET) == 0) 24.312 + fwrite32le(dataLen, data->f); // 'data' header len 24.313 + if(fseek(data->f, 4, SEEK_SET) == 0) 24.314 + fwrite32le(size-8, data->f); // 'WAVE' header len 24.315 + } 24.316 +} 24.317 + 24.318 + 24.319 +static const BackendFuncs wave_funcs = { 24.320 + wave_open_playback, 24.321 + wave_close_playback, 24.322 + wave_reset_playback, 24.323 + wave_stop_playback, 24.324 + NULL, 24.325 + NULL, 24.326 + NULL, 24.327 + NULL, 24.328 + NULL, 24.329 + NULL 24.330 +}; 24.331 + 24.332 +ALCboolean alc_wave_init(BackendFuncs *func_list) 24.333 +{ 24.334 + *func_list = wave_funcs; 24.335 + printf("WAVE: I'm init!!\n"); 24.336 + return ALC_TRUE; 24.337 +} 24.338 + 24.339 +void alc_wave_deinit(void) 24.340 +{ 24.341 +} 24.342 + 24.343 +void alc_wave_probe(enum DevProbe type) 24.344 +{ 24.345 + printf("WAVE: I'm being probed :)\n"); 24.346 + if(!ConfigValueExists("wave", "file")) 24.347 + return; 24.348 + 24.349 + switch(type) 24.350 + { 24.351 + case DEVICE_PROBE: 24.352 + AppendDeviceList(waveDevice); 24.353 + break; 24.354 + case ALL_DEVICE_PROBE: 24.355 + AppendAllDeviceList(waveDevice); 24.356 + break; 24.357 + case CAPTURE_DEVICE_PROBE: 24.358 + break; 24.359 + } 24.360 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 25.2 +++ b/Alc/backends/winmm.c Tue Oct 25 13:02:31 2011 -0700 25.3 @@ -0,0 +1,780 @@ 25.4 +/** 25.5 + * OpenAL cross platform audio library 25.6 + * Copyright (C) 1999-2007 by authors. 25.7 + * This library is free software; you can redistribute it and/or 25.8 + * modify it under the terms of the GNU Library General Public 25.9 + * License as published by the Free Software Foundation; either 25.10 + * version 2 of the License, or (at your option) any later version. 25.11 + * 25.12 + * This library is distributed in the hope that it will be useful, 25.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 25.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25.15 + * Library General Public License for more details. 25.16 + * 25.17 + * You should have received a copy of the GNU Library General Public 25.18 + * License along with this library; if not, write to the 25.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 25.20 + * Boston, MA 02111-1307, USA. 25.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 25.22 + */ 25.23 + 25.24 +#include "config.h" 25.25 + 25.26 +#define _WIN32_WINNT 0x0500 25.27 +#include <stdlib.h> 25.28 +#include <stdio.h> 25.29 +#include <memory.h> 25.30 + 25.31 +#include <windows.h> 25.32 +#include <mmsystem.h> 25.33 + 25.34 +#include "alMain.h" 25.35 +#include "AL/al.h" 25.36 +#include "AL/alc.h" 25.37 + 25.38 + 25.39 +typedef struct { 25.40 + // MMSYSTEM Device 25.41 + volatile ALboolean bWaveShutdown; 25.42 + HANDLE hWaveThreadEvent; 25.43 + HANDLE hWaveThread; 25.44 + DWORD ulWaveThreadID; 25.45 + LONG lWaveBuffersCommitted; 25.46 + WAVEHDR WaveBuffer[4]; 25.47 + 25.48 + union { 25.49 + HWAVEIN In; 25.50 + HWAVEOUT Out; 25.51 + } hWaveHandle; 25.52 + 25.53 + ALuint Frequency; 25.54 + 25.55 + RingBuffer *pRing; 25.56 +} WinMMData; 25.57 + 25.58 + 25.59 +static const ALCchar woDefault[] = "WaveOut Default"; 25.60 + 25.61 +static ALCchar **PlaybackDeviceList; 25.62 +static ALuint NumPlaybackDevices; 25.63 +static ALCchar **CaptureDeviceList; 25.64 +static ALuint NumCaptureDevices; 25.65 + 25.66 + 25.67 +static void ProbePlaybackDevices(void) 25.68 +{ 25.69 + ALuint i; 25.70 + 25.71 + for(i = 0;i < NumPlaybackDevices;i++) 25.72 + free(PlaybackDeviceList[i]); 25.73 + 25.74 + NumPlaybackDevices = waveOutGetNumDevs(); 25.75 + PlaybackDeviceList = realloc(PlaybackDeviceList, sizeof(ALCchar*) * NumPlaybackDevices); 25.76 + for(i = 0;i < NumPlaybackDevices;i++) 25.77 + { 25.78 + WAVEOUTCAPS WaveCaps; 25.79 + 25.80 + PlaybackDeviceList[i] = NULL; 25.81 + if(waveOutGetDevCaps(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) 25.82 + { 25.83 + char name[1024]; 25.84 + ALuint count, j; 25.85 + 25.86 + count = 0; 25.87 + do { 25.88 + if(count == 0) 25.89 + snprintf(name, sizeof(name), "%s", WaveCaps.szPname); 25.90 + else 25.91 + snprintf(name, sizeof(name), "%s #%d", WaveCaps.szPname, count+1); 25.92 + count++; 25.93 + 25.94 + for(j = 0;j < i;j++) 25.95 + { 25.96 + if(strcmp(name, PlaybackDeviceList[j]) == 0) 25.97 + break; 25.98 + } 25.99 + } while(j != i); 25.100 + 25.101 + PlaybackDeviceList[i] = strdup(name); 25.102 + } 25.103 + } 25.104 +} 25.105 + 25.106 +static void ProbeCaptureDevices(void) 25.107 +{ 25.108 + ALuint i; 25.109 + 25.110 + for(i = 0;i < NumCaptureDevices;i++) 25.111 + free(CaptureDeviceList[i]); 25.112 + 25.113 + NumCaptureDevices = waveInGetNumDevs(); 25.114 + CaptureDeviceList = realloc(CaptureDeviceList, sizeof(ALCchar*) * NumCaptureDevices); 25.115 + for(i = 0;i < NumCaptureDevices;i++) 25.116 + { 25.117 + WAVEINCAPS WaveInCaps; 25.118 + 25.119 + CaptureDeviceList[i] = NULL; 25.120 + if(waveInGetDevCaps(i, &WaveInCaps, sizeof(WAVEINCAPS)) == MMSYSERR_NOERROR) 25.121 + { 25.122 + char name[1024]; 25.123 + ALuint count, j; 25.124 + 25.125 + count = 0; 25.126 + do { 25.127 + if(count == 0) 25.128 + snprintf(name, sizeof(name), "%s", WaveInCaps.szPname); 25.129 + else 25.130 + snprintf(name, sizeof(name), "%s #%d", WaveInCaps.szPname, count+1); 25.131 + count++; 25.132 + 25.133 + for(j = 0;j < i;j++) 25.134 + { 25.135 + if(strcmp(name, CaptureDeviceList[j]) == 0) 25.136 + break; 25.137 + } 25.138 + } while(j != i); 25.139 + 25.140 + CaptureDeviceList[i] = strdup(name); 25.141 + } 25.142 + } 25.143 +} 25.144 + 25.145 + 25.146 +/* 25.147 + WaveOutProc 25.148 + 25.149 + Posts a message to 'PlaybackThreadProc' everytime a WaveOut Buffer is completed and 25.150 + returns to the application (for more data) 25.151 +*/ 25.152 +static void CALLBACK WaveOutProc(HWAVEOUT hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2) 25.153 +{ 25.154 + ALCdevice *pDevice = (ALCdevice*)dwInstance; 25.155 + WinMMData *pData = pDevice->ExtraData; 25.156 + 25.157 + (void)hDevice; 25.158 + (void)dwParam2; 25.159 + 25.160 + if(uMsg != WOM_DONE) 25.161 + return; 25.162 + 25.163 + // Decrement number of buffers in use 25.164 + InterlockedDecrement(&pData->lWaveBuffersCommitted); 25.165 + 25.166 + if(pData->bWaveShutdown == AL_FALSE) 25.167 + { 25.168 + // Notify Wave Processor Thread that a Wave Header has returned 25.169 + PostThreadMessage(pData->ulWaveThreadID, uMsg, 0, dwParam1); 25.170 + } 25.171 + else 25.172 + { 25.173 + if(pData->lWaveBuffersCommitted == 0) 25.174 + { 25.175 + // Post 'Quit' Message to WaveOut Processor Thread 25.176 + PostThreadMessage(pData->ulWaveThreadID, WM_QUIT, 0, 0); 25.177 + } 25.178 + } 25.179 +} 25.180 + 25.181 +/* 25.182 + PlaybackThreadProc 25.183 + 25.184 + Used by "MMSYSTEM" Device. Called when a WaveOut buffer has used up its 25.185 + audio data. 25.186 +*/ 25.187 +static DWORD WINAPI PlaybackThreadProc(LPVOID lpParameter) 25.188 +{ 25.189 + ALCdevice *pDevice = (ALCdevice*)lpParameter; 25.190 + WinMMData *pData = pDevice->ExtraData; 25.191 + LPWAVEHDR pWaveHdr; 25.192 + ALuint FrameSize; 25.193 + MSG msg; 25.194 + 25.195 + FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 25.196 + 25.197 + SetRTPriority(); 25.198 + 25.199 + while(GetMessage(&msg, NULL, 0, 0)) 25.200 + { 25.201 + if(msg.message != WOM_DONE || pData->bWaveShutdown) 25.202 + continue; 25.203 + 25.204 + pWaveHdr = ((LPWAVEHDR)msg.lParam); 25.205 + 25.206 + aluMixData(pDevice, pWaveHdr->lpData, pWaveHdr->dwBufferLength/FrameSize); 25.207 + 25.208 + // Send buffer back to play more data 25.209 + waveOutWrite(pData->hWaveHandle.Out, pWaveHdr, sizeof(WAVEHDR)); 25.210 + InterlockedIncrement(&pData->lWaveBuffersCommitted); 25.211 + } 25.212 + 25.213 + // Signal Wave Thread completed event 25.214 + if(pData->hWaveThreadEvent) 25.215 + SetEvent(pData->hWaveThreadEvent); 25.216 + 25.217 + ExitThread(0); 25.218 + 25.219 + return 0; 25.220 +} 25.221 + 25.222 +/* 25.223 + WaveInProc 25.224 + 25.225 + Posts a message to 'CaptureThreadProc' everytime a WaveIn Buffer is completed and 25.226 + returns to the application (with more data) 25.227 +*/ 25.228 +static void CALLBACK WaveInProc(HWAVEIN hDevice,UINT uMsg,DWORD_PTR dwInstance,DWORD_PTR dwParam1,DWORD_PTR dwParam2) 25.229 +{ 25.230 + ALCdevice *pDevice = (ALCdevice*)dwInstance; 25.231 + WinMMData *pData = pDevice->ExtraData; 25.232 + 25.233 + (void)hDevice; 25.234 + (void)dwParam2; 25.235 + 25.236 + if(uMsg != WIM_DATA) 25.237 + return; 25.238 + 25.239 + // Decrement number of buffers in use 25.240 + InterlockedDecrement(&pData->lWaveBuffersCommitted); 25.241 + 25.242 + if(pData->bWaveShutdown == AL_FALSE) 25.243 + { 25.244 + // Notify Wave Processor Thread that a Wave Header has returned 25.245 + PostThreadMessage(pData->ulWaveThreadID,uMsg,0,dwParam1); 25.246 + } 25.247 + else 25.248 + { 25.249 + if(pData->lWaveBuffersCommitted == 0) 25.250 + { 25.251 + // Post 'Quit' Message to WaveIn Processor Thread 25.252 + PostThreadMessage(pData->ulWaveThreadID,WM_QUIT,0,0); 25.253 + } 25.254 + } 25.255 +} 25.256 + 25.257 +/* 25.258 + CaptureThreadProc 25.259 + 25.260 + Used by "MMSYSTEM" Device. Called when a WaveIn buffer had been filled with new 25.261 + audio data. 25.262 +*/ 25.263 +static DWORD WINAPI CaptureThreadProc(LPVOID lpParameter) 25.264 +{ 25.265 + ALCdevice *pDevice = (ALCdevice*)lpParameter; 25.266 + WinMMData *pData = pDevice->ExtraData; 25.267 + LPWAVEHDR pWaveHdr; 25.268 + ALuint FrameSize; 25.269 + MSG msg; 25.270 + 25.271 + FrameSize = FrameSizeFromDevFmt(pDevice->FmtChans, pDevice->FmtType); 25.272 + 25.273 + while(GetMessage(&msg, NULL, 0, 0)) 25.274 + { 25.275 + if(msg.message != WIM_DATA || pData->bWaveShutdown) 25.276 + continue; 25.277 + 25.278 + pWaveHdr = ((LPWAVEHDR)msg.lParam); 25.279 + 25.280 + WriteRingBuffer(pData->pRing, (ALubyte*)pWaveHdr->lpData, 25.281 + pWaveHdr->dwBytesRecorded/FrameSize); 25.282 + 25.283 + // Send buffer back to capture more data 25.284 + waveInAddBuffer(pData->hWaveHandle.In,pWaveHdr,sizeof(WAVEHDR)); 25.285 + InterlockedIncrement(&pData->lWaveBuffersCommitted); 25.286 + } 25.287 + 25.288 + // Signal Wave Thread completed event 25.289 + if(pData->hWaveThreadEvent) 25.290 + SetEvent(pData->hWaveThreadEvent); 25.291 + 25.292 + ExitThread(0); 25.293 + 25.294 + return 0; 25.295 +} 25.296 + 25.297 + 25.298 +static ALCboolean WinMMOpenPlayback(ALCdevice *pDevice, const ALCchar *deviceName) 25.299 +{ 25.300 + WAVEFORMATEX wfexFormat; 25.301 + WinMMData *pData = NULL; 25.302 + UINT lDeviceID = 0; 25.303 + MMRESULT res; 25.304 + ALuint i = 0; 25.305 + 25.306 + // Find the Device ID matching the deviceName if valid 25.307 + if(!deviceName || strcmp(deviceName, woDefault) == 0) 25.308 + lDeviceID = WAVE_MAPPER; 25.309 + else 25.310 + { 25.311 + if(!PlaybackDeviceList) 25.312 + ProbePlaybackDevices(); 25.313 + 25.314 + for(i = 0;i < NumPlaybackDevices;i++) 25.315 + { 25.316 + if(PlaybackDeviceList[i] && 25.317 + strcmp(deviceName, PlaybackDeviceList[i]) == 0) 25.318 + { 25.319 + lDeviceID = i; 25.320 + break; 25.321 + } 25.322 + } 25.323 + if(i == NumPlaybackDevices) 25.324 + return ALC_FALSE; 25.325 + } 25.326 + 25.327 + pData = calloc(1, sizeof(*pData)); 25.328 + if(!pData) 25.329 + { 25.330 + alcSetError(pDevice, ALC_OUT_OF_MEMORY); 25.331 + return ALC_FALSE; 25.332 + } 25.333 + pDevice->ExtraData = pData; 25.334 + 25.335 + if(pDevice->FmtChans != DevFmtMono) 25.336 + { 25.337 + if((pDevice->Flags&DEVICE_CHANNELS_REQUEST) && 25.338 + pDevice->FmtChans != DevFmtStereo) 25.339 + { 25.340 + ERR("Failed to set %s, got Stereo instead\n", DevFmtChannelsString(pDevice->FmtChans)); 25.341 + pDevice->Flags &= ~DEVICE_CHANNELS_REQUEST; 25.342 + } 25.343 + pDevice->FmtChans = DevFmtStereo; 25.344 + } 25.345 + switch(pDevice->FmtType) 25.346 + { 25.347 + case DevFmtByte: 25.348 + pDevice->FmtType = DevFmtUByte; 25.349 + break; 25.350 + case DevFmtUShort: 25.351 + case DevFmtFloat: 25.352 + pDevice->FmtType = DevFmtShort; 25.353 + break; 25.354 + case DevFmtUByte: 25.355 + case DevFmtShort: 25.356 + break; 25.357 + } 25.358 + 25.359 + memset(&wfexFormat, 0, sizeof(WAVEFORMATEX)); 25.360 + wfexFormat.wFormatTag = WAVE_FORMAT_PCM; 25.361 + wfexFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans); 25.362 + wfexFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8; 25.363 + wfexFormat.nBlockAlign = wfexFormat.wBitsPerSample * 25.364 + wfexFormat.nChannels / 8; 25.365 + wfexFormat.nSamplesPerSec = pDevice->Frequency; 25.366 + wfexFormat.nAvgBytesPerSec = wfexFormat.nSamplesPerSec * 25.367 + wfexFormat.nBlockAlign; 25.368 + wfexFormat.cbSize = 0; 25.369 + 25.370 + if((res=waveOutOpen(&pData->hWaveHandle.Out, lDeviceID, &wfexFormat, (DWORD_PTR)&WaveOutProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) 25.371 + { 25.372 + ERR("waveOutOpen failed: %u\n", res); 25.373 + goto failure; 25.374 + } 25.375 + 25.376 + pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 25.377 + if(pData->hWaveThreadEvent == NULL) 25.378 + { 25.379 + ERR("CreateEvent failed: %lu\n", GetLastError()); 25.380 + goto failure; 25.381 + } 25.382 + 25.383 + pData->Frequency = pDevice->Frequency; 25.384 + 25.385 + pDevice->szDeviceName = strdup((lDeviceID==WAVE_MAPPER) ? woDefault : 25.386 + PlaybackDeviceList[lDeviceID]); 25.387 + return ALC_TRUE; 25.388 + 25.389 +failure: 25.390 + if(pData->hWaveThreadEvent) 25.391 + CloseHandle(pData->hWaveThreadEvent); 25.392 + 25.393 + if(pData->hWaveHandle.Out) 25.394 + waveOutClose(pData->hWaveHandle.Out); 25.395 + 25.396 + free(pData); 25.397 + pDevice->ExtraData = NULL; 25.398 + return ALC_FALSE; 25.399 +} 25.400 + 25.401 +static void WinMMClosePlayback(ALCdevice *device) 25.402 +{ 25.403 + WinMMData *pData = (WinMMData*)device->ExtraData; 25.404 + 25.405 + // Close the Wave device 25.406 + CloseHandle(pData->hWaveThreadEvent); 25.407 + pData->hWaveThreadEvent = 0; 25.408 + 25.409 + waveOutClose(pData->hWaveHandle.Out); 25.410 + pData->hWaveHandle.Out = 0; 25.411 + 25.412 + free(pData); 25.413 + device->ExtraData = NULL; 25.414 +} 25.415 + 25.416 +static ALCboolean WinMMResetPlayback(ALCdevice *device) 25.417 +{ 25.418 + WinMMData *pData = (WinMMData*)device->ExtraData; 25.419 + ALbyte *BufferData; 25.420 + ALint lBufferSize; 25.421 + ALuint i; 25.422 + 25.423 + pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PlaybackThreadProc, (LPVOID)device, 0, &pData->ulWaveThreadID); 25.424 + if(pData->hWaveThread == NULL) 25.425 + return ALC_FALSE; 25.426 + 25.427 + device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize * 25.428 + pData->Frequency / device->Frequency); 25.429 + if(device->Frequency != pData->Frequency) 25.430 + { 25.431 + if((device->Flags&DEVICE_FREQUENCY_REQUEST)) 25.432 + ERR("WinMM does not support changing sample rates (wanted %dhz, got %dhz)\n", device->Frequency, pData->Frequency); 25.433 + device->Flags &= ~DEVICE_FREQUENCY_REQUEST; 25.434 + device->Frequency = pData->Frequency; 25.435 + } 25.436 + 25.437 + SetDefaultWFXChannelOrder(device); 25.438 + 25.439 + pData->lWaveBuffersCommitted = 0; 25.440 + 25.441 + // Create 4 Buffers 25.442 + lBufferSize = device->UpdateSize*device->NumUpdates / 4; 25.443 + lBufferSize *= FrameSizeFromDevFmt(device->FmtChans, device->FmtType); 25.444 + 25.445 + BufferData = calloc(4, lBufferSize); 25.446 + for(i = 0;i < 4;i++) 25.447 + { 25.448 + memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR)); 25.449 + pData->WaveBuffer[i].dwBufferLength = lBufferSize; 25.450 + pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : 25.451 + (pData->WaveBuffer[i-1].lpData + 25.452 + pData->WaveBuffer[i-1].dwBufferLength)); 25.453 + waveOutPrepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.454 + waveOutWrite(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.455 + InterlockedIncrement(&pData->lWaveBuffersCommitted); 25.456 + } 25.457 + 25.458 + return ALC_TRUE; 25.459 +} 25.460 + 25.461 +static void WinMMStopPlayback(ALCdevice *device) 25.462 +{ 25.463 + WinMMData *pData = (WinMMData*)device->ExtraData; 25.464 + void *buffer = NULL; 25.465 + int i; 25.466 + 25.467 + if(pData->hWaveThread == NULL) 25.468 + return; 25.469 + 25.470 + // Set flag to stop processing headers 25.471 + pData->bWaveShutdown = AL_TRUE; 25.472 + 25.473 + // Wait for signal that Wave Thread has been destroyed 25.474 + WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE); 25.475 + 25.476 + CloseHandle(pData->hWaveThread); 25.477 + pData->hWaveThread = 0; 25.478 + 25.479 + pData->bWaveShutdown = AL_FALSE; 25.480 + 25.481 + // Release the wave buffers 25.482 + for(i = 0;i < 4;i++) 25.483 + { 25.484 + waveOutUnprepareHeader(pData->hWaveHandle.Out, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.485 + if(i == 0) buffer = pData->WaveBuffer[i].lpData; 25.486 + pData->WaveBuffer[i].lpData = NULL; 25.487 + } 25.488 + free(buffer); 25.489 +} 25.490 + 25.491 + 25.492 +static ALCboolean WinMMOpenCapture(ALCdevice *pDevice, const ALCchar *deviceName) 25.493 +{ 25.494 + WAVEFORMATEX wfexCaptureFormat; 25.495 + DWORD ulCapturedDataSize; 25.496 + WinMMData *pData = NULL; 25.497 + UINT lDeviceID = 0; 25.498 + ALbyte *BufferData; 25.499 + ALint lBufferSize; 25.500 + MMRESULT res; 25.501 + ALuint i; 25.502 + 25.503 + if(!CaptureDeviceList) 25.504 + ProbeCaptureDevices(); 25.505 + 25.506 + // Find the Device ID matching the deviceName if valid 25.507 + if(deviceName) 25.508 + { 25.509 + for(i = 0;i < NumCaptureDevices;i++) 25.510 + { 25.511 + if(CaptureDeviceList[i] && 25.512 + strcmp(deviceName, CaptureDeviceList[i]) == 0) 25.513 + { 25.514 + lDeviceID = i; 25.515 + break; 25.516 + } 25.517 + } 25.518 + } 25.519 + else 25.520 + { 25.521 + for(i = 0;i < NumCaptureDevices;i++) 25.522 + { 25.523 + if(CaptureDeviceList[i]) 25.524 + { 25.525 + lDeviceID = i; 25.526 + break; 25.527 + } 25.528 + } 25.529 + } 25.530 + if(i == NumCaptureDevices) 25.531 + return ALC_FALSE; 25.532 + 25.533 + pData = calloc(1, sizeof(*pData)); 25.534 + if(!pData) 25.535 + { 25.536 + alcSetError(pDevice, ALC_OUT_OF_MEMORY); 25.537 + return ALC_FALSE; 25.538 + } 25.539 + pDevice->ExtraData = pData; 25.540 + 25.541 + if((pDevice->FmtChans != DevFmtMono && pDevice->FmtChans != DevFmtStereo) || 25.542 + (pDevice->FmtType != DevFmtUByte && pDevice->FmtType != DevFmtShort)) 25.543 + { 25.544 + alcSetError(pDevice, ALC_INVALID_ENUM); 25.545 + goto failure; 25.546 + } 25.547 + 25.548 + memset(&wfexCaptureFormat, 0, sizeof(WAVEFORMATEX)); 25.549 + wfexCaptureFormat.wFormatTag = WAVE_FORMAT_PCM; 25.550 + wfexCaptureFormat.nChannels = ChannelsFromDevFmt(pDevice->FmtChans); 25.551 + wfexCaptureFormat.wBitsPerSample = BytesFromDevFmt(pDevice->FmtType) * 8; 25.552 + wfexCaptureFormat.nBlockAlign = wfexCaptureFormat.wBitsPerSample * 25.553 + wfexCaptureFormat.nChannels / 8; 25.554 + wfexCaptureFormat.nSamplesPerSec = pDevice->Frequency; 25.555 + wfexCaptureFormat.nAvgBytesPerSec = wfexCaptureFormat.nSamplesPerSec * 25.556 + wfexCaptureFormat.nBlockAlign; 25.557 + wfexCaptureFormat.cbSize = 0; 25.558 + 25.559 + if((res=waveInOpen(&pData->hWaveHandle.In, lDeviceID, &wfexCaptureFormat, (DWORD_PTR)&WaveInProc, (DWORD_PTR)pDevice, CALLBACK_FUNCTION)) != MMSYSERR_NOERROR) 25.560 + { 25.561 + ERR("waveInOpen failed: %u\n", res); 25.562 + goto failure; 25.563 + } 25.564 + 25.565 + pData->hWaveThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL); 25.566 + if(pData->hWaveThreadEvent == NULL) 25.567 + { 25.568 + ERR("CreateEvent failed: %lu\n", GetLastError()); 25.569 + goto failure; 25.570 + } 25.571 + 25.572 + pData->Frequency = pDevice->Frequency; 25.573 + 25.574 + // Allocate circular memory buffer for the captured audio 25.575 + ulCapturedDataSize = pDevice->UpdateSize*pDevice->NumUpdates; 25.576 + 25.577 + // Make sure circular buffer is at least 100ms in size 25.578 + if(ulCapturedDataSize < (wfexCaptureFormat.nSamplesPerSec / 10)) 25.579 + ulCapturedDataSize = wfexCaptureFormat.nSamplesPerSec / 10; 25.580 + 25.581 + pData->pRing = CreateRingBuffer(wfexCaptureFormat.nBlockAlign, ulCapturedDataSize); 25.582 + if(!pData->pRing) 25.583 + goto failure; 25.584 + 25.585 + pData->lWaveBuffersCommitted = 0; 25.586 + 25.587 + // Create 4 Buffers of 50ms each 25.588 + lBufferSize = wfexCaptureFormat.nAvgBytesPerSec / 20; 25.589 + lBufferSize -= (lBufferSize % wfexCaptureFormat.nBlockAlign); 25.590 + 25.591 + BufferData = calloc(4, lBufferSize); 25.592 + if(!BufferData) 25.593 + goto failure; 25.594 + 25.595 + for(i = 0;i < 4;i++) 25.596 + { 25.597 + memset(&pData->WaveBuffer[i], 0, sizeof(WAVEHDR)); 25.598 + pData->WaveBuffer[i].dwBufferLength = lBufferSize; 25.599 + pData->WaveBuffer[i].lpData = ((i==0) ? (LPSTR)BufferData : 25.600 + (pData->WaveBuffer[i-1].lpData + 25.601 + pData->WaveBuffer[i-1].dwBufferLength)); 25.602 + pData->WaveBuffer[i].dwFlags = 0; 25.603 + pData->WaveBuffer[i].dwLoops = 0; 25.604 + waveInPrepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.605 + waveInAddBuffer(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.606 + InterlockedIncrement(&pData->lWaveBuffersCommitted); 25.607 + } 25.608 + 25.609 + pData->hWaveThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CaptureThreadProc, (LPVOID)pDevice, 0, &pData->ulWaveThreadID); 25.610 + if (pData->hWaveThread == NULL) 25.611 + goto failure; 25.612 + 25.613 + pDevice->szDeviceName = strdup(CaptureDeviceList[lDeviceID]); 25.614 + return ALC_TRUE; 25.615 + 25.616 +failure: 25.617 + if(pData->hWaveThread) 25.618 + CloseHandle(pData->hWaveThread); 25.619 + 25.620 + for(i = 0;i < 4;i++) 25.621 + { 25.622 + if(pData->WaveBuffer[i].lpData) 25.623 + { 25.624 + waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.625 + if(i == 0) 25.626 + free(pData->WaveBuffer[i].lpData); 25.627 + } 25.628 + } 25.629 + 25.630 + if(pData->pRing) 25.631 + DestroyRingBuffer(pData->pRing); 25.632 + 25.633 + if(pData->hWaveThreadEvent) 25.634 + CloseHandle(pData->hWaveThreadEvent); 25.635 + 25.636 + if(pData->hWaveHandle.In) 25.637 + waveInClose(pData->hWaveHandle.In); 25.638 + 25.639 + free(pData); 25.640 + pDevice->ExtraData = NULL; 25.641 + return ALC_FALSE; 25.642 +} 25.643 + 25.644 +static void WinMMCloseCapture(ALCdevice *pDevice) 25.645 +{ 25.646 + WinMMData *pData = (WinMMData*)pDevice->ExtraData; 25.647 + void *buffer = NULL; 25.648 + int i; 25.649 + 25.650 + // Call waveOutReset to shutdown wave device 25.651 + pData->bWaveShutdown = AL_TRUE; 25.652 + waveInReset(pData->hWaveHandle.In); 25.653 + 25.654 + // Wait for signal that Wave Thread has been destroyed 25.655 + WaitForSingleObjectEx(pData->hWaveThreadEvent, 5000, FALSE); 25.656 + 25.657 + CloseHandle(pData->hWaveThread); 25.658 + pData->hWaveThread = 0; 25.659 + 25.660 + // Release the wave buffers 25.661 + for(i = 0;i < 4;i++) 25.662 + { 25.663 + waveInUnprepareHeader(pData->hWaveHandle.In, &pData->WaveBuffer[i], sizeof(WAVEHDR)); 25.664 + if(i == 0) buffer = pData->WaveBuffer[i].lpData; 25.665 + pData->WaveBuffer[i].lpData = NULL; 25.666 + } 25.667 + free(buffer); 25.668 + 25.669 + DestroyRingBuffer(pData->pRing); 25.670 + pData->pRing = NULL; 25.671 + 25.672 + // Close the Wave device 25.673 + CloseHandle(pData->hWaveThreadEvent); 25.674 + pData->hWaveThreadEvent = 0; 25.675 + 25.676 + waveInClose(pData->hWaveHandle.In); 25.677 + pData->hWaveHandle.In = 0; 25.678 + 25.679 + free(pData); 25.680 + pDevice->ExtraData = NULL; 25.681 +} 25.682 + 25.683 +static void WinMMStartCapture(ALCdevice *pDevice) 25.684 +{ 25.685 + WinMMData *pData = (WinMMData*)pDevice->ExtraData; 25.686 + waveInStart(pData->hWaveHandle.In); 25.687 +} 25.688 + 25.689 +static void WinMMStopCapture(ALCdevice *pDevice) 25.690 +{ 25.691 + WinMMData *pData = (WinMMData*)pDevice->ExtraData; 25.692 + waveInStop(pData->hWaveHandle.In); 25.693 +} 25.694 + 25.695 +static ALCuint WinMMAvailableSamples(ALCdevice *pDevice) 25.696 +{ 25.697 + WinMMData *pData = (WinMMData*)pDevice->ExtraData; 25.698 + return RingBufferSize(pData->pRing); 25.699 +} 25.700 + 25.701 +static void WinMMCaptureSamples(ALCdevice *pDevice, ALCvoid *pBuffer, ALCuint lSamples) 25.702 +{ 25.703 + WinMMData *pData = (WinMMData*)pDevice->ExtraData; 25.704 + 25.705 + if(WinMMAvailableSamples(pDevice) >= lSamples) 25.706 + ReadRingBuffer(pData->pRing, pBuffer, lSamples); 25.707 + else 25.708 + alcSetError(pDevice, ALC_INVALID_VALUE); 25.709 +} 25.710 + 25.711 + 25.712 +static const BackendFuncs WinMMFuncs = { 25.713 + WinMMOpenPlayback, 25.714 + WinMMClosePlayback, 25.715 + WinMMResetPlayback, 25.716 + WinMMStopPlayback, 25.717 + WinMMOpenCapture, 25.718 + WinMMCloseCapture, 25.719 + WinMMStartCapture, 25.720 + WinMMStopCapture, 25.721 + WinMMCaptureSamples, 25.722 + WinMMAvailableSamples 25.723 +}; 25.724 + 25.725 +ALCboolean alcWinMMInit(BackendFuncs *FuncList) 25.726 +{ 25.727 + *FuncList = WinMMFuncs; 25.728 + return ALC_TRUE; 25.729 +} 25.730 + 25.731 +void alcWinMMDeinit() 25.732 +{ 25.733 + ALuint lLoop; 25.734 + 25.735 + for(lLoop = 0;lLoop < NumPlaybackDevices;lLoop++) 25.736 + free(PlaybackDeviceList[lLoop]); 25.737 + free(PlaybackDeviceList); 25.738 + PlaybackDeviceList = NULL; 25.739 + 25.740 + NumPlaybackDevices = 0; 25.741 + 25.742 + 25.743 + for(lLoop = 0; lLoop < NumCaptureDevices; lLoop++) 25.744 + free(CaptureDeviceList[lLoop]); 25.745 + free(CaptureDeviceList); 25.746 + CaptureDeviceList = NULL; 25.747 + 25.748 + NumCaptureDevices = 0; 25.749 +} 25.750 + 25.751 +void alcWinMMProbe(enum DevProbe type) 25.752 +{ 25.753 + ALuint i; 25.754 + 25.755 + switch(type) 25.756 + { 25.757 + case DEVICE_PROBE: 25.758 + ProbePlaybackDevices(); 25.759 + if(NumPlaybackDevices > 0) 25.760 + AppendDeviceList(woDefault); 25.761 + break; 25.762 + 25.763 + case ALL_DEVICE_PROBE: 25.764 + ProbePlaybackDevices(); 25.765 + if(NumPlaybackDevices > 0) 25.766 + AppendAllDeviceList(woDefault); 25.767 + for(i = 0;i < NumPlaybackDevices;i++) 25.768 + { 25.769 + if(PlaybackDeviceList[i]) 25.770 + AppendAllDeviceList(PlaybackDeviceList[i]); 25.771 + } 25.772 + break; 25.773 + 25.774 + case CAPTURE_DEVICE_PROBE: 25.775 + ProbeCaptureDevices(); 25.776 + for(i = 0;i < NumCaptureDevices;i++) 25.777 + { 25.778 + if(CaptureDeviceList[i]) 25.779 + AppendCaptureDeviceList(CaptureDeviceList[i]); 25.780 + } 25.781 + break; 25.782 + } 25.783 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 26.2 +++ b/Alc/bs2b.c Tue Oct 25 13:02:31 2011 -0700 26.3 @@ -0,0 +1,201 @@ 26.4 +/*- 26.5 + * Copyright (c) 2005 Boris Mikhaylov 26.6 + * 26.7 + * Permission is hereby granted, free of charge, to any person obtaining 26.8 + * a copy of this software and associated documentation files (the 26.9 + * "Software"), to deal in the Software without restriction, including 26.10 + * without limitation the rights to use, copy, modify, merge, publish, 26.11 + * distribute, sublicense, and/or sell copies of the Software, and to 26.12 + * permit persons to whom the Software is furnished to do so, subject to 26.13 + * the following conditions: 26.14 + * 26.15 + * The above copyright notice and this permission notice shall be 26.16 + * included in all copies or substantial portions of the Software. 26.17 + * 26.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 26.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 26.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26.24 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26.25 + */ 26.26 + 26.27 +#include "config.h" 26.28 + 26.29 +#include <math.h> 26.30 + 26.31 +#include "bs2b.h" 26.32 + 26.33 +#ifndef M_PI 26.34 +#define M_PI 3.14159265358979323846 26.35 +#endif 26.36 + 26.37 +/* Single pole IIR filter. 26.38 + * O[n] = a0*I[n] + a1*I[n-1] + b1*O[n-1] 26.39 + */ 26.40 + 26.41 +/* Lowpass filter */ 26.42 +#define lo_filter(in, out_1) (bs2b->a0_lo*(in) + bs2b->b1_lo*(out_1)) 26.43 + 26.44 +/* Highboost filter */ 26.45 +#define hi_filter(in, in_1, out_1) (bs2b->a0_hi*(in) + bs2b->a1_hi*(in_1) + bs2b->b1_hi*(out_1)) 26.46 + 26.47 +/* Set up all data. */ 26.48 +static void init(struct bs2b *bs2b) 26.49 +{ 26.50 + double Fc_lo, Fc_hi; 26.51 + double G_lo, G_hi; 26.52 + double x; 26.53 + 26.54 + if ((bs2b->srate > 192000) || (bs2b->srate < 2000)) 26.55 + bs2b->srate = BS2B_DEFAULT_SRATE; 26.56 + 26.57 + switch(bs2b->level) 26.58 + { 26.59 + case BS2B_LOW_CLEVEL: /* Low crossfeed level */ 26.60 + Fc_lo = 360.0; 26.61 + Fc_hi = 501.0; 26.62 + G_lo = 0.398107170553497; 26.63 + G_hi = 0.205671765275719; 26.64 + break; 26.65 + 26.66 + case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */ 26.67 + Fc_lo = 500.0; 26.68 + Fc_hi = 711.0; 26.69 + G_lo = 0.459726988530872; 26.70 + G_hi = 0.228208484414988; 26.71 + break; 26.72 + 26.73 + case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */ 26.74 + Fc_lo = 700.0; 26.75 + Fc_hi = 1021.0; 26.76 + G_lo = 0.530884444230988; 26.77 + G_hi = 0.250105790667544; 26.78 + break; 26.79 + 26.80 + case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */ 26.81 + Fc_lo = 360.0; 26.82 + Fc_hi = 494.0; 26.83 + G_lo = 0.316227766016838; 26.84 + G_hi = 0.168236228897329; 26.85 + break; 26.86 + 26.87 + case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */ 26.88 + Fc_lo = 500.0; 26.89 + Fc_hi = 689.0; 26.90 + G_lo = 0.354813389233575; 26.91 + G_hi = 0.187169483835901; 26.92 + break; 26.93 + 26.94 + default: /* High easy crossfeed level */ 26.95 + bs2b->level = BS2B_HIGH_ECLEVEL; 26.96 + 26.97 + Fc_lo = 700.0; 26.98 + Fc_hi = 975.0; 26.99 + G_lo = 0.398107170553497; 26.100 + G_hi = 0.205671765275719; 26.101 + break; 26.102 + } /* switch */ 26.103 + 26.104 + /* $fc = $Fc / $s; 26.105 + * $d = 1 / 2 / pi / $fc; 26.106 + * $x = exp(-1 / $d); 26.107 + */ 26.108 + 26.109 + x = exp(-2.0 * M_PI * Fc_lo / bs2b->srate); 26.110 + bs2b->b1_lo = x; 26.111 + bs2b->a0_lo = G_lo * (1.0 - x); 26.112 + 26.113 + x = exp(-2.0 * M_PI * Fc_hi / bs2b->srate); 26.114 + bs2b->b1_hi = x; 26.115 + bs2b->a0_hi = 1.0 - G_hi * (1.0 - x); 26.116 + bs2b->a1_hi = -x; 26.117 + 26.118 + bs2b->gain = 1.0 / (1.0 - G_hi + G_lo); 26.119 +} /* init */ 26.120 + 26.121 +/* Exported functions. 26.122 + * See descriptions in "bs2b.h" 26.123 + */ 26.124 + 26.125 +void bs2b_set_level(struct bs2b *bs2b, int level) 26.126 +{ 26.127 + if(level == bs2b->level) 26.128 + return; 26.129 + bs2b->level = level; 26.130 + init(bs2b); 26.131 +} /* bs2b_set_level */ 26.132 + 26.133 +int bs2b_get_level(struct bs2b *bs2b) 26.134 +{ 26.135 + return bs2b->level; 26.136 +} /* bs2b_get_level */ 26.137 + 26.138 +void bs2b_set_srate(struct bs2b *bs2b, int srate) 26.139 +{ 26.140 + if (srate == bs2b->srate) 26.141 + return; 26.142 + bs2b->srate = srate; 26.143 + init(bs2b); 26.144 +} /* bs2b_set_srate */ 26.145 + 26.146 +int bs2b_get_srate(struct bs2b *bs2b) 26.147 +{ 26.148 + return bs2b->srate; 26.149 +} /* bs2b_get_srate */ 26.150 + 26.151 +void bs2b_clear(struct bs2b *bs2b) 26.152 +{ 26.153 + int loopv = sizeof(bs2b->last_sample); 26.154 + 26.155 + while (loopv) 26.156 + { 26.157 + ((char *)&bs2b->last_sample)[--loopv] = 0; 26.158 + } 26.159 +} /* bs2b_clear */ 26.160 + 26.161 +int bs2b_is_clear(struct bs2b *bs2b) 26.162 +{ 26.163 + int loopv = sizeof(bs2b->last_sample); 26.164 + 26.165 + while (loopv) 26.166 + { 26.167 + if (((char *)&bs2b->last_sample)[--loopv] != 0) 26.168 + return 0; 26.169 + } 26.170 + return 1; 26.171 +} /* bs2b_is_clear */ 26.172 + 26.173 +void bs2b_cross_feed(struct bs2b *bs2b, float *sample) 26.174 +{ 26.175 + /* Lowpass filter */ 26.176 + bs2b->last_sample.lo[0] = lo_filter(sample[0], bs2b->last_sample.lo[0]); 26.177 + bs2b->last_sample.lo[1] = lo_filter(sample[1], bs2b->last_sample.lo[1]); 26.178 + 26.179 + /* Highboost filter */ 26.180 + bs2b->last_sample.hi[0] = hi_filter(sample[0], bs2b->last_sample.asis[0], bs2b->last_sample.hi[0]); 26.181 + bs2b->last_sample.hi[1] = hi_filter(sample[1], bs2b->last_sample.asis[1], bs2b->last_sample.hi[1]); 26.182 + bs2b->last_sample.asis[0] = sample[0]; 26.183 + bs2b->last_sample.asis[1] = sample[1]; 26.184 + 26.185 + /* Crossfeed */ 26.186 + sample[0] = bs2b->last_sample.hi[0] + bs2b->last_sample.lo[1]; 26.187 + sample[1] = bs2b->last_sample.hi[1] + bs2b->last_sample.lo[0]; 26.188 + 26.189 + /* Bass boost cause allpass attenuation */ 26.190 + sample[0] *= bs2b->gain; 26.191 + sample[1] *= bs2b->gain; 26.192 + 26.193 + /* Clipping of overloaded samples */ 26.194 +#if 0 26.195 + if (sample[0] > 1.0) 26.196 + sample[0] = 1.0; 26.197 + if (sample[0] < -1.0) 26.198 + sample[0] = -1.0; 26.199 + if (sample[1] > 1.0) 26.200 + sample[1] = 1.0; 26.201 + if (sample[1] < -1.0) 26.202 + sample[1] = -1.0; 26.203 +#endif 26.204 +} /* bs2b_cross_feed */
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 27.2 +++ b/Alc/helpers.c Tue Oct 25 13:02:31 2011 -0700 27.3 @@ -0,0 +1,349 @@ 27.4 +/** 27.5 + * OpenAL cross platform audio library 27.6 + * Copyright (C) 2011 by authors. 27.7 + * This library is free software; you can redistribute it and/or 27.8 + * modify it under the terms of the GNU Library General Public 27.9 + * License as published by the Free Software Foundation; either 27.10 + * version 2 of the License, or (at your option) any later version. 27.11 + * 27.12 + * This library is distributed in the hope that it will be useful, 27.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 27.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27.15 + * Library General Public License for more details. 27.16 + * 27.17 + * You should have received a copy of the GNU Library General Public 27.18 + * License along with this library; if not, write to the 27.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 27.20 + * Boston, MA 02111-1307, USA. 27.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 27.22 + */ 27.23 + 27.24 +#include "config.h" 27.25 + 27.26 +#include <stdlib.h> 27.27 +#ifdef HAVE_DLFCN_H 27.28 +#include <dlfcn.h> 27.29 +#endif 27.30 + 27.31 +#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H) 27.32 +#define INITGUID 27.33 +#include <windows.h> 27.34 +#ifdef HAVE_GUIDDEF_H 27.35 +#include <guiddef.h> 27.36 +#else 27.37 +#include <initguid.h> 27.38 +#endif 27.39 + 27.40 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); 27.41 +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); 27.42 + 27.43 +DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x00,0xa0,0xc9,0x25,0xcd,0x16); 27.44 + 27.45 +DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e); 27.46 +DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6); 27.47 +DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2); 27.48 +DEFINE_GUID(IID_IAudioRenderClient, 0xf294acfc, 0x3146, 0x4483, 0xa7,0xbf, 0xad,0xdc,0xa7,0xc2,0x60,0xe2); 27.49 + 27.50 +#endif 27.51 + 27.52 +#include "alMain.h" 27.53 + 27.54 +#ifdef _WIN32 27.55 +void pthread_once(pthread_once_t *once, void (*callback)(void)) 27.56 +{ 27.57 + LONG ret; 27.58 + while((ret=InterlockedExchange(once, 1)) == 1) 27.59 + Sleep(0); 27.60 + if(ret == 0) 27.61 + callback(); 27.62 + InterlockedExchange(once, 2); 27.63 +} 27.64 + 27.65 +void *LoadLib(const char *name) 27.66 +{ return LoadLibraryA(name); } 27.67 +void CloseLib(void *handle) 27.68 +{ FreeLibrary((HANDLE)handle); } 27.69 +void *GetSymbol(void *handle, const char *name) 27.70 +{ 27.71 + void *ret; 27.72 + 27.73 + ret = (void*)GetProcAddress((HANDLE)handle, name); 27.74 + if(ret == NULL) 27.75 + ERR("Failed to load %s\n", name); 27.76 + return ret; 27.77 +} 27.78 + 27.79 +#else 27.80 + 27.81 +void InitializeCriticalSection(CRITICAL_SECTION *cs) 27.82 +{ 27.83 + pthread_mutexattr_t attrib; 27.84 + int ret; 27.85 + 27.86 + ret = pthread_mutexattr_init(&attrib); 27.87 + assert(ret == 0); 27.88 + 27.89 + ret = pthread_mutexattr_settype(&attrib, PTHREAD_MUTEX_RECURSIVE); 27.90 +#ifdef HAVE_PTHREAD_NP_H 27.91 + if(ret != 0) 27.92 + ret = pthread_mutexattr_setkind_np(&attrib, PTHREAD_MUTEX_RECURSIVE); 27.93 +#endif 27.94 + assert(ret == 0); 27.95 + ret = pthread_mutex_init(cs, &attrib); 27.96 + assert(ret == 0); 27.97 + 27.98 + pthread_mutexattr_destroy(&attrib); 27.99 +} 27.100 +void DeleteCriticalSection(CRITICAL_SECTION *cs) 27.101 +{ 27.102 + int ret; 27.103 + ret = pthread_mutex_destroy(cs); 27.104 + assert(ret == 0); 27.105 +} 27.106 +void EnterCriticalSection(CRITICAL_SECTION *cs) 27.107 +{ 27.108 + int ret; 27.109 + ret = pthread_mutex_lock(cs); 27.110 + assert(ret == 0); 27.111 +} 27.112 +void LeaveCriticalSection(CRITICAL_SECTION *cs) 27.113 +{ 27.114 + int ret; 27.115 + ret = pthread_mutex_unlock(cs); 27.116 + assert(ret == 0); 27.117 +} 27.118 + 27.119 +/* NOTE: This wrapper isn't quite accurate as it returns an ALuint, as opposed 27.120 + * to the expected DWORD. Both are defined as unsigned 32-bit types, however. 27.121 + * Additionally, Win32 is supposed to measure the time since Windows started, 27.122 + * as opposed to the actual time. */ 27.123 +ALuint timeGetTime(void) 27.124 +{ 27.125 +#if _POSIX_TIMERS > 0 27.126 + struct timespec ts; 27.127 + int ret = -1; 27.128 + 27.129 +#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK >= 0) 27.130 +#if _POSIX_MONOTONIC_CLOCK == 0 27.131 + static int hasmono = 0; 27.132 + if(hasmono > 0 || (hasmono == 0 && 27.133 + (hasmono=sysconf(_SC_MONOTONIC_CLOCK)) > 0)) 27.134 +#endif 27.135 + ret = clock_gettime(CLOCK_MONOTONIC, &ts); 27.136 +#endif 27.137 + if(ret != 0) 27.138 + ret = clock_gettime(CLOCK_REALTIME, &ts); 27.139 + assert(ret == 0); 27.140 + 27.141 + return ts.tv_nsec/1000000 + ts.tv_sec*1000; 27.142 +#else 27.143 + struct timeval tv; 27.144 + int ret; 27.145 + 27.146 + ret = gettimeofday(&tv, NULL); 27.147 + assert(ret == 0); 27.148 + 27.149 + return tv.tv_usec/1000 + tv.tv_sec*1000; 27.150 +#endif 27.151 +} 27.152 + 27.153 +#ifdef HAVE_DLFCN_H 27.154 + 27.155 +void *LoadLib(const char *name) 27.156 +{ 27.157 + const char *err; 27.158 + void *handle; 27.159 + 27.160 + dlerror(); 27.161 + handle = dlopen(name, RTLD_NOW); 27.162 + if((err=dlerror()) != NULL) 27.163 + handle = NULL; 27.164 + return handle; 27.165 +} 27.166 +void CloseLib(void *handle) 27.167 +{ dlclose(handle); } 27.168 +void *GetSymbol(void *handle, const char *name) 27.169 +{ 27.170 + const char *err; 27.171 + void *sym; 27.172 + 27.173 + dlerror(); 27.174 + sym = dlsym(handle, name); 27.175 + if((err=dlerror()) != NULL) 27.176 + { 27.177 + ERR("Failed to load %s: %s\n", name, err); 27.178 + sym = NULL; 27.179 + } 27.180 + return sym; 27.181 +} 27.182 + 27.183 +#endif 27.184 +#endif 27.185 + 27.186 + 27.187 +void al_print(const char *fname, unsigned int line, const char *fmt, ...) 27.188 +{ 27.189 + const char *fn; 27.190 + char str[256]; 27.191 + int i; 27.192 + 27.193 + fn = strrchr(fname, '/'); 27.194 + if(!fn) fn = strrchr(fname, '\\'); 27.195 + if(!fn) fn = fname; 27.196 + else fn += 1; 27.197 + 27.198 + i = snprintf(str, sizeof(str), "AL lib: %s:%d: ", fn, line); 27.199 + if(i < (int)sizeof(str) && i > 0) 27.200 + { 27.201 + va_list ap; 27.202 + va_start(ap, fmt); 27.203 + vsnprintf(str+i, sizeof(str)-i, fmt, ap); 27.204 + va_end(ap); 27.205 + } 27.206 + str[sizeof(str)-1] = 0; 27.207 + 27.208 + fprintf(LogFile, "%s", str); 27.209 + fflush(LogFile); 27.210 +} 27.211 + 27.212 + 27.213 +void SetRTPriority(void) 27.214 +{ 27.215 + ALboolean failed; 27.216 + 27.217 +#ifdef _WIN32 27.218 + if(RTPrioLevel > 0) 27.219 + failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); 27.220 + else 27.221 + failed = !SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL); 27.222 +#elif defined(HAVE_PTHREAD_SETSCHEDPARAM) && !defined(__OpenBSD__) 27.223 + struct sched_param param; 27.224 + 27.225 + if(RTPrioLevel > 0) 27.226 + { 27.227 + /* Use the minimum real-time priority possible for now (on Linux this 27.228 + * should be 1 for SCHED_RR) */ 27.229 + param.sched_priority = sched_get_priority_min(SCHED_RR); 27.230 + failed = !!pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); 27.231 + } 27.232 + else 27.233 + { 27.234 + param.sched_priority = 0; 27.235 + failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, ¶m); 27.236 + } 27.237 +#else 27.238 + /* Real-time priority not available */ 27.239 + failed = (RTPrioLevel>0); 27.240 +#endif 27.241 + if(failed) 27.242 + ERR("Failed to set priority level for thread\n"); 27.243 +} 27.244 + 27.245 + 27.246 +void InitUIntMap(UIntMap *map) 27.247 +{ 27.248 + map->array = NULL; 27.249 + map->size = 0; 27.250 + map->maxsize = 0; 27.251 +} 27.252 + 27.253 +void ResetUIntMap(UIntMap *map) 27.254 +{ 27.255 + free(map->array); 27.256 + map->array = NULL; 27.257 + map->size = 0; 27.258 + map->maxsize = 0; 27.259 +} 27.260 + 27.261 +ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value) 27.262 +{ 27.263 + ALsizei pos = 0; 27.264 + 27.265 + if(map->size > 0) 27.266 + { 27.267 + ALsizei low = 0; 27.268 + ALsizei high = map->size - 1; 27.269 + while(low < high) 27.270 + { 27.271 + ALsizei mid = low + (high-low)/2; 27.272 + if(map->array[mid].key < key) 27.273 + low = mid + 1; 27.274 + else 27.275 + high = mid; 27.276 + } 27.277 + if(map->array[low].key < key) 27.278 + low++; 27.279 + pos = low; 27.280 + } 27.281 + 27.282 + if(pos == map->size || map->array[pos].key != key) 27.283 + { 27.284 + if(map->size == map->maxsize) 27.285 + { 27.286 + ALvoid *temp; 27.287 + ALsizei newsize; 27.288 + 27.289 + newsize = (map->maxsize ? (map->maxsize<<1) : 4); 27.290 + if(newsize < map->maxsize) 27.291 + return AL_OUT_OF_MEMORY; 27.292 + 27.293 + temp = realloc(map->array, newsize*sizeof(map->array[0])); 27.294 + if(!temp) return AL_OUT_OF_MEMORY; 27.295 + map->array = temp; 27.296 + map->maxsize = newsize; 27.297 + } 27.298 + 27.299 + map->size++; 27.300 + if(pos < map->size-1) 27.301 + memmove(&map->array[pos+1], &map->array[pos], 27.302 + (map->size-1-pos)*sizeof(map->array[0])); 27.303 + } 27.304 + map->array[pos].key = key; 27.305 + map->array[pos].value = value; 27.306 + 27.307 + return AL_NO_ERROR; 27.308 +} 27.309 + 27.310 +void RemoveUIntMapKey(UIntMap *map, ALuint key) 27.311 +{ 27.312 + if(map->size > 0) 27.313 + { 27.314 + ALsizei low = 0; 27.315 + ALsizei high = map->size - 1; 27.316 + while(low < high) 27.317 + { 27.318 + ALsizei mid = low + (high-low)/2; 27.319 + if(map->array[mid].key < key) 27.320 + low = mid + 1; 27.321 + else 27.322 + high = mid; 27.323 + } 27.324 + if(map->array[low].key == key) 27.325 + { 27.326 + if(low < map->size-1) 27.327 + memmove(&map->array[low], &map->array[low+1], 27.328 + (map->size-1-low)*sizeof(map->array[0])); 27.329 + map->size--; 27.330 + } 27.331 + } 27.332 +} 27.333 + 27.334 +ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key) 27.335 +{ 27.336 + if(map->size > 0) 27.337 + { 27.338 + ALsizei low = 0; 27.339 + ALsizei high = map->size - 1; 27.340 + while(low < high) 27.341 + { 27.342 + ALsizei mid = low + (high-low)/2; 27.343 + if(map->array[mid].key < key) 27.344 + low = mid + 1; 27.345 + else 27.346 + high = mid; 27.347 + } 27.348 + if(map->array[low].key == key) 27.349 + return map->array[low].value; 27.350 + } 27.351 + return NULL; 27.352 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 28.2 +++ b/Alc/hrtf.c Tue Oct 25 13:02:31 2011 -0700 28.3 @@ -0,0 +1,412 @@ 28.4 +/** 28.5 + * OpenAL cross platform audio library 28.6 + * Copyright (C) 2011 by Chris Robinson 28.7 + * This library is free software; you can redistribute it and/or 28.8 + * modify it under the terms of the GNU Library General Public 28.9 + * License as published by the Free Software Foundation; either 28.10 + * version 2 of the License, or (at your option) any later version. 28.11 + * 28.12 + * This library is distributed in the hope that it will be useful, 28.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 28.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28.15 + * Library General Public License for more details. 28.16 + * 28.17 + * You should have received a copy of the GNU Library General Public 28.18 + * License along with this library; if not, write to the 28.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 28.20 + * Boston, MA 02111-1307, USA. 28.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 28.22 + */ 28.23 + 28.24 +#include "config.h" 28.25 + 28.26 +#include "AL/al.h" 28.27 +#include "AL/alc.h" 28.28 +#include "alMain.h" 28.29 +#include "alSource.h" 28.30 + 28.31 +/* External HRTF file format (LE byte order): 28.32 + * 28.33 + * ALchar magic[8] = "MinPHR00"; 28.34 + * ALuint sampleRate; 28.35 + * 28.36 + * ALushort hrirCount; // Required value: 828 28.37 + * ALushort hrirSize; // Required value: 32 28.38 + * ALubyte evCount; // Required value: 19 28.39 + * 28.40 + * ALushort evOffset[evCount]; // Required values: 28.41 + * { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 } 28.42 + * 28.43 + * ALushort coefficients[hrirCount][hrirSize]; 28.44 + * ALubyte delays[hrirCount]; // Element values must not exceed 127 28.45 + */ 28.46 + 28.47 +static const ALchar magicMarker[8] = "MinPHR00"; 28.48 + 28.49 +#define HRIR_COUNT 828 28.50 +#define ELEV_COUNT 19 28.51 + 28.52 +static const ALushort evOffset[ELEV_COUNT] = { 0, 1, 13, 37, 73, 118, 174, 234, 306, 378, 450, 522, 594, 654, 710, 755, 791, 815, 827 }; 28.53 +static const ALubyte azCount[ELEV_COUNT] = { 1, 12, 24, 36, 45, 56, 60, 72, 72, 72, 72, 72, 60, 56, 45, 36, 24, 12, 1 }; 28.54 + 28.55 +static struct Hrtf { 28.56 + ALuint sampleRate; 28.57 + ALshort coeffs[HRIR_COUNT][HRIR_LENGTH]; 28.58 + ALubyte delays[HRIR_COUNT]; 28.59 +} Hrtf = { 28.60 + 44100, 28.61 +#include "hrtf_tables.inc" 28.62 +}; 28.63 + 28.64 +// Calculate the elevation indices given the polar elevation in radians. 28.65 +// This will return two indices between 0 and (ELEV_COUNT-1) and an 28.66 +// interpolation factor between 0.0 and 1.0. 28.67 +static void CalcEvIndices(ALfloat ev, ALuint *evidx, ALfloat *evmu) 28.68 +{ 28.69 + ev = (M_PI/2.0f + ev) * (ELEV_COUNT-1) / M_PI; 28.70 + evidx[0] = (ALuint)ev; 28.71 + evidx[1] = minu(evidx[0] + 1, ELEV_COUNT-1); 28.72 + *evmu = ev - evidx[0]; 28.73 +} 28.74 + 28.75 +// Calculate the azimuth indices given the polar azimuth in radians. This 28.76 +// will return two indices between 0 and (azCount [ei] - 1) and an 28.77 +// interpolation factor between 0.0 and 1.0. 28.78 +static void CalcAzIndices(ALuint evidx, ALfloat az, ALuint *azidx, ALfloat *azmu) 28.79 +{ 28.80 + az = (M_PI*2.0f + az) * azCount[evidx] / (M_PI*2.0f); 28.81 + azidx[0] = (ALuint)az % azCount[evidx]; 28.82 + azidx[1] = (azidx[0] + 1) % azCount[evidx]; 28.83 + *azmu = az - floor(az); 28.84 +} 28.85 + 28.86 +// Calculates the normalized HRTF transition factor (delta) from the changes 28.87 +// in gain and listener to source angle between updates. The result is a 28.88 +// normalized delta factor than can be used to calculate moving HRIR stepping 28.89 +// values. 28.90 +ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]) 28.91 +{ 28.92 + ALfloat gainChange, angleChange; 28.93 + 28.94 + // Calculate the normalized dB gain change. 28.95 + newGain = maxf(newGain, 0.0001f); 28.96 + oldGain = maxf(oldGain, 0.0001f); 28.97 + gainChange = aluFabs(log10(newGain / oldGain) / log10(0.0001f)); 28.98 + 28.99 + // Calculate the normalized listener to source angle change when there is 28.100 + // enough gain to notice it. 28.101 + angleChange = 0.0f; 28.102 + if(gainChange > 0.0001f || newGain > 0.0001f) 28.103 + { 28.104 + // No angle change when the directions are equal or degenerate (when 28.105 + // both have zero length). 28.106 + if(newdir[0]-olddir[0] || newdir[1]-olddir[1] || newdir[2]-olddir[2]) 28.107 + angleChange = aluAcos(olddir[0]*newdir[0] + 28.108 + olddir[1]*newdir[1] + 28.109 + olddir[2]*newdir[2]) / M_PI; 28.110 + 28.111 + } 28.112 + 28.113 + // Use the largest of the two changes for the delta factor, and apply a 28.114 + // significance shaping function to it. 28.115 + return clampf(angleChange*2.0f, gainChange*2.0f, 1.0f); 28.116 +} 28.117 + 28.118 +// Calculates static HRIR coefficients and delays for the given polar 28.119 +// elevation and azimuth in radians. Linear interpolation is used to 28.120 +// increase the apparent resolution of the HRIR dataset. The coefficients 28.121 +// are also normalized and attenuated by the specified gain. 28.122 +void GetLerpedHrtfCoeffs(ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays) 28.123 +{ 28.124 + ALuint evidx[2], azidx[2]; 28.125 + ALfloat mu[3]; 28.126 + ALuint lidx[4], ridx[4]; 28.127 + ALuint i; 28.128 + 28.129 + // Claculate elevation indices and interpolation factor. 28.130 + CalcEvIndices(elevation, evidx, &mu[2]); 28.131 + 28.132 + // Calculate azimuth indices and interpolation factor for the first 28.133 + // elevation. 28.134 + CalcAzIndices(evidx[0], azimuth, azidx, &mu[0]); 28.135 + 28.136 + // Calculate the first set of linear HRIR indices for left and right 28.137 + // channels. 28.138 + lidx[0] = evOffset[evidx[0]] + azidx[0]; 28.139 + lidx[1] = evOffset[evidx[0]] + azidx[1]; 28.140 + ridx[0] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[0]) % azCount[evidx[0]]); 28.141 + ridx[1] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[1]) % azCount[evidx[0]]); 28.142 + 28.143 + // Calculate azimuth indices and interpolation factor for the second 28.144 + // elevation. 28.145 + CalcAzIndices(evidx[1], azimuth, azidx, &mu[1]); 28.146 + 28.147 + // Calculate the second set of linear HRIR indices for left and right 28.148 + // channels. 28.149 + lidx[2] = evOffset[evidx[1]] + azidx[0]; 28.150 + lidx[3] = evOffset[evidx[1]] + azidx[1]; 28.151 + ridx[2] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[0]) % azCount[evidx[1]]); 28.152 + ridx[3] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[1]) % azCount[evidx[1]]); 28.153 + 28.154 + // Calculate the normalized and attenuated HRIR coefficients using linear 28.155 + // interpolation when there is enough gain to warrant it. Zero the 28.156 + // coefficients if gain is too low. 28.157 + if(gain > 0.0001f) 28.158 + { 28.159 + ALdouble scale = gain * (1.0/32767.0); 28.160 + for(i = 0;i < HRIR_LENGTH;i++) 28.161 + { 28.162 + coeffs[i][0] = lerp(lerp(Hrtf.coeffs[lidx[0]][i], Hrtf.coeffs[lidx[1]][i], mu[0]), 28.163 + lerp(Hrtf.coeffs[lidx[2]][i], Hrtf.coeffs[lidx[3]][i], mu[1]), 28.164 + mu[2]) * scale; 28.165 + coeffs[i][1] = lerp(lerp(Hrtf.coeffs[ridx[0]][i], Hrtf.coeffs[ridx[1]][i], mu[0]), 28.166 + lerp(Hrtf.coeffs[ridx[2]][i], Hrtf.coeffs[ridx[3]][i], mu[1]), 28.167 + mu[2]) * scale; 28.168 + } 28.169 + } 28.170 + else 28.171 + { 28.172 + for(i = 0;i < HRIR_LENGTH;i++) 28.173 + { 28.174 + coeffs[i][0] = 0.0f; 28.175 + coeffs[i][1] = 0.0f; 28.176 + } 28.177 + } 28.178 + 28.179 + // Calculate the HRIR delays using linear interpolation. 28.180 + delays[0] = (ALuint)(lerp(lerp(Hrtf.delays[lidx[0]], Hrtf.delays[lidx[1]], mu[0]), 28.181 + lerp(Hrtf.delays[lidx[2]], Hrtf.delays[lidx[3]], mu[1]), 28.182 + mu[2]) * 65536.0f); 28.183 + delays[1] = (ALuint)(lerp(lerp(Hrtf.delays[ridx[0]], Hrtf.delays[ridx[1]], mu[0]), 28.184 + lerp(Hrtf.delays[ridx[2]], Hrtf.delays[ridx[3]], mu[1]), 28.185 + mu[2]) * 65536.0f); 28.186 +} 28.187 + 28.188 +// Calculates the moving HRIR target coefficients, target delays, and 28.189 +// stepping values for the given polar elevation and azimuth in radians. 28.190 +// Linear interpolation is used to increase the apparent resolution of the 28.191 +// HRIR dataset. The coefficients are also normalized and attenuated by the 28.192 +// specified gain. Stepping resolution and count is determined using the 28.193 +// given delta factor between 0.0 and 1.0. 28.194 +ALuint GetMovingHrtfCoeffs(ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep) 28.195 +{ 28.196 + ALuint evidx[2], azidx[2]; 28.197 + ALuint lidx[4], ridx[4]; 28.198 + ALfloat left, right; 28.199 + ALfloat mu[3]; 28.200 + ALfloat step; 28.201 + ALuint i; 28.202 + 28.203 + // Claculate elevation indices and interpolation factor. 28.204 + CalcEvIndices(elevation, evidx, &mu[2]); 28.205 + 28.206 + // Calculate azimuth indices and interpolation factor for the first 28.207 + // elevation. 28.208 + CalcAzIndices(evidx[0], azimuth, azidx, &mu[0]); 28.209 + 28.210 + // Calculate the first set of linear HRIR indices for left and right 28.211 + // channels. 28.212 + lidx[0] = evOffset[evidx[0]] + azidx[0]; 28.213 + lidx[1] = evOffset[evidx[0]] + azidx[1]; 28.214 + ridx[0] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[0]) % azCount[evidx[0]]); 28.215 + ridx[1] = evOffset[evidx[0]] + ((azCount[evidx[0]]-azidx[1]) % azCount[evidx[0]]); 28.216 + 28.217 + // Calculate azimuth indices and interpolation factor for the second 28.218 + // elevation. 28.219 + CalcAzIndices(evidx[1], azimuth, azidx, &mu[1]); 28.220 + 28.221 + // Calculate the second set of linear HRIR indices for left and right 28.222 + // channels. 28.223 + lidx[2] = evOffset[evidx[1]] + azidx[0]; 28.224 + lidx[3] = evOffset[evidx[1]] + azidx[1]; 28.225 + ridx[2] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[0]) % azCount[evidx[1]]); 28.226 + ridx[3] = evOffset[evidx[1]] + ((azCount[evidx[1]]-azidx[1]) % azCount[evidx[1]]); 28.227 + 28.228 + // Calculate the stepping parameters. 28.229 + delta = maxf(floor(delta*(Hrtf.sampleRate*0.015f) + 0.5), 1.0f); 28.230 + step = 1.0f / delta; 28.231 + 28.232 + // Calculate the normalized and attenuated target HRIR coefficients using 28.233 + // linear interpolation when there is enough gain to warrant it. Zero 28.234 + // the target coefficients if gain is too low. Then calculate the 28.235 + // coefficient stepping values using the target and previous running 28.236 + // coefficients. 28.237 + if(gain > 0.0001f) 28.238 + { 28.239 + ALdouble scale = gain * (1.0/32767.0); 28.240 + for(i = 0;i < HRIR_LENGTH;i++) 28.241 + { 28.242 + left = coeffs[i][0] - (coeffStep[i][0] * counter); 28.243 + right = coeffs[i][1] - (coeffStep[i][1] * counter); 28.244 + 28.245 + coeffs[i][0] = lerp(lerp(Hrtf.coeffs[lidx[0]][i], Hrtf.coeffs[lidx[1]][i], mu[0]), 28.246 + lerp(Hrtf.coeffs[lidx[2]][i], Hrtf.coeffs[lidx[3]][i], mu[1]), 28.247 + mu[2]) * scale; 28.248 + coeffs[i][1] = lerp(lerp(Hrtf.coeffs[ridx[0]][i], Hrtf.coeffs[ridx[1]][i], mu[0]), 28.249 + lerp(Hrtf.coeffs[ridx[2]][i], Hrtf.coeffs[ridx[3]][i], mu[1]), 28.250 + mu[2]) * scale; 28.251 + 28.252 + coeffStep[i][0] = step * (coeffs[i][0] - left); 28.253 + coeffStep[i][1] = step * (coeffs[i][1] - right); 28.254 + } 28.255 + } 28.256 + else 28.257 + { 28.258 + for(i = 0;i < HRIR_LENGTH;i++) 28.259 + { 28.260 + left = coeffs[i][0] - (coeffStep[i][0] * counter); 28.261 + right = coeffs[i][1] - (coeffStep[i][1] * counter); 28.262 + 28.263 + coeffs[i][0] = 0.0f; 28.264 + coeffs[i][1] = 0.0f; 28.265 + 28.266 + coeffStep[i][0] = step * -left; 28.267 + coeffStep[i][1] = step * -right; 28.268 + } 28.269 + } 28.270 + 28.271 + // Calculate the HRIR delays using linear interpolation. Then calculate 28.272 + // the delay stepping values using the target and previous running 28.273 + // delays. 28.274 + left = delays[0] - (delayStep[0] * counter); 28.275 + right = delays[1] - (delayStep[1] * counter); 28.276 + 28.277 + delays[0] = (ALuint)(lerp(lerp(Hrtf.delays[lidx[0]], Hrtf.delays[lidx[1]], mu[0]), 28.278 + lerp(Hrtf.delays[lidx[2]], Hrtf.delays[lidx[3]], mu[1]), 28.279 + mu[2]) * 65536.0f); 28.280 + delays[1] = (ALuint)(lerp(lerp(Hrtf.delays[ridx[0]], Hrtf.delays[ridx[1]], mu[0]), 28.281 + lerp(Hrtf.delays[ridx[2]], Hrtf.delays[ridx[3]], mu[1]), 28.282 + mu[2]) * 65536.0f); 28.283 + 28.284 + delayStep[0] = (ALint)(step * (delays[0] - left)); 28.285 + delayStep[1] = (ALint)(step * (delays[1] - right)); 28.286 + 28.287 + // The stepping count is the number of samples necessary for the HRIR to 28.288 + // complete its transition. The mixer will only apply stepping for this 28.289 + // many samples. 28.290 + return (ALuint)delta; 28.291 +} 28.292 + 28.293 +ALCboolean IsHrtfCompatible(ALCdevice *device) 28.294 +{ 28.295 + if(device->FmtChans == DevFmtStereo && device->Frequency == Hrtf.sampleRate) 28.296 + return ALC_TRUE; 28.297 + ERR("Incompatible HRTF format: %s %uhz (%s %uhz needed)\n", 28.298 + DevFmtChannelsString(device->FmtChans), device->Frequency, 28.299 + DevFmtChannelsString(DevFmtStereo), Hrtf.sampleRate); 28.300 + return ALC_FALSE; 28.301 +} 28.302 + 28.303 +void InitHrtf(void) 28.304 +{ 28.305 + const char *fname; 28.306 + FILE *f = NULL; 28.307 + 28.308 + fname = GetConfigValue(NULL, "hrtf_tables", ""); 28.309 + if(fname[0] != '\0') 28.310 + { 28.311 + f = fopen(fname, "rb"); 28.312 + if(f == NULL) 28.313 + ERR("Could not open %s\n", fname); 28.314 + } 28.315 + if(f != NULL) 28.316 + { 28.317 + const ALubyte maxDelay = SRC_HISTORY_LENGTH-1; 28.318 + ALboolean failed = AL_FALSE; 28.319 + struct Hrtf newdata; 28.320 + ALchar magic[9]; 28.321 + ALsizei i, j; 28.322 + 28.323 + if(fread(magic, 1, sizeof(magicMarker), f) != sizeof(magicMarker)) 28.324 + { 28.325 + ERR("Failed to read magic marker\n"); 28.326 + failed = AL_TRUE; 28.327 + } 28.328 + else if(memcmp(magic, magicMarker, sizeof(magicMarker)) != 0) 28.329 + { 28.330 + magic[8] = 0; 28.331 + ERR("Invalid magic marker: \"%s\"\n", magic); 28.332 + failed = AL_TRUE; 28.333 + } 28.334 + 28.335 + if(!failed) 28.336 + { 28.337 + ALushort hrirCount, hrirSize; 28.338 + ALubyte evCount; 28.339 + 28.340 + newdata.sampleRate = fgetc(f); 28.341 + newdata.sampleRate |= fgetc(f)<<8; 28.342 + newdata.sampleRate |= fgetc(f)<<16; 28.343 + newdata.sampleRate |= fgetc(f)<<24; 28.344 + 28.345 + hrirCount = fgetc(f); 28.346 + hrirCount |= fgetc(f)<<8; 28.347 + 28.348 + hrirSize = fgetc(f); 28.349 + hrirSize |= fgetc(f)<<8; 28.350 + 28.351 + evCount = fgetc(f); 28.352 + 28.353 + if(hrirCount != HRIR_COUNT || hrirSize != HRIR_LENGTH || evCount != ELEV_COUNT) 28.354 + { 28.355 + ERR("Unsupported value: hrirCount=%d (%d), hrirSize=%d (%d), evCount=%d (%d)\n", 28.356 + hrirCount, HRIR_COUNT, hrirSize, HRIR_LENGTH, evCount, ELEV_COUNT); 28.357 + failed = AL_TRUE; 28.358 + } 28.359 + } 28.360 + 28.361 + if(!failed) 28.362 + { 28.363 + for(i = 0;i < HRIR_COUNT;i++) 28.364 + { 28.365 + ALushort offset; 28.366 + offset = fgetc(f); 28.367 + offset |= fgetc(f)<<8; 28.368 + if(offset != evOffset[i]) 28.369 + { 28.370 + ERR("Unsupported evOffset[%d] value: %d (%d)\n", i, offset, evOffset[i]); 28.371 + failed = AL_TRUE; 28.372 + } 28.373 + } 28.374 + } 28.375 + 28.376 + if(!failed) 28.377 + { 28.378 + for(i = 0;i < HRIR_COUNT;i++) 28.379 + { 28.380 + for(j = 0;j < HRIR_LENGTH;j++) 28.381 + { 28.382 + ALshort coeff; 28.383 + coeff = fgetc(f); 28.384 + coeff |= fgetc(f)<<8; 28.385 + newdata.coeffs[i][j] = coeff; 28.386 + } 28.387 + } 28.388 + for(i = 0;i < HRIR_COUNT;i++) 28.389 + { 28.390 + ALubyte delay; 28.391 + delay = fgetc(f); 28.392 + newdata.delays[i] = delay; 28.393 + if(delay > maxDelay) 28.394 + { 28.395 + ERR("Invalid delay[%d]: %d (%d)\n", i, delay, maxDelay); 28.396 + failed = AL_TRUE; 28.397 + } 28.398 + } 28.399 + 28.400 + if(feof(f)) 28.401 + { 28.402 + ERR("Premature end of data\n"); 28.403 + failed = AL_TRUE; 28.404 + } 28.405 + } 28.406 + 28.407 + fclose(f); 28.408 + f = NULL; 28.409 + 28.410 + if(!failed) 28.411 + Hrtf = newdata; 28.412 + else 28.413 + ERR("Failed to load %s\n", fname); 28.414 + } 28.415 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 29.2 +++ b/Alc/hrtf_tables.inc Tue Oct 25 13:02:31 2011 -0700 29.3 @@ -0,0 +1,839 @@ 29.4 +/* This data is Copyright 1994 by the MIT Media Laboratory. It is provided free 29.5 + * with no restrictions on use, provided the authors are cited when the data is 29.6 + * used in any research or commercial application. */ 29.7 +/* Bill Gardner <billg@media.mit.edu> and Keith Martin <kdm@media.mit.edu> */ 29.8 + 29.9 + /* HRIR Coefficients */ 29.10 + { 29.11 + { +5817, +7833, +3253, +2795, +1080, +403, +948, -690, -2207, -1110, +658, -33, -481, -949, -839, -287, -146, -103, +7, -47, -269, -105, -316, -221, -304, -497, -373, -231, -114, -14, +66, -62, }, 29.12 + { +6586, +8107, +2781, +3167, +1095, +99, +922, -641, -2255, -1457, +602, +170, -469, -781, -818, -773, -258, +8, -111, -125, -368, -216, -345, -265, -298, -447, -408, -158, -22, +0, +63, -96, }, 29.13 + { +5986, +7570, +2713, +2756, +1080, +403, +921, -758, -2112, -1067, +565, -93, -431, -738, -604, -361, -238, +10, +63, -88, -302, -101, -306, -243, -358, -488, -341, -224, -98, -1, +79, -55, }, 29.14 + { +5571, +7005, +2499, +2549, +974, +438, +959, -688, -1966, -793, +755, -35, -305, -631, -545, -165, -118, -72, +26, -36, -228, -36, -253, -158, -261, -436, -311, -197, -85, +11, +82, -47, }, 29.15 + { +5472, +6865, +2460, +2524, +978, +492, +1057, -561, -1857, -706, +813, -3, -353, -739, -587, -120, -98, -94, +21, -32, -228, -31, -232, -119, -204, -399, -293, -197, -124, -45, +34, -81, }, 29.16 + { +5627, +7081, +2487, +2449, +858, +396, +981, -676, -2051, -899, +820, +82, -332, -774, -643, -127, -26, -14, +72, +27, -183, -16, -234, -142, -240, -422, -289, -151, -36, +63, +108, -65, }, 29.17 + { +6172, +7677, +2541, +2564, +874, +397, +966, -927, -2421, -1117, +905, +38, -545, -990, -785, -200, -66, -60, +50, +17, -244, -35, -244, -146, -246, -433, -290, -139, -42, +40, +108, -37, }, 29.18 + { +6521, +8320, +2827, +2690, +909, +230, +917, -1084, -2525, -1115, +652, -122, -480, -974, -823, -289, -150, +21, +73, -58, -296, -90, -299, -198, -317, -480, -327, -206, -64, +25, +103, -47, }, 29.19 + { +6956, +8505, +2738, +3040, +1131, +209, +719, -1389, -2419, -516, +530, -857, -697, -801, -443, -77, -328, -117, +128, -70, -281, -49, -356, -233, -419, -579, -344, -271, -169, -16, +76, -98, }, 29.20 + { +7928, +9215, +2040, +2470, +595, +264, +1348, -1308, -2698, -258, +1302, -836, -1179, -1210, -483, +125, -403, -370, +81, -61, -416, -45, -378, -208, -426, -708, -383, -223, -150, -20, +82, -119, }, 29.21 + { +8205, +9593, +2241, +2306, +197, +241, +1480, -1080, -3081, -704, +1757, -153, -1144, -1906, -912, +311, -4, -441, -129, -99, -476, -104, -467, -207, -379, -660, -412, -194, -106, -31, +48, -172, }, 29.22 + { +7822, +9388, +3008, +2690, +349, +155, +1066, -976, -3351, -1396, +1366, +202, -165, -1794, -1686, +63, +209, -110, -81, -164, -375, -114, -487, -174, -394, -771, -456, -312, -109, +27, +100, -71, }, 29.23 + { +7342, +9001, +2833, +2968, +859, +118, +830, -1009, -2609, -1583, +1030, +177, -566, -888, -1564, -882, +55, +78, +62, +48, -275, -224, -531, -354, -242, -534, -487, -241, -107, +31, +92, -76, }, 29.24 + { +7420, +8277, +2251, +3723, +1049, -308, +945, -518, -2311, -1945, +592, +496, -502, -565, -848, -1420, -265, +189, -293, -192, -468, -339, -342, -319, -275, -379, -474, -58, +77, -10, +55, -134, }, 29.25 + { +6584, +7746, +2495, +3374, +1000, -52, +897, -756, -2030, -1406, +280, +34, -398, -477, -456, -856, -571, +107, +104, -158, -435, -199, -286, -253, -345, -425, -316, -178, -107, -66, +74, -62, }, 29.26 + { +6049, +7215, +2251, +2809, +1129, +395, +858, -790, -1953, -1091, +399, -101, -343, -474, -371, -537, -334, +183, +103, -155, -328, -94, -287, -281, -418, -457, -307, -226, -82, +10, +91, -45, }, 29.27 + { +5611, +6654, +2026, +2614, +1122, +421, +846, -730, -1795, -787, +486, -181, -199, -331, -331, -290, -184, +57, +64, -94, -264, -59, -241, -160, -276, -381, -321, -242, -63, +33, +98, -44, }, 29.28 + { +5099, +6036, +1921, +2401, +945, +508, +937, -640, -1638, -506, +755, -23, -74, -266, -268, -108, -114, -39, +41, -26, -172, +33, -185, -102, -220, -366, -254, -174, -58, +33, +94, -28, }, 29.29 + { +4863, +5622, +1644, +2154, +818, +547, +1098, -307, -1280, -210, +982, +96, -111, -376, -319, -58, -43, -22, +51, -10, -188, -3, -174, -47, -165, -316, -201, -114, -14, +20, +16, -134, }, 29.30 + { +4874, +5742, +1871, +2357, +961, +630, +1147, -376, -1424, -337, +863, +34, -193, -499, -332, +8, -81, -97, +36, -13, -175, +46, -137, -17, -102, -297, -226, -178, -147, -83, +1, -91, }, 29.31 + { +4960, +5827, +1797, +2194, +842, +622, +1162, -376, -1492, -421, +910, +56, -246, -568, -430, +32, +120, +83, +106, +18, -182, -19, -208, -85, -152, -240, -94, -64, -84, -82, -30, -123, }, 29.32 + { +5228, +6194, +1872, +2175, +707, +445, +1001, -617, -1837, -723, +933, +227, -167, -586, -451, +10, +86, +68, +127, +106, -88, +66, -146, -70, -175, -339, -208, -74, +41, +139, +139, -76, }, 29.33 + { +5697, +6722, +1953, +2283, +727, +469, +969, -882, -2258, -1037, +972, +175, -413, -806, -593, -28, +130, +87, +177, +163, -115, +43, -180, -84, -142, -297, -156, -24, +4, +49, +85, -29, }, 29.34 + { +6473, +7408, +1826, +2417, +711, +442, +966, -1188, -2613, -1118, +1193, +107, -644, -1020, -716, -117, +16, -26, +92, +89, -223, +39, -164, -76, -190, -362, -208, -46, +24, +86, +145, -12, }, 29.35 + { +7101, +8208, +1841, +2445, +711, +357, +985, -1505, -2879, -1121, +1181, +70, -658, -1173, -814, -168, -29, +29, +47, +36, -265, -40, -293, -166, -283, -429, -229, -63, +43, +81, +160, -20, }, 29.36 + { +7271, +8783, +2298, +2617, +755, +48, +900, -1532, -2806, -1083, +615, -189, -449, -1001, -807, -311, -150, +184, +122, -88, -322, -71, -273, -179, -335, -451, -278, -188, -9, +60, +138, -32, }, 29.37 + { +7519, +8972, +2519, +3099, +1077, -70, +527, -1818, -2665, -568, +208, -889, -424, -657, -398, -291, -483, +67, +222, -56, -219, -19, -307, -204, -436, -529, -306, -304, -126, +27, +128, -48, }, 29.38 + { +8267, +9086, +2039, +3441, +1167, -66, +449, -2175, -2478, +261, +170, -1844, -741, -537, +19, +68, -620, -86, +289, -131, -285, +19, -414, -244, -560, -647, -289, -330, -230, -5, +89, -141, }, 29.39 + { +9334, +10020, +1039, +2681, +800, -36, +1253, -2153, -2906, +675, +921, -2082, -1336, -748, +118, +362, -708, -352, +305, -89, -430, +16, -461, -267, -609, -817, -292, -288, -287, -70, +134, -107, }, 29.40 + { +10490, +10443, +234, +2319, +106, +215, +1880, -2162, -3146, +928, +1870, -2011, -1861, -1339, +44, +548, -846, -647, +252, -93, -597, +65, -464, -180, -581, -943, -344, -209, -200, -20, +104, -191, }, 29.41 + { +11090, +10859, +176, +1929, -492, +415, +2257, -1899, -3660, +617, +2693, -1436, -2083, -2245, -339, +944, -576, -854, +49, -173, -603, +64, -607, -194, -525, -910, -310, -113, -162, +10, +55, -268, }, 29.42 + { +11123, +11231, +589, +1885, -762, +272, +2193, -1677, -4087, +10, +3036, -569, -1972, -2950, -747, +1099, +20, -922, -216, -122, -721, -53, -651, -153, -474, -845, -423, -135, -107, -57, +30, -304, }, 29.43 + { +10803, +11222, +1474, +2265, -883, +91, +1845, -1667, -4470, -728, +2793, +190, -972, -3366, -1480, +1091, +471, -617, -486, -175, -639, -113, -591, -51, -507, -934, -502, -309, -106, -118, +53, -177, }, 29.44 + { +10246, +10868, +2402, +2554, -531, +31, +1268, -1323, -4728, -1500, +2335, +359, +174, -2966, -2559, +743, +585, -219, -198, -287, -474, -103, -696, -72, -517, -1094, -493, -391, -81, +78, +133, -87, }, 29.45 + { +9638, +10459, +2554, +3136, -109, -170, +1213, -1306, -4339, -2094, +2099, +264, +202, -1798, -3312, -170, +781, +126, +63, -260, -424, +20, -759, -504, -338, -983, -510, -236, -85, +153, +125, -96, }, 29.46 + { +9150, +10114, +2114, +3243, +563, -199, +731, -1335, -3018, -2131, +1610, +397, -733, -785, -2524, -1463, +491, +266, +80, +156, -304, -383, -768, -471, -118, -592, -631, -225, -95, +87, +113, -96, }, 29.47 + { +8454, +9243, +2047, +3497, +881, -249, +701, -1042, -2617, -2062, +1294, +712, -942, -676, -1397, -1797, -57, +250, -231, -14, -250, -237, -521, -454, -179, -387, -649, -192, -30, +13, +161, -121, }, 29.48 + { +8323, +8323, +1685, +4494, +893, -823, +1049, -315, -2397, -2598, +672, +957, -622, -284, -950, -2240, -109, +425, -567, -229, -570, -475, -300, -391, -228, -295, -579, +83, +176, -48, +44, -175, }, 29.49 + { +7274, +7900, +2262, +4107, +785, -714, +918, -662, -1986, -1894, +51, +378, -372, -108, -420, -1664, -750, +303, +73, -176, -577, -344, -248, -256, -255, -331, -406, -129, -13, -101, +50, -88, }, 29.50 + { +6560, +7256, +2146, +3528, +960, -9, +858, -751, -1783, -1572, +54, +101, -313, -181, -229, -1133, -648, +400, +128, -265, -444, -160, -232, -331, -449, -399, -265, -206, -153, -62, +116, -28, }, 29.51 + { +5980, +6790, +1905, +2935, +1217, +364, +757, -764, -1730, -1213, +165, -24, -228, -158, -154, -831, -410, +428, +110, -247, -340, -86, -256, -338, -480, -399, -278, -238, -61, +18, +103, -30, }, 29.52 + { +5480, +6206, +1692, +2736, +1300, +391, +709, -692, -1565, -861, +226, -147, -68, -24, -127, -550, -217, +281, +49, -181, -257, -43, -247, -249, -345, -298, -274, -270, -50, +56, +119, -43, }, 29.53 + { +4953, +5620, +1632, +2478, +1119, +519, +800, -639, -1430, -598, +380, -73, +141, +70, -109, -295, -151, +126, +65, -105, -195, +54, -97, -104, -271, -314, -265, -208, -14, +48, +99, +5, }, 29.54 + { +4358, +4972, +1588, +2310, +986, +595, +869, -526, -1223, -277, +652, +34, +216, +141, -22, -120, -122, +1, +49, -14, -101, +99, -108, -54, -180, -284, -207, -160, -31, +53, +104, -2, }, 29.55 + { +4049, +4526, +1367, +2016, +774, +619, +1057, -193, -943, +8, +975, +238, +224, +73, -43, -96, -105, -16, +104, +54, -140, +64, -50, +12, -174, -276, -142, -78, +11, +66, +70, -116, }, 29.56 + { +3893, +4241, +1180, +1972, +964, +806, +1165, +33, -630, +212, +995, +139, -10, -165, -98, +59, +41, +7, +5, -42, -115, +70, -77, +64, -30, -184, -140, -90, -15, -39, -72, -166, }, 29.57 + { +3974, +4515, +1563, +2245, +1024, +802, +1202, -117, -913, -34, +802, +109, -1, -233, -83, +92, -89, -104, +51, +9, -107, +121, -30, +82, +5, -192, -173, -173, -183, -127, -31, -91, }, 29.58 + { +4054, +4585, +1487, +2101, +966, +877, +1249, -118, -989, -177, +776, +97, -55, -258, -131, +135, +150, +93, +56, -19, -114, +43, -129, +22, -1, -45, +2, -139, -203, -156, -63, -102, }, 29.59 + { +4259, +4784, +1375, +1894, +699, +649, +1161, -136, -1098, -231, +956, +281, +11, -419, -371, +109, +241, +228, +268, +110, -100, +71, -147, -93, -92, -157, -42, +95, +87, -12, -90, -205, }, 29.60 + { +4579, +5216, +1470, +1933, +626, +538, +991, -498, -1568, -608, +1002, +425, +4, -387, -268, +119, +196, +143, +174, +193, +16, +138, -48, -8, -110, -248, -134, +1, +116, +214, +157, -94, }, 29.61 + { +5066, +5749, +1521, +2044, +640, +538, +926, -811, -2022, -949, +1051, +371, -252, -591, -377, +160, +302, +178, +234, +199, -60, +136, -88, +2, -40, -201, -104, +47, +67, +67, +148, +54, }, 29.62 + { +5824, +6357, +1417, +2188, +604, +584, +938, -1093, -2439, -1140, +1270, +283, -550, -828, -547, +25, +209, +96, +231, +241, -75, +150, -72, -37, -72, -173, -85, +78, +65, +65, +106, -26, }, 29.63 + { +6705, +7034, +1139, +2353, +584, +531, +931, -1467, -2777, -1121, +1528, +169, -787, -1030, -630, -42, +104, -4, +133, +171, -212, +119, -74, -14, -133, -284, -130, +49, +82, +127, +179, +14, }, 29.64 + { +7494, +7838, +930, +2406, +628, +447, +939, -1854, -3086, -1058, +1655, +110, -889, -1206, -690, -58, +26, -36, +86, +157, -264, +21, -209, -75, -225, -353, -152, +18, +88, +139, +234, +25, }, 29.65 + { +7942, +8659, +1161, +2413, +549, +251, +1028, -2079, -3182, -1091, +1258, +58, -663, -1281, -862, -154, +30, +213, +47, +25, -289, -45, -300, -173, -306, -391, -167, -32, +123, +117, +202, -22, }, 29.66 + { +8068, +9218, +1660, +2593, +617, -151, +900, -2038, -3036, -1021, +535, -219, -391, -1036, -790, -354, -141, +391, +141, -138, -345, -47, -238, -167, -360, -407, -230, -180, +55, +90, +173, -18, }, 29.67 + { +8265, +9463, +2020, +3087, +909, -384, +486, -2292, -2858, -489, -42, -958, -218, -589, -423, -435, -531, +296, +255, -79, -195, -39, -305, -178, -439, -471, -257, -338, -66, +74, +175, -25, }, 29.68 + { +8828, +9479, +1858, +3692, +1200, -444, +108, -2595, -2598, +225, -443, -1837, -211, -338, +130, -297, -878, +233, +403, -155, -160, +68, -348, -198, -618, -577, -252, -401, -165, +50, +123, -106, }, 29.69 + { +9769, +9532, +1154, +4053, +1153, -433, +152, -3044, -2341, +1209, -501, -2958, -549, -180, +526, +122, -1023, +24, +484, -243, -273, +98, -497, -249, -730, -696, -208, -420, -294, +24, +104, -194, }, 29.70 + { +10963, +10314, -18, +3480, +928, -378, +839, -3146, -2679, +1815, +181, -3477, -1184, -280, +767, +456, -1173, -196, +557, -284, -445, +171, -561, -316, -811, -844, -191, -379, -352, -44, +133, -183, }, 29.71 + { +12437, +11094, -1445, +2785, +310, -110, +1926, -3295, -3171, +2280, +1217, -3589, -1908, -710, +881, +724, -1458, -605, +653, -147, -678, +163, -557, -237, -805, -1040, -224, -349, -355, -12, +190, -216, }, 29.72 + { +13565, +11394, -2213, +2503, -423, +267, +2542, -3317, -3490, +2485, +2267, -3594, -2432, -1318, +735, +938, -1508, -888, +536, -170, -812, +241, -591, -131, -780, -1195, -241, -201, -267, -8, +131, -283, }, 29.73 + { +14365, +11785, -2502, +2065, -1128, +690, +3071, -3145, -4082, +2294, +3294, -3126, -2782, -2332, +449, +1450, -1337, -1152, +323, -232, -796, +274, -707, -133, -760, -1160, -175, -77, -224, +1, +81, -344, }, 29.74 + { +14713, +12188, -2245, +1714, -1545, +697, +3166, -2769, -4728, +1796, +4066, -2366, -3022, -3257, +104, +1860, -844, -1416, +119, -254, -847, +177, -909, -97, -642, -1112, -239, -41, -190, +38, +3, -445, }, 29.75 + { +14645, +12610, -1772, +1687, -1818, +544, +3067, -2552, -5197, +1109, +4450, -1369, -2921, -4051, -284, +2048, -140, -1537, -208, -123, -1018, +64, -886, -45, -602, -1050, -397, -58, -122, -90, +12, -460, }, 29.76 + { +14311, +12744, -823, +2013, -2087, +348, +2751, -2573, -5594, +298, +4380, -359, -2003, -4793, -1003, +2181, +482, -1298, -654, -93, -995, -9, -758, +71, -678, -1141, -461, -235, -94, -220, +50, -343, }, 29.77 + { +13776, +12639, +346, +2236, -2014, +116, +2251, -2236, -6147, -504, +3963, +239, -615, -5033, -2049, +2178, +726, -876, -698, -265, -701, -87, -865, +185, -648, -1310, -522, -464, -75, -87, +92, -171, }, 29.78 + { +13149, +12169, +1402, +2459, -1565, +84, +1536, -1759, -6362, -1341, +3564, +365, +555, -4522, -3382, +1810, +905, -453, -324, -409, -562, -71, -953, +103, -691, -1468, -465, -480, -26, +135, +160, -111, }, 29.79 + { +12380, +11681, +1885, +3275, -1333, -131, +1419, -1701, -5961, -2232, +3308, +405, +924, -3382, -4610, +1021, +1316, -94, -127, -370, -464, +43, -1042, -366, -474, -1380, -504, -384, +12, +312, +117, -135, }, 29.80 + { +11903, +11393, +1499, +3646, -589, -712, +1361, -1471, -5102, -2585, +2953, +277, +167, -1768, -4726, -478, +1438, +247, +197, -198, -524, -85, -1094, -602, -205, -1156, -495, -151, -147, +245, +126, -155, }, 29.81 + { +11277, +11106, +1068, +3696, +162, -535, +662, -1668, -3438, -2767, +2450, +580, -999, -611, -3766, -1971, +1197, +402, +51, +288, -364, -586, -1018, -564, +72, -690, -805, -170, -83, +153, +125, -123, }, 29.82 + { +10588, +10248, +1041, +3990, +549, -596, +503, -1508, -2940, -2531, +2104, +852, -1356, -383, -2481, -2696, +537, +474, -251, +251, -199, -459, -926, -574, +197, -420, -1013, -187, +29, +54, +181, -131, }, 29.83 + { +9521, +9264, +1317, +4316, +722, -767, +764, -816, -2661, -2833, +1508, +1326, -1203, -394, -1458, -2679, +165, +492, -606, -94, -331, -324, -381, -536, -231, -294, -717, -35, +53, -16, +190, -183, }, 29.84 + { +9295, +8224, +1109, +5503, +566, -1438, +1272, -36, -2542, -3436, +897, +1558, -877, +95, -1150, -3243, +276, +686, -962, -210, -683, -628, -208, -496, -150, -199, -735, +279, +265, -118, +39, -219, }, 29.85 + { +7955, +7915, +2062, +4941, +392, -1429, +1053, -497, -1939, -2532, -124, +882, -416, +352, -483, -2672, -726, +593, -30, -164, -732, -489, -159, -285, -145, -245, -559, -60, +99, -150, +30, -106, }, 29.86 + { +7031, +7277, +2031, +4336, +697, -646, +955, -623, -1641, -2182, -233, +535, -317, +229, -165, -1960, -826, +699, +101, -378, -580, -260, -151, -369, -398, -280, -286, -150, -143, -139, +125, -38, }, 29.87 + { +6295, +6730, +1892, +3559, +1033, +63, +744, -685, -1521, -1804, -171, +306, -225, +149, +4, -1512, -648, +773, +80, -370, -396, -159, -189, -414, -539, -344, -273, -228, -102, -44, +122, +2, }, 29.88 + { +5567, +6186, +1652, +2969, +1443, +344, +573, -641, -1422, -1343, -105, +121, -57, +247, +28, -1174, -348, +731, +56, -360, -317, -47, -217, -426, -532, -288, -251, -274, -18, +48, +118, -19, }, 29.89 + { +4996, +5539, +1497, +2838, +1501, +319, +538, -541, -1215, -962, -91, -26, +159, +383, +48, -835, -191, +492, -4, -250, -216, -31, -205, -289, -352, -182, -273, -311, -10, +79, +133, -33, }, 29.90 + { +4369, +4911, +1493, +2561, +1337, +470, +618, -484, -1046, -662, +27, +2, +405, +487, +57, -528, -160, +283, +46, -156, -163, +53, -43, -114, -258, -209, -289, -247, +29, +65, +110, +22, }, 29.91 + { +3634, +4210, +1572, +2321, +1183, +650, +679, -395, -859, -352, +291, +111, +541, +545, +126, -276, -117, +132, +29, -68, -30, +169, -23, -64, -184, -195, -205, -180, +9, +60, +105, +51, }, 29.92 + { +3016, +3577, +1500, +2051, +987, +707, +858, -234, -596, +114, +631, +273, +558, +609, +229, -166, -145, -29, +96, +94, -41, +113, +28, +51, -118, -204, -138, -123, -4, +88, +117, +1, }, 29.93 + { +2776, +3142, +1225, +1761, +847, +791, +1067, +272, -238, +302, +902, +413, +488, +421, +138, -130, -62, +38, +115, +77, -79, +99, +64, +85, -110, -151, -69, -33, +59, +61, +9, -164, }, 29.94 + { +2597, +2855, +1075, +1771, +1129, +1005, +1152, +473, +68, +492, +881, +270, +197, +161, +118, +79, +88, +32, -20, -32, -27, +115, +32, +153, +68, -66, -90, -62, +9, -70, -139, -184, }, 29.95 + { +2669, +3145, +1471, +2033, +1221, +1035, +1183, +275, -243, +270, +725, +249, +159, +52, +151, +138, -51, -81, +23, -1, -18, +190, +86, +173, +118, -82, -134, -156, -186, -160, -81, -98, }, 29.96 + { +2819, +3343, +1567, +2048, +1169, +1075, +1248, +244, -402, -85, +455, +306, +297, +79, +134, +124, +55, +91, +34, -77, +10, +181, -46, +108, +219, +134, -56, -289, -273, -145, -92, -88, }, 29.97 + { +2900, +3386, +1384, +1773, +1008, +1084, +1261, +225, -495, +12, +783, +242, +37, -53, -9, +253, +383, +202, +102, +70, -62, +11, -40, +64, +31, +110, +190, -6, -190, -236, -126, -117, }, 29.98 + { +3231, +3701, +1275, +1612, +705, +788, +1133, +122, -729, -179, +937, +566, +221, -206, -199, +166, +308, +308, +335, +202, +36, +131, -62, -37, -38, -83, +43, +191, +169, +38, -106, -235, }, 29.99 + { +3635, +4205, +1339, +1662, +626, +662, +937, -299, -1254, -578, +1037, +699, +166, -176, -99, +200, +312, +211, +211, +294, +129, +195, +63, +39, -40, -148, -70, +74, +192, +288, +163, -117, }, 29.100 + { +4194, +4783, +1346, +1788, +630, +642, +840, -677, -1766, -952, +1124, +635, -123, -376, -187, +304, +462, +242, +276, +259, +18, +219, +17, +71, +61, -99, -59, +121, +125, +97, +206, +113, }, 29.101 + { +4979, +5362, +1202, +1940, +602, +719, +840, -1009, -2235, -1155, +1361, +510, -477, -624, -359, +169, +423, +212, +324, +400, +17, +168, -5, +20, +47, -58, +31, +174, +74, +79, +86, +27, }, 29.102 + { +6045, +6030, +859, +2185, +506, +725, +848, -1395, -2650, -1218, +1701, +338, -794, -842, -492, +56, +296, +67, +259, +328, -97, +236, +42, +27, -10, -99, -27, +180, +116, +105, +139, -10, }, 29.103 + { +7127, +6787, +391, +2413, +495, +620, +850, -1887, -2997, -1109, +1985, +195, -1031, -1079, -541, +28, +148, +5, +155, +227, -224, +200, +4, -1, -101, -203, -81, +123, +136, +165, +254, +85, }, 29.104 + { +8041, +7641, +54, +2482, +542, +525, +873, -2340, -3303, -988, +2101, +103, -1125, -1253, -590, +7, +85, -30, +110, +254, -288, +69, -159, -33, -202, -285, -79, +104, +146, +180, +291, +49, }, 29.105 + { +8670, +8596, +151, +2444, +429, +355, +1004, -2691, -3423, -1007, +1694, +127, -881, -1445, -767, -93, +121, +297, -11, +97, -290, +1, -294, -164, -296, -328, -78, +89, +211, +122, +240, -5, }, 29.106 + { +8845, +9339, +619, +2533, +443, -115, +1042, -2670, -3312, -1004, +882, -48, -483, -1247, -888, -243, +10, +511, +67, -76, -337, -56, -239, -164, -351, -335, -149, -114, +174, +149, +241, -25, }, 29.107 + { +8992, +9809, +1188, +2897, +625, -583, +690, -2700, -3089, -635, -11, -646, -104, -790, -618, -507, -344, +619, +168, -148, -236, -69, -262, -132, -414, -375, -196, -304, +74, +121, +206, -26, }, 29.108 + { +9299, +9977, +1439, +3466, +927, -820, +224, -3016, -2800, -12, -737, -1360, +110, -354, -169, -639, -802, +553, +363, -141, -128, +0, -287, -205, -550, -443, -225, -438, -58, +99, +221, -4, }, 29.109 + { +10058, +9879, +1163, +4263, +1177, -922, -219, -3311, -2434, +862, -1303, -2457, +248, -70, +493, -501, -1236, +540, +538, -275, -74, +119, -379, -193, -775, -553, -189, -513, -161, +91, +140, -128, }, 29.110 + { +11144, +9761, +369, +4862, +1071, -936, -203, -3855, -2065, +1997, -1565, -3828, +38, +198, +979, -90, -1513, +341, +661, -404, -156, +165, -600, -237, -878, -660, -142, -564, -301, +70, +104, -215, }, 29.111 + { +12546, +10246, -966, +4691, +927, -833, +309, -4199, -2112, +2959, -1144, -4789, -535, +243, +1329, +364, -1689, +85, +795, -505, -386, +288, -677, -309, -1025, -827, -61, -516, -419, +27, +137, -278, }, 29.112 + { +14045, +11382, -2788, +3760, +580, -650, +1686, -4408, -2934, +3566, -51, -5174, -1321, +73, +1428, +705, -1911, -307, +891, -369, -599, +281, -731, -286, -1048, -1082, -16, -454, -510, -50, +248, -211, }, 29.113 + { +15970, +11714, -4486, +3446, -223, -120, +2672, -4778, -3223, +4216, +1130, -5477, -2203, -468, +1756, +960, -2402, -712, +1105, -303, -935, +391, -711, -185, -1048, -1265, -82, -424, -432, +54, +241, -341, }, 29.114 + { +17220, +11916, -5327, +3210, -1072, +444, +3327, -4843, -3644, +4439, +2382, -5600, -2783, -1154, +1580, +1254, -2411, -1038, +941, -324, -1057, +499, -778, -47, -1032, -1459, -61, -214, -352, +22, +162, -398, }, 29.115 + { +18240, +12274, -5799, +2731, -1899, +1079, +3952, -4749, -4376, +4334, +3662, -5208, -3266, -2349, +1378, +1910, -2296, -1381, +715, -370, -1038, +545, -912, -20, -1028, -1437, +31, -67, -319, +18, +102, -464, }, 29.116 + { +18833, +12668, -5683, +2184, -2439, +1329, +4171, -4328, -5232, +3901, +4824, -4546, -3741, -3476, +1105, +2561, -1914, -1779, +533, -418, -1036, +485, -1184, +14, -859, -1412, +1, +27, -315, +91, +5, -584, }, 29.117 + { +19008, +13162, -5318, +1926, -2788, +1224, +4180, -3950, -5962, +3321, +5549, -3543, -3998, -4445, +848, +2902, -1193, -2106, +263, -305, -1180, +327, -1267, +112, -828, -1285, -169, +16, -197, +33, -71, -637, }, 29.118 + { +18737, +13681, -4618, +1963, -3145, +1044, +4007, -3789, -6476, +2407, +5985, -2289, -3707, -5492, +344, +3198, -328, -2230, -228, -74, -1401, +254, -1150, +181, -810, -1310, -322, -25, -144, -179, +21, -629, }, 29.119 + { +18348, +13822, -3468, +2221, -3496, +867, +3623, -3756, -6961, +1517, +5968, -1098, -2716, -6475, -416, +3438, +367, -2015, -778, +7, -1351, +154, -986, +288, -914, -1395, -403, -225, -85, -331, +78, -475, }, 29.120 + { +17731, +13756, -2024, +2354, -3509, +578, +3074, -3309, -7685, +628, +5586, -260, -1146, -7037, -1592, +3604, +681, -1553, -946, -177, -966, +4, -1088, +448, -897, -1594, -473, -493, -35, -196, +111, -266, }, 29.121 + { +16988, +13672, -858, +2219, -2857, +446, +2261, -2723, -8186, -143, +5173, +8, +354, -6856, -3083, +3505, +877, -1058, -660, -442, -746, +8, -1186, +419, -932, -1761, -398, -679, +86, +39, +115, -97, }, 29.122 + { +16138, +12803, +575, +2903, -2738, +274, +1624, -2112, -8167, -1458, +4911, +239, +1463, -6034, -4971, +3030, +1336, -611, -295, -547, -554, +6, -1339, +184, -852, -1914, -351, -543, +76, +333, +176, -169, }, 29.123 + { +15265, +12532, +737, +3734, -2365, -148, +1753, -2212, -7519, -2381, +4804, +154, +1395, -4336, -6360, +1992, +1942, -242, -104, -546, -503, +190, -1457, -473, -403, -1767, -438, -339, +44, +430, +96, -165, }, 29.124 + { +14708, +12215, +282, +4265, -1521, -1002, +1719, -1840, -6421, -2928, +4336, +115, +445, -2293, -6587, +102, +2286, +140, +231, -302, -617, -45, -1479, -669, -78, -1505, -452, -92, -181, +382, +108, -202, }, 29.125 + { +13989, +12100, -300, +4352, -584, -894, +751, -1879, -4250, -3597, +3863, +484, -1133, -527, -5742, -1882, +2289, +370, +107, +366, -557, -756, -1254, -675, +260, -958, -884, -49, -127, +270, +110, -168, }, 29.126 + { +13107, +11235, -316, +4649, +46, -886, +387, -2126, -3083, -3291, +3067, +1077, -1914, +82, -4188, -3391, +1793, +547, -349, +600, -246, -893, -1266, -562, +499, -574, -1293, -81, +40, +122, +177, -141, }, 29.127 + { +12123, +10207, -26, +5040, +240, -1159, +554, -1339, -3049, -3489, +2834, +1553, -2088, +86, -2702, -3839, +1078, +690, -758, +264, -223, -525, -820, -718, +257, -322, -1226, +21, +75, +12, +282, -234, }, 29.128 + { +10747, +9168, +566, +5397, +351, -1371, +926, -546, -2786, -3752, +1902, +1979, -1557, -9, -1749, -3706, +668, +745, -1061, -69, -419, -453, -245, -659, -216, -192, -848, +155, +137, -64, +205, -239, }, 29.129 + { +10338, +7957, +561, +6771, -2, -2128, +1652, +306, -2773, -4474, +1333, +2284, -1324, +617, -1488, -4429, +966, +918, -1497, -98, -822, -796, -54, -649, -27, -96, -951, +551, +331, -223, +48, -268, }, 29.130 + { +8720, +7871, +1937, +5955, -252, -2274, +1362, -265, -1942, -3385, -195, +1599, -597, +942, -704, -3945, -437, +923, -232, -93, -938, -655, -8, -340, +19, -166, -798, +69, +242, -236, +6, -124, }, 29.131 + { +7602, +7369, +1980, +5375, +188, -1525, +1271, -440, -1548, -3046, -447, +1237, -466, +757, -218, -3077, -861, +1080, +8, -496, -751, -394, -12, -415, -286, -141, -377, -40, -114, -262, +138, -57, }, 29.132 + { +6659, +6622, +2031, +4526, +599, -537, +864, -488, -1252, -2664, -491, +837, -265, +650, -6, -2474, -736, +1187, -23, -536, -523, -192, -58, -543, -514, -195, -232, -228, -227, -106, +203, +4, }, 29.133 + { +5900, +6258, +1847, +3648, +1138, +55, +581, -518, -1216, -2232, -426, +663, -175, +546, +190, -2072, -582, +1218, -57, -487, -330, -182, -121, -530, -618, -248, -293, -250, -52, -43, +131, +41, }, 29.134 + { +5056, +5699, +1640, +3073, +1682, +223, +366, -415, -1093, -1701, -428, +436, +76, +685, +156, -1697, -250, +1101, -72, -482, -271, -35, -164, -545, -578, -155, -255, -314, +31, +57, +129, +2, }, 29.135 + { +4420, +5031, +1526, +2971, +1795, +154, +317, -287, -871, -1279, -467, +257, +332, +803, +167, -1309, -82, +802, -141, -342, -151, -34, -185, -411, -382, -26, -278, -370, +32, +101, +150, -29, }, 29.136 + { +3741, +4414, +1550, +2755, +1697, +240, +358, -209, -641, -963, -482, +156, +636, +955, +153, -952, -130, +526, -22, -234, -141, -29, -17, -156, -225, -73, -393, -324, +91, +81, +127, +14, }, 29.137 + { +2974, +3771, +1714, +2268, +1466, +609, +473, -195, -532, -642, -208, +371, +868, +928, +168, -618, -68, +350, +7, -152, -30, +198, +164, -106, -265, -109, -239, -204, +88, +59, +101, +117, }, 29.138 + { +2091, +3036, +1907, +2129, +1391, +724, +464, -41, -262, -310, +40, +365, +939, +1032, +282, -384, -88, +174, -12, -37, +129, +229, +41, -48, -98, -70, -190, -179, +36, +72, +111, +99, }, 29.139 + { +1445, +2433, +1850, +1781, +1171, +805, +720, +119, +17, +232, +387, +551, +917, +1092, +388, -310, -142, -4, +121, +154, +38, +139, +164, +94, -72, -106, -103, -116, +22, +112, +121, +28, }, 29.140 + { +1185, +1993, +1603, +1441, +986, +909, +956, +692, +298, +365, +753, +730, +851, +889, +295, -301, -75, +80, +163, +139, -24, +148, +231, +110, -113, -59, -17, -3, +88, +93, +26, -171, }, 29.141 + { +929, +1455, +1263, +1389, +1207, +1075, +1117, +1195, +937, +623, +608, +551, +588, +631, +253, -42, +158, +103, +4, +39, +49, +61, +131, +212, +119, +81, -26, +0, +138, -59, -235, -232, }, 29.142 + { +822, +1583, +1506, +1563, +1699, +1350, +1018, +900, +685, +649, +736, +432, +188, +378, +360, +160, +134, -13, -136, -75, +123, +246, +203, +257, +240, +33, -106, -86, -100, -185, -187, -131, }, 29.143 + { +1055, +2056, +2052, +1866, +1431, +1170, +1157, +723, +299, +248, +365, +522, +438, +367, +368, +108, -145, -117, +92, +69, +74, +249, +238, +249, +240, +27, -128, -200, -286, -220, -88, -53, }, 29.144 + { +1205, +2171, +1980, +1773, +1441, +1300, +1201, +725, +193, -127, +142, +624, +550, +387, +335, +108, +110, +159, +2, -95, +146, +227, +29, +177, +403, +337, -41, -376, -330, -171, -140, -61, }, 29.145 + { +1241, +2158, +1760, +1464, +1328, +1398, +1227, +684, +95, +70, +568, +408, +149, +304, +228, +314, +526, +203, +21, +102, +15, -27, +94, +161, +134, +344, +341, -75, -343, -352, -143, -62, }, 29.146 + { +1622, +2444, +1530, +1228, +926, +1008, +1151, +744, -34, -42, +764, +765, +377, -38, -176, +304, +572, +431, +399, +163, +15, +139, +7, -83, +139, +174, +132, +311, +140, -144, -288, -260, }, 29.147 + { +1988, +2810, +1493, +1199, +762, +896, +984, +329, -524, -369, +974, +1088, +421, +50, +39, +109, +262, +367, +396, +394, +294, +181, +60, +66, -63, -115, +123, +273, +319, +228, -43, -271, }, 29.148 + { +2526, +3457, +1538, +1318, +724, +747, +744, -154, -1107, -804, +1097, +1060, +234, +52, +56, +324, +531, +217, +162, +419, +225, +256, +263, +67, +92, -2, -93, +88, +240, +428, +251, -76, }, 29.149 + { +3196, +4012, +1429, +1473, +720, +771, +686, -545, -1618, -1131, +1253, +952, -133, -206, -51, +422, +646, +293, +343, +345, +85, +287, +111, +124, +185, +14, -5, +226, +158, +71, +246, +198, }, 29.150 + { +4055, +4548, +1209, +1653, +679, +876, +676, -915, -2105, -1296, +1540, +778, -521, -439, -221, +267, +627, +274, +404, +557, +82, +190, +96, +57, +173, +67, +122, +268, +75, +91, +69, +85, }, 29.151 + { +5274, +5182, +788, +1972, +519, +928, +689, -1324, -2574, -1398, +1954, +556, -880, -663, -380, +149, +471, +122, +381, +459, +18, +339, +145, +8, +122, +110, +27, +301, +132, +67, +132, +6, }, 29.152 + { +6463, +5753, +204, +2322, +409, +883, +685, -1827, -2887, -1237, +2299, +272, -1164, -830, -425, +53, +394, -18, +257, +435, -217, +313, +174, +118, +26, -101, +42, +280, +156, +192, +176, +19, }, 29.153 + { +7727, +6595, -464, +2628, +421, +701, +721, -2439, -3227, -1064, +2569, +149, -1378, -1132, -432, +91, +148, +15, +160, +263, -252, +291, +71, -34, -78, -110, -65, +186, +193, +201, +372, +187, }, 29.154 + { +8674, +7441, -887, +2687, +475, +615, +762, -2918, -3490, -885, +2619, +32, -1422, -1271, -474, +50, +151, -43, +133, +383, -345, +103, -122, +5, -192, -218, -4, +192, +197, +219, +350, +56, }, 29.155 + { +9426, +8468, -909, +2618, +320, +470, +937, -3379, -3580, -906, +2153, +153, -1146, -1581, -641, -54, +224, +390, -97, +193, -307, +44, -287, -162, -284, -252, +7, +204, +290, +112, +287, +9, }, 29.156 + { +9648, +9372, -545, +2609, +289, -35, +1177, -3423, -3509, -971, +1312, +111, -652, -1474, -971, -83, +171, +613, -45, +26, -344, -79, -230, -165, -334, -249, -69, -50, +303, +195, +309, -45, }, 29.157 + { +9794, +9998, +39, +2769, +379, -638, +980, -3266, -3261, -859, +205, -83, -237, -1162, -748, -518, -59, +946, +29, -268, -354, +5, -131, -183, -422, -257, -155, -194, +224, +120, +248, +7, }, 29.158 + { +9981, +10397, +622, +3286, +610, -1141, +509, -3403, -3000, -195, -811, -998, +359, -548, -477, -751, -558, +952, +151, -164, -95, -136, -277, -86, -487, -322, -168, -469, +127, +155, +238, -39, }, 29.159 + { +10400, +10438, +745, +3939, +894, -1363, +3, -3769, -2585, +471, -1670, -1614, +581, -153, +52, -948, -1056, +930, +424, -236, -31, +17, -267, -241, -666, -379, -196, -563, -20, +129, +269, +14, }, 29.160 + { +11293, +10206, +442, +4923, +1094, -1505, -530, -3996, -2130, +1419, -2437, -2806, +924, +121, +806, -871, -1571, +1001, +618, -424, +58, +151, -379, -185, -956, -481, -127, -651, -119, +140, +160, -149, }, 29.161 + { +12405, +9835, -281, +5828, +885, -1582, -583, -4592, -1654, +2615, -2996, -4362, +959, +504, +1380, -564, -2020, +895, +761, -610, +81, +185, -720, -204, -1012, -549, -116, -759, -235, +116, +85, -201, }, 29.162 + { +13934, +9778, -1546, +6319, +686, -1381, -382, -5271, -1119, +3944, -3172, -5767, +686, +682, +1741, +77, -2181, +507, +979, -721, -237, +318, -773, -227, -1265, -756, +92, -716, -477, +162, +134, -400, }, 29.163 + { +15591, +10583, -3448, +5772, +592, -1315, +577, -5494, -1701, +4790, -2265, -6627, -93, +745, +2160, +357, -2547, +377, +1130, -881, -407, +529, -934, -349, -1319, -885, +105, -673, -507, +45, +171, -344, }, 29.164 + { +17313, +11801, -5808, +4851, +227, -980, +2385, -6012, -2746, +5567, -996, -7076, -952, +586, +2154, +773, -2812, -169, +1297, -600, -709, +461, -948, -242, -1337, -1246, +226, -600, -658, -10, +354, -281, }, 29.165 + { +19637, +11754, -7792, +4845, -732, -208, +3348, -6604, -2889, +6378, +241, -7587, -1944, +32, +2714, +992, -3500, -540, +1647, -590, -1131, +670, -931, -134, -1354, -1421, +144, -583, -536, +136, +307, -469, }, 29.166 + { +21056, +11745, -8787, +4783, -1622, +469, +3944, -6753, -3241, +6740, +1590, -8058, -2609, -411, +2588, +1199, -3554, -896, +1543, -588, -1309, +826, -1017, +54, -1317, -1707, +140, -326, -455, +92, +212, -518, }, 29.167 + { +22470, +11991, -9701, +4389, -2684, +1431, +4782, -6942, -4015, +6909, +3084, -7923, -3158, -1809, +2522, +1950, -3598, -1289, +1296, -609, -1331, +920, -1125, +160, -1425, -1754, +339, -152, -445, +42, +154, -583, }, 29.168 + { +23333, +12284, -9893, +3816, -3344, +2109, +5145, -6669, -4930, +6673, +4509, -7499, -3802, -2971, +2448, +2729, -3461, -1700, +1131, -635, -1249, +918, -1341, +144, -1300, -1646, +329, -23, -418, +82, +75, -652, }, 29.169 + { +23907, +12687, -9670, +3149, -3819, +2297, +5278, -6129, -6015, +6230, +5855, -6823, -4412, -4207, +2246, +3493, -3012, -2245, +989, -670, -1278, +815, -1685, +265, -1083, -1694, +279, +79, -444, +187, -65, -803, }, 29.170 + { +24068, +13242, -9317, +2853, -4157, +2181, +5293, -5711, -6874, +5677, +6685, -5741, -4828, -5227, +2103, +3851, -2196, -2705, +724, -483, -1476, +639, -1724, +395, -1100, -1511, +43, +72, -276, +84, -146, -836, }, 29.171 + { +23835, +13868, -8722, +2737, -4517, +2057, +5139, -5437, -7512, +4767, +7374, -4441, -4873, -6362, +1764, +4214, -1258, -3060, +266, -145, -1812, +589, -1602, +416, -1030, -1500, -192, +122, -223, -168, -12, -862, }, 29.172 + { +23307, +14493, -7616, +2886, -5061, +1805, +4905, -5438, -8024, +3633, +7772, -2910, -4088, -7840, +1069, +4716, -316, -3023, -501, +151, -1943, +531, -1399, +596, -1194, -1653, -168, -131, -123, -407, +123, -804, }, 29.173 + { +22971, +14195, -6115, +3007, -5341, +1777, +4268, -5238, -8637, +2925, +7500, -1787, -2907, -8792, +313, +4922, +197, -2731, -1003, +162, -1684, +337, -1204, +594, -1286, -1645, -381, -303, -37, -516, +148, -504, }, 29.174 + { +22070, +14375, -4392, +2868, -5223, +1286, +3714, -4447, -9674, +1907, +7159, -860, -973, -9579, -1209, +5344, +421, -2142, -1115, -130, -1112, +96, -1456, +898, -1239, -2004, -343, -667, +59, -231, +163, -308, }, 29.175 + { +21240, +14393, -3174, +2492, -4298, +1094, +2745, -3688, -10265, +1178, +6777, -618, +645, -9443, -2927, +5381, +636, -1617, -791, -478, -882, +115, -1535, +816, -1293, -2149, -223, -878, +246, +6, +122, -102, }, 29.176 + { +20341, +13345, -1099, +2866, -4191, +914, +1804, -2626, -10582, -327, +6635, -287, +2111, -8876, -5214, +5209, +1109, -1120, -336, -736, -608, +24, -1715, +729, -1303, -2434, -80, -706, +170, +364, +230, -221, }, 29.177 + { +19164, +13059, -468, +4105, -4326, +617, +1911, -2785, -9817, -1770, +6595, -131, +2540, -7381, -7331, +4587, +2019, -857, -311, -599, -501, +196, -1861, -41, -744, -2295, -231, -641, +296, +624, -2, -206, }, 29.178 + { +18422, +13001, -808, +4597, -3422, -211, +2249, -2884, -9087, -2495, +6668, -543, +1814, -4858, -8725, +3134, +2718, -437, +54, -836, -508, +440, -2036, -713, -94, -2244, -301, -159, -24, +549, +64, -190, }, 29.179 + { +17855, +12583, -1366, +5362, -2553, -1443, +2178, -2151, -7613, -3290, +5904, -270, +528, -2457, -8756, +644, +3333, -90, +363, -320, -761, -106, -1922, -663, +147, -1870, -338, +6, -294, +558, +55, -269, }, 29.180 + { +16989, +12653, -2050, +5407, -1459, -1174, +828, -2193, -4917, -4430, +5563, +243, -1454, -249, -7905, -1684, +3547, +136, +95, +521, -741, -985, -1507, -732, +567, -1249, -1016, +108, -174, +393, +77, -205, }, 29.181 + { +15955, +11844, -2035, +5709, -643, -1173, +284, -2723, -3123, -4229, +4384, +1201, -2654, +769, -6230, -3909, +3368, +375, -503, +1015, -370, -1372, -1549, -501, +871, -801, -1619, +110, +41, +191, +164, -153, }, 29.182 + { +15076, +10787, -1651, +6161, -494, -1528, +363, -1853, -3374, -4091, +4325, +1345, -2786, +774, -4553, -4709, +2401, +708, -854, +734, -248, -874, -1363, -746, +954, -560, -1815, +201, +149, +40, +297, -250, }, 29.183 + { +13619, +9790, -1075, +6480, -296, -1830, +805, -986, -3179, -4836, +3833, +2526, -3239, +844, -2857, -5293, +1983, +856, -1538, +348, -255, -582, -521, -965, +224, -130, -1436, +334, +56, -57, +433, -405, }, 29.184 + { +11990, +8803, -122, +6797, -290, -2053, +1262, -151, -2986, -4897, +2471, +2765, -2059, +507, -2148, -4881, +1467, +956, -1677, +43, -545, -596, -9, -842, -196, -59, -1007, +415, +207, -148, +219, -297, }, 29.185 + { +12081, +7961, -53, +8316, -2153, -3098, +1599, -1374, -4780, -3918, +6091, +1729, -1658, +3619, -1653, -4298, +1906, +240, -2274, -904, -1646, -475, -581, -1417, -48, -621, -760, +583, -70, -397, +372, +38, }, 29.186 + { +10221, +7710, +913, +7396, -744, -3594, +288, -1159, -3490, -2578, +4228, +2100, -676, +2348, -1090, -3898, +283, +166, -1419, -166, -1389, -451, +154, -1605, +30, -242, -1341, +92, +30, -175, +146, +10, }, 29.187 + { +8688, +6964, +1507, +6729, -314, -2703, +315, -1206, -2584, -2071, +3004, +1882, -602, +1784, -753, -3344, +27, -28, -1040, +36, -1038, -169, +101, -1356, +51, -283, -1249, -154, -166, -180, +96, -77, }, 29.188 + { +7115, +6222, +2194, +6013, +21, -1813, +346, -984, -1850, -1758, +2164, +1394, -547, +1436, -539, -2734, -356, -16, -801, -44, -393, +279, +133, -1115, -80, -420, -1086, -375, -460, -339, +102, +64, }, 29.189 + { +5945, +5731, +2369, +5160, +628, -1311, +172, -355, -1302, -1644, +1506, +1052, -512, +980, -248, -2308, -600, +61, -662, +216, +230, +430, +21, -924, -262, -525, -975, -595, -515, -352, +24, +58, }, 29.190 + { +4951, +5289, +2362, +4475, +1066, -1021, +399, +107, -1048, -1369, +919, +662, -450, +769, -110, -1957, -639, +150, -163, +531, +305, +258, +28, -774, -421, -578, -897, -479, -486, -369, -53, -38, }, 29.191 + { +4363, +4902, +2175, +3906, +1203, -661, +681, +254, -736, -1138, +362, +420, -286, +700, -78, -1616, -376, +371, +225, +620, +133, +107, -31, -735, -442, -346, -613, -527, -506, -305, -33, +11, }, 29.192 + { +3887, +4410, +1997, +3432, +1166, -200, +836, +280, -488, -1038, -68, +289, -94, +640, +127, -1246, -284, +556, +413, +412, -66, +15, -158, -547, -132, -220, -649, -561, -395, -212, +21, +92, }, 29.193 + { +3376, +3956, +1885, +2975, +1204, +193, +869, +327, -309, -968, -279, +153, +258, +942, +175, -1108, -255, +727, +480, +101, -239, +78, +89, -338, -137, -200, -570, -519, -230, -33, +148, +121, }, 29.194 + { +2882, +3708, +1714, +2272, +1421, +628, +806, +292, -242, -915, -154, +676, +462, +684, +167, -864, -170, +750, +347, -82, -16, +193, +144, -210, -259, -192, -347, -281, -16, +141, -8, -250, }, 29.195 + { +2046, +3121, +1820, +2057, +1654, +693, +650, +385, +140, -232, -150, +593, +684, +440, +155, -506, -275, +602, +454, -11, +56, +206, +86, -187, -110, +2, -156, -45, +18, -158, -271, -285, }, 29.196 + { +1488, +2866, +1983, +1297, +1310, +1249, +896, +455, +406, +318, +200, +433, +517, +126, +107, -107, -188, +504, +467, +57, +7, +98, +167, +102, +54, +69, +57, -187, -324, -266, -204, -157, }, 29.197 + { +1053, +2185, +1754, +1283, +1374, +1384, +1276, +1018, +579, +445, +413, +125, +270, +305, -100, -39, +315, +357, +242, +93, +19, +226, +393, +295, +143, -27, -218, -292, -266, -226, -155, -132, }, 29.198 + { +1057, +1688, +1471, +1786, +1766, +1650, +1060, +783, +933, +472, +248, +183, +76, +69, +137, +183, +238, +233, +230, +317, +365, +313, +253, +237, +26, -223, -314, -259, -170, -175, -164, -190, }, 29.199 + { +1484, +2348, +1611, +1846, +1758, +1472, +1102, +423, +268, +233, +403, +262, +27, +176, +309, +97, -27, +318, +563, +614, +474, +195, -31, -203, -192, -193, -175, -172, -180, -189, -226, -227, }, 29.200 + { +1189, +2150, +2013, +2091, +1722, +1365, +885, +462, +260, +102, +413, +490, +320, +96, +1, +58, +212, +334, +486, +716, +577, +224, -92, -268, -289, -245, -180, -118, -126, -201, -214, -200, }, 29.201 + { +1538, +2422, +1826, +1858, +1328, +1049, +982, +559, +11, +288, +803, +359, +369, +46, -142, +244, +201, +241, +677, +674, +409, +408, -39, -390, -282, -219, -225, -163, -112, -102, -144, -262, }, 29.202 + { +1451, +2242, +1550, +1542, +1259, +1129, +1099, +613, +12, +373, +659, +432, +541, +134, +290, +219, +14, +256, +292, +393, +633, +888, +287, -211, -275, -432, -238, -88, -138, -127, -59, -184, }, 29.203 + { +1889, +2552, +1389, +1386, +798, +799, +1037, +440, -97, +313, +902, +615, +250, +224, +305, +196, +454, +188, +213, +467, +218, +428, +693, +519, -184, -445, -344, -230, -88, -89, -79, -137, }, 29.204 + { +2363, +3156, +1398, +1195, +447, +518, +860, +263, -393, +80, +1073, +455, +343, +419, -4, +307, +535, +250, +536, +315, -34, +496, +401, +321, +495, -3, -404, -292, -153, -89, -99, -128, }, 29.205 + { +2825, +3421, +1231, +1466, +685, +599, +704, -461, -1098, +100, +1264, +329, +295, +180, +24, +419, +226, +386, +756, +380, +127, +240, +62, +328, +348, +131, +263, +30, -341, -335, -68, -108, }, 29.206 + { +3491, +4043, +1102, +1542, +710, +589, +566, -937, -1530, +137, +1469, +122, -70, -161, -43, +468, +450, +426, +430, +401, +160, +372, +284, +90, +60, +56, +234, +293, +163, -117, -305, -271, }, 29.207 + { +4318, +4870, +895, +1479, +603, +516, +626, -1326, -2005, +237, +1656, -115, -219, -418, -328, +396, +406, +377, +591, +338, -178, +469, +312, +158, +217, -234, -8, +329, +210, +69, +187, -16, }, 29.208 + { +5303, +5497, +566, +1592, +649, +557, +509, -1916, -2395, +604, +1814, -332, -334, -762, -437, +361, +208, +350, +554, +119, -140, +409, +18, +313, +179, -239, +98, -40, +40, +299, +419, +154, }, 29.209 + { +6339, +6214, +236, +1676, +646, +546, +369, -2580, -2680, +1136, +1943, -586, -423, -1111, -529, +411, +162, +286, +376, -36, -255, +422, +29, +77, +2, -290, -43, +175, +135, +31, +367, +299, }, 29.210 + { +7425, +6991, -61, +1742, +482, +489, +257, -3260, -2805, +1599, +1929, -688, -450, -1459, -633, +395, +140, +359, +251, -272, -354, +408, -47, +55, -274, -528, -51, +174, +73, +63, +482, +141, }, 29.211 + { +8275, +7928, -159, +1756, +330, +237, +226, -3790, -2846, +1890, +1754, -690, -422, -1605, -800, +248, +185, +442, +143, -377, -482, +428, -180, -145, -222, -605, -186, -18, +24, +140, +387, +163, }, 29.212 + { +8779, +8969, +132, +1669, +354, -215, +82, -3976, -2837, +1984, +1471, -648, -422, -1570, -842, -60, +130, +630, +84, -403, -597, +177, +30, -221, -403, -610, -358, +87, -64, -83, +409, +63, }, 29.213 + { +8644, +10014, +1089, +1453, +493, -603, -298, -3906, -2820, +1754, +1240, -552, -546, -1453, -849, -345, +44, +672, +148, -531, -682, +196, +32, -233, -584, -609, -409, -84, -103, -217, +378, +199, }, 29.214 + { +8306, +10593, +2458, +1598, +488, -758, -657, -3861, -2849, +1369, +1000, -322, -680, -1443, -722, -668, -37, +677, -45, -127, -673, -156, +70, -281, -443, -635, -631, -315, -160, -54, +479, +139, }, 29.215 + { +8399, +10550, +3351, +2403, +311, -794, -759, -3852, -2757, +792, +477, +47, -726, -1554, -558, -902, -349, +816, +82, -285, -484, -159, +82, -356, -623, -644, -824, -243, +7, -98, +292, +151, }, 29.216 + { +8816, +10302, +3569, +3594, +382, -1029, -763, -3770, -2393, +191, -597, +339, -557, -1492, -281, -1488, -279, +1005, -143, -84, -408, -266, +120, -345, -812, -549, -772, -407, -193, -80, +533, +172, }, 29.217 + { +9548, +9994, +3253, +4643, +623, -1187, -749, -3597, -1800, -143, -2200, +304, -135, -1804, +254, -1488, -709, +1187, -140, -38, -318, -470, +133, -281, -894, -381, -819, -627, -170, -88, +384, +19, }, 29.218 + { +10751, +9616, +2488, +5649, +553, -1161, -620, -3463, -848, -358, -3996, +121, +130, -2080, +871, -1563, -750, +1416, -465, -119, -39, -417, +70, -275, -1074, -309, -632, -645, -410, -224, +390, -12, }, 29.219 + { +12014, +9312, +1365, +6755, +300, -1330, -113, -3321, +199, -72, -5935, -749, +987, -2491, +1095, -1087, -1039, +1478, -609, -197, +278, -296, -103, -265, -1088, -288, -651, -818, -474, -102, +420, -351, }, 29.220 + { +13420, +9342, -277, +7865, +178, -2087, +567, -3307, +1525, +754, -7969, -2060, +1804, -2289, +1011, -875, -1158, +1512, -570, -399, +356, -20, -88, -202, -1219, -576, -573, -671, -574, -252, +223, -435, }, 29.221 + { +14807, +9961, -2295, +8150, +567, -2864, +1147, -3390, +2627, +2008, -9297, -3776, +2200, -1711, +807, -518, -1276, +1360, -541, -609, +222, +438, +75, -495, -1315, -653, -426, -658, -1054, -304, +558, -512, }, 29.222 + { +16799, +11079, -4722, +7037, +966, -2929, +1994, -3796, +2704, +3553, -9595, -5358, +1866, -912, +909, -200, -1483, +979, -455, -806, +207, +669, +68, -725, -1243, -745, -665, -630, -1077, -219, +691, -658, }, 29.223 + { +18748, +11700, -6587, +6122, +943, -2914, +2664, -4426, +2804, +5554, -10085, -6616, +1486, -372, +1328, -285, -1517, +471, -396, -837, +75, +587, +104, -751, -1461, -967, -816, -312, -988, -264, +684, -677, }, 29.224 + { +20863, +12866, -8572, +4385, +266, -1602, +3832, -5716, +2704, +6971, -9876, -6842, +1023, -479, +1689, -35, -1641, +123, -340, -939, -107, +662, +89, -932, -1675, -1081, -768, +37, -888, -310, +796, -570, }, 29.225 + { +22765, +13783, -10202, +2941, -746, -81, +4256, -6846, +2898, +7803, -8917, -6979, +238, -972, +2079, +576, -1912, -370, -306, -915, -363, +634, -131, -948, -1776, -1303, -718, +235, -798, -279, +1030, -691, }, 29.226 + { +24585, +14272, -11287, +1831, -1784, +1157, +4160, -7450, +3079, +8440, -7630, -7341, -269, -1716, +2654, +1114, -2449, -581, -181, -975, -680, +550, -325, -686, -1945, -1634, -616, +402, -659, -135, +1021, -867, }, 29.227 + { +25869, +14987, -12073, +934, -2610, +1696, +3918, -7361, +2532, +9076, -6029, -7754, -590, -2620, +3019, +1624, -2920, -652, -46, -1264, -966, +600, -472, -467, -2153, -1908, -503, +517, -451, -126, +848, -860, }, 29.228 + { +26886, +15454, -12309, +371, -3390, +1840, +3592, -7055, +1669, +9594, -4128, -8018, -1017, -3459, +3063, +2189, -3137, -722, +61, -1655, -1121, +760, -729, -326, -2158, -2099, -462, +648, -404, -166, +686, -817, }, 29.229 + { +27684, +15653, -11980, +24, -4099, +1713, +3246, -6955, +802, +10113, -2356, -7981, -1587, -4226, +3032, +2573, -2987, -885, +150, -1954, -1167, +794, -988, -168, -2014, -2167, -434, +666, -569, -144, +540, -855, }, 29.230 + { +27741, +16216, -11243, -193, -4856, +1352, +3238, -7293, -125, +10598, -852, -7518, -2157, -4853, +2670, +2868, -2470, -1300, +205, -1901, -1416, +672, -1092, +16, -1804, -2095, -591, +514, -688, -235, +476, -797, }, 29.231 + { +27272, +16910, -10056, -159, -5917, +966, +3706, -8117, -996, +10790, +336, -6433, -2511, -5475, +1946, +3049, -1685, -1717, +71, -1629, -1727, +569, -1061, +184, -1403, -2279, -872, +450, -920, -127, +585, -861, }, 29.232 + { +26292, +17598, -8440, +25, -7051, +509, +4314, -9076, -1994, +10815, +1175, -4930, -2295, -6533, +1145, +3192, -1111, -1763, -328, -1487, -1778, +538, -867, +358, -1413, -2301, -1193, +94, -600, -21, +592, -845, }, 29.233 + { +24908, +18211, -6510, +265, -7874, +12, +4724, -9478, -3509, +10716, +2192, -3778, -1219, -7880, +248, +3471, -999, -1541, -792, -1628, -1421, +841, -1035, +457, -1363, -2591, -1213, -67, -308, +27, +657, -759, }, 29.234 + { +23173, +18778, -4279, +420, -8200, -952, +4606, -8583, -5614, +10055, +3892, -3343, +694, -8935, -1196, +3813, -1288, -1146, -860, -1990, -933, +977, -1325, +807, -1645, -2747, -714, -417, -75, +218, +548, -805, }, 29.235 + { +22000, +18365, -2003, +631, -8453, -1561, +3477, -6891, -7183, +8672, +5645, -3122, +2529, -8996, -3276, +3955, -1630, -956, -275, -2341, -1164, +1321, -1481, +629, -1309, -2933, -330, -280, -173, +221, +483, -718, }, 29.236 + { +21112, +17584, -502, +1334, -8158, -2273, +2292, -5787, -7662, +7007, +7216, -2614, +3372, -7775, -5664, +3835, -1591, -1170, +244, -2374, -1158, +1090, -1550, +627, -758, -3019, +93, -274, -410, +438, +348, -800, }, 29.237 + { +20632, +17088, -637, +2364, -7070, -3739, +1695, -4935, -8217, +5848, +8673, -2173, +3453, -6082, -7678, +3590, -1152, -1978, +580, -2279, -1275, +1124, -1750, +530, -17, -2783, -114, -166, -296, +284, +223, -679, }, 29.238 + { +20783, +15919, -1263, +4036, -6965, -4754, +1892, -4346, -8539, +4539, +9671, -1610, +3670, -4797, -8663, +2624, -468, -2009, +28, -2355, -1460, +1576, -1563, +142, +565, -2599, -176, -95, -480, +333, +227, -736, }, 29.239 + { +19898, +14834, -883, +5611, -7741, -5058, +2778, -4286, -8109, +2022, +9952, -268, +3452, -2598, -9652, +1195, +498, -1859, -458, -2733, -1925, +1990, -998, -244, +1156, -2794, -697, +541, -558, +197, +87, -769, }, 29.240 + { +18353, +13734, -294, +6773, -7182, -5247, +2895, -3546, -8000, -248, +9510, +1071, +3101, -432, -9279, -621, +1397, -1978, -692, -2518, -2682, +1633, -584, +363, +1428, -3524, -1018, +1348, -563, -124, +38, -581, }, 29.241 + { +17879, +12019, -1720, +8332, -4976, -5136, +2334, -3753, -7617, -1708, +9554, +1908, +1367, +1443, -7575, -1992, +1783, -1645, -1254, -2425, -2861, +887, -188, +457, +1489, -3426, -1450, +1731, -415, -317, +8, -369, }, 29.242 + { +16652, +10730, -1605, +9069, -4100, -5114, +2342, -2722, -7212, -3184, +9140, +2114, -706, +3732, -5117, -4057, +2505, -1340, -2078, -1590, -2693, +151, -496, -93, +1733, -2286, -1942, +1173, +71, -202, +59, -356, }, 29.243 + { +15156, +9682, -934, +8954, -3661, -4339, +2035, -2043, -6405, -3988, +8467, +1700, -1521, +4564, -3502, -4488, +2506, -991, -2469, -1109, -2320, -118, -899, -916, +1437, -1210, -1567, +612, -176, -55, +492, -295, }, 29.244 + { +13768, +8771, -687, +8850, -3021, -3693, +1828, -1815, -5404, -4221, +7310, +1847, -1818, +4247, -2573, -4214, +2383, -697, -2275, -1002, -2080, -223, -830, -1342, +608, -827, -917, +655, -473, -208, +715, -175, }, 29.245 + { +14260, +8470, -4402, +9252, +637, -4904, +113, -702, -4629, -3590, +7432, -364, -3180, +3406, -815, -2084, +3326, +846, -1128, +174, -1402, -361, -2087, -2634, -411, -921, -1460, -69, -168, +123, +619, -314, }, 29.246 + { +12203, +8042, -2103, +8153, +36, -4209, +166, -837, -3973, -3102, +5672, +328, -1860, +2823, -972, -1947, +2514, +629, -644, +18, -1399, -247, -1603, -2116, -289, -1032, -1262, -81, -282, -111, +472, -81, }, 29.247 + { +9978, +7761, -851, +7167, +518, -3404, +616, -905, -3552, -2875, +4478, +661, -1312, +2289, -665, -1823, +1788, +811, -693, -46, -1135, -436, -1105, -1539, -267, -710, -1155, -219, -156, -293, +133, -138, }, 29.248 + { +8252, +7011, +325, +6475, +571, -2476, +1105, -925, -3370, -2437, +3577, +876, -1052, +1795, -250, -1885, +1251, +954, -652, -129, -973, -426, -862, -997, +85, -618, -1083, -201, -130, -385, -107, -293, }, 29.249 + { +6990, +6408, +794, +5771, +1007, -1732, +1092, -813, -2841, -2294, +2966, +1185, -1180, +1392, +18, -1807, +929, +855, -550, -195, -860, -345, -413, -570, +52, -503, -888, -152, -282, -552, -210, -339, }, 29.250 + { +6315, +5794, +807, +5067, +1552, -954, +511, -614, -2056, -2084, +2442, +1235, -1125, +916, +7, -1376, +711, +581, -457, -233, -563, +16, -83, -537, -90, -310, -669, -307, -465, -561, -130, -413, }, 29.251 + { +5495, +5067, +1235, +4594, +1625, -330, +383, -413, -1595, -1679, +1966, +934, -895, +616, -4, -1020, +465, +389, -292, +92, -212, +95, -14, -517, -157, -268, -599, -430, -445, -406, -157, -409, }, 29.252 + { +4664, +4577, +1540, +4071, +1781, +42, +302, -196, -1100, -1341, +1290, +763, -650, +297, +59, -796, +256, +526, +78, +88, -122, +237, -54, -604, -266, -281, -530, -328, -364, -356, -110, -313, }, 29.253 + { +3851, +4119, +1861, +3768, +1681, +225, +590, +32, -804, -1149, +865, +588, -638, +296, +218, -632, +437, +631, +5, +112, +96, +233, -258, -721, -220, -100, -390, -319, -297, -172, -5, -185, }, 29.254 + { +3336, +3750, +1919, +3488, +1574, +321, +813, +276, -570, -1058, +527, +383, -558, +511, +605, -444, +230, +571, +103, +183, +137, -15, -469, -450, -1, -70, -317, -262, -110, +31, -67, -427, }, 29.255 + { +3049, +3510, +1714, +3215, +1488, +383, +1012, +442, -405, -1074, +260, +303, -38, +921, +427, -524, +201, +517, +216, +135, -99, -116, -221, -179, +46, -34, -244, -78, -50, -204, -303, -502, }, 29.256 + { +2844, +3234, +1490, +2937, +1418, +496, +1224, +481, -359, -986, +230, +762, +253, +708, +333, -527, +155, +538, +90, +24, +59, +6, -45, -70, +130, +103, -256, -256, -271, -304, -297, -325, }, 29.257 + { +2647, +2909, +1294, +2675, +1363, +698, +1331, +460, -184, -366, +335, +522, +431, +628, +210, -521, -47, +509, +303, +218, +56, +23, +150, +170, +182, -200, -553, -341, -197, -165, -211, -392, }, 29.258 + { +2534, +2823, +1022, +1970, +1429, +1221, +1392, +703, +196, -392, +319, +726, +304, +316, -41, -517, +273, +763, +274, +109, +137, +366, +348, -105, -308, -391, -404, -192, -101, -238, -327, -356, }, 29.259 + { +1989, +2468, +1081, +1801, +1546, +1331, +1957, +1126, +247, -246, -18, +528, +333, +129, -70, -149, +414, +761, +386, +169, +318, +372, +30, -395, -334, -284, -295, -143, -195, -279, -332, -341, }, 29.260 + { +1620, +2490, +1471, +1655, +2013, +1585, +1301, +1138, +603, -161, -181, -90, -24, +524, +502, +148, +414, +612, +427, +246, +105, +30, -174, -325, -240, -291, -355, -203, -136, -260, -309, -267, }, 29.261 + { +1263, +2410, +2075, +1764, +1891, +1970, +1489, +641, +109, -195, -152, +183, +214, +240, +589, +646, +460, +466, +334, +34, -111, -86, -179, -264, -241, -257, -328, -326, -184, -161, -161, -211, }, 29.262 + { +1659, +2476, +1676, +2229, +1972, +1422, +1669, +708, -448, -272, +296, +223, +206, +469, +501, +694, +819, +331, -104, -205, -133, -45, -56, -253, -357, -286, -277, -167, -214, -215, -128, -196, }, 29.263 + { +1539, +2551, +1891, +1969, +1762, +1252, +1228, +862, +110, -20, +303, +230, +166, +358, +647, +849, +752, +128, -158, -145, -243, -82, -52, -123, -279, -382, -292, -181, -163, -170, -155, -213, }, 29.264 + { +1700, +2807, +1619, +1270, +1372, +1179, +1161, +1231, +504, +52, +504, +136, +92, +640, +736, +453, +675, +669, -252, -473, -51, +20, -170, -152, -154, -240, -345, -332, -109, -89, -138, -173, }, 29.265 + { +1694, +2657, +1452, +968, +771, +1023, +1613, +1199, +359, +667, +624, -76, +382, +536, +594, +753, +564, +532, +330, -84, -457, -257, +116, +14, -260, -224, -186, -331, -270, -123, -32, -136, }, 29.266 + { +1868, +2708, +1232, +929, +844, +827, +1033, +736, +424, +738, +823, +481, +179, +246, +857, +667, +444, +613, +612, +119, -110, -152, -501, -78, +116, -202, -290, -173, -262, -254, -131, -141, }, 29.267 + { +2010, +2795, +1111, +875, +1109, +1106, +857, -4, -401, +861, +1319, +394, +265, +408, +467, +655, +737, +455, +536, +705, +304, -158, -205, -280, -395, +24, +44, -233, -199, -207, -233, -158, }, 29.268 + { +2330, +2991, +964, +1027, +1208, +1180, +792, -487, -765, +646, +1124, +466, +294, +78, +501, +769, +452, +561, +675, +354, +514, +630, -115, -307, -312, -411, -176, +29, -28, -209, -223, -273, }, 29.269 + { +2824, +3565, +965, +943, +1112, +1083, +667, -717, -987, +738, +1121, +2, +110, +106, +412, +576, +458, +606, +513, +519, +535, +409, +396, +221, -406, -363, -190, -297, -93, +42, -95, -282, }, 29.270 + { +3349, +3983, +872, +1076, +1173, +1134, +531, -1288, -1216, +1017, +1171, -131, -155, -369, +349, +670, +365, +458, +453, +375, +399, +660, +331, +266, +204, -128, -309, -306, -200, -192, -42, -94, }, 29.271 + { +3961, +4442, +707, +1254, +1277, +1123, +361, -1769, -1366, +1301, +1136, -328, -227, -538, +131, +409, +403, +542, +281, +118, +332, +560, +285, +456, +66, +169, +247, -283, -261, -198, -228, -289, }, 29.272 + { +4686, +5052, +536, +1343, +1245, +1005, +207, -2188, -1265, +1645, +926, -588, -346, -640, +177, +285, +106, +548, +311, +27, +151, +303, +255, +325, +75, +299, +196, +155, +118, -260, -236, -300, }, 29.273 + { +5534, +5563, +318, +1536, +1252, +806, -127, -2646, -995, +2082, +649, -787, -525, -824, +252, +141, +115, +500, +81, -14, +111, +227, +28, +135, -85, +201, +321, +171, +203, +214, -19, -500, }, 29.274 + { +6386, +6175, +93, +1727, +1236, +541, -519, -3046, -559, +2421, +322, -926, -609, -965, +269, -57, +33, +671, -21, -197, +21, +165, +4, +40, -436, +106, +232, +49, +425, +144, +66, +0, }, 29.275 + { +7130, +6925, -88, +1879, +1277, +209, -950, -3419, -58, +2693, -41, -998, -710, -991, +321, -320, -82, +770, -64, -189, -88, -19, +13, -38, -523, -42, -30, +68, +150, +89, +365, -23, }, 29.276 + { +7792, +7702, -133, +1956, +1357, -128, -1415, -3772, +482, +2874, -375, -1048, -862, -936, +402, -512, -233, +760, -129, -149, -81, -155, -78, -100, -630, -36, -59, -442, +95, +280, +185, +75, }, 29.277 + { +8084, +8648, +147, +1800, +1588, -465, -1801, -4057, +739, +3060, -585, -1055, -1095, -889, +484, -597, -294, +651, -254, -145, -54, -182, -110, -282, -564, -209, -393, -202, +61, +14, +171, +1, }, 29.278 + { +7950, +9589, +964, +1429, +1845, -635, -2157, -4183, +602, +3177, -602, -1039, -1301, -965, +529, -614, -333, +613, -355, -295, -22, -253, -53, -255, -948, -322, -205, -347, -6, +31, +59, -71, }, 29.279 + { +7608, +10215, +2256, +1215, +1866, -509, -2499, -4150, +252, +3102, -462, -1007, -1377, -1131, +543, -620, -361, +628, -344, -407, -176, -143, -39, -636, -843, -265, -361, -355, -99, +51, +143, +45, }, 29.280 + { +7478, +10350, +3382, +1641, +1562, -364, -2671, -4182, +82, +2795, -422, -952, -1415, -1234, +496, -705, -369, +637, -288, -460, -139, -421, -273, -301, -1004, -427, -393, -387, -99, +121, +207, -128, }, 29.281 + { +7601, +10277, +3938, +2546, +1409, -546, -2604, -4195, -39, +2430, -446, -937, -1542, -1235, +449, -844, -397, +623, -239, -176, -592, -583, -41, -478, -953, -587, -540, -343, +32, +110, -10, -156, }, 29.282 + { +7999, +10060, +3982, +3415, +1699, -807, -2609, -3807, -190, +1946, -508, -758, -1860, -1306, +494, -1071, -466, +696, -160, -448, -342, -561, -316, -440, -936, -533, -717, -285, -33, -87, +138, +52, }, 29.283 + { +8868, +9667, +3696, +4220, +1884, -786, -2974, -3169, -25, +1022, -611, -333, -2076, -1587, +587, -1486, -187, +551, -545, +152, -427, -718, -238, -557, -971, -356, -742, -544, -186, +78, +286, -144, }, 29.284 + { +10008, +9228, +3019, +5173, +1730, -514, -3173, -2654, +674, -266, -982, +303, -2059, -1915, +478, -1617, -384, +327, -296, +313, -485, -639, -255, -549, -996, -197, -986, -652, +62, -23, +48, -97, }, 29.285 + { +11234, +8968, +1867, +6284, +1449, -576, -2850, -2320, +1671, -1457, -1966, +1061, -1777, -2251, +610, -2387, -502, +717, -908, +856, -362, -807, -179, -457, -950, -356, -981, -565, +70, -205, +52, -184, }, 29.286 + { +12424, +9043, +307, +7301, +1477, -1225, -2226, -1811, +2733, -2240, -3502, +1512, -1095, -2186, +52, -2767, -416, +476, -1043, +1163, -163, -967, -182, -310, -939, -309, -1033, -648, +172, -197, -66, -313, }, 29.287 + { +13850, +9410, -1577, +7710, +1903, -2007, -1727, -1126, +3784, -2445, -5373, +1368, +274, -2547, -214, -2859, -931, +830, -1404, +1283, +192, -1142, -131, -304, -939, -130, -968, -870, +367, -211, -179, -446, }, 29.288 + { +15689, +10650, -4191, +6439, +2855, -1819, -1216, -1122, +4356, -1735, -7082, +796, +1337, -2613, -354, -3165, -1020, +960, -1511, +1143, +338, -957, -254, -411, -1003, +93, -787, -961, +276, -120, -242, -590, }, 29.289 + { +17568, +11974, -6732, +4560, +3824, -1109, -754, -1349, +4606, -843, -8100, -287, +1911, -2056, -658, -3260, -1157, +899, -1412, +975, +487, -915, -443, -511, -909, +161, -686, -992, +148, +70, -223, -830, }, 29.290 + { +19484, +13084, -9012, +2638, +4382, +24, -354, -1619, +4661, +92, -8630, -1472, +1971, -1185, -834, -3443, -1007, +624, -1325, +1001, +434, -935, -492, -574, -862, +109, -756, -815, +84, +193, -327, -1033, }, 29.291 + { +21524, +13678, -10956, +1222, +4385, +1297, -139, -2069, +5017, +1156, -9307, -2582, +2096, -601, -528, -3661, -796, +152, -1389, +1321, +257, -1041, -461, -535, -1092, +104, -751, -637, +26, +127, -265, -1109, }, 29.292 + { +23605, +13718, -12574, +568, +3860, +2238, -103, -2760, +6167, +2019, -10424, -3226, +2099, -412, +299, -3787, -992, -294, -1323, +1597, -108, -1067, -318, -600, -1468, +200, -723, -642, -34, +135, -184, -1205, }, 29.293 + { +25071, +14148, -13932, +471, +3008, +2768, -76, -3611, +7895, +2700, -11593, -3451, +1646, -185, +1383, -3748, -1496, -431, -1263, +1534, -312, -957, -121, -752, -1802, +171, -636, -694, -65, +159, -201, -1248, }, 29.294 + { +26816, +13743, -14786, +862, +1921, +2946, -342, -4385, +10015, +2577, -12171, -3354, +671, +309, +2238, -3598, -1940, -465, -1278, +1149, -315, -796, +17, -1000, -2051, +76, -546, -729, -117, +138, -282, -1090, }, 29.295 + { +27951, +14104, -15590, +1273, +860, +2927, -633, -4986, +11529, +2744, -11887, -3827, +2, +498, +2997, -3184, -2478, -171, -1514, +556, -142, -469, -72, -1148, -2207, -3, -362, -847, -143, +170, -197, -1176, }, 29.296 + { +28803, +14580, -16123, +1472, -187, +3073, -1250, -5325, +12182, +3270, -11190, -4406, -641, +391, +3646, -2789, -2835, +205, -1933, -111, +62, -112, -330, -1167, -2390, +48, -212, -1112, -86, +341, -303, -1353, }, 29.297 + { +30323, +13889, -15910, +1407, -1171, +3553, -2383, -5267, +12463, +3540, -10099, -4882, -1197, +116, +4331, -2625, -2785, +375, -2274, -723, +301, +72, -494, -1132, -2662, +359, -286, -1255, +88, +360, -528, -1375, }, 29.298 + { +30968, +14210, -15671, +1048, -1781, +3667, -3019, -5566, +12074, +4371, -8903, -5378, -1555, -380, +4891, -2272, -2787, +479, -2516, -1197, +410, +143, -580, -995, -2832, +409, -254, -1218, +75, +188, -590, -1406, }, 29.299 + { +30975, +15165, -15312, +546, -2218, +3398, -2954, -6444, +11217, +5687, -7852, -5572, -1909, -880, +5215, -1819, -2692, +359, -2645, -1443, +355, +103, -656, -709, -2922, +164, -25, -1239, -84, +72, -690, -1273, }, 29.300 + { +30424, +16368, -14573, +92, -2674, +2748, -2205, -7930, +10058, +7372, -7052, -5344, -2312, -1403, +5238, -1260, -2430, -1, -2723, -1529, +312, -177, -560, -464, -2980, -55, -69, -1190, -231, -99, -594, -932, }, 29.301 + { +29455, +17526, -13363, -127, -3235, +1964, -1140, -9860, +8781, +9245, -6389, -4845, -2498, -2034, +4995, -530, -2084, -491, -2825, -1345, +221, -559, -398, -274, -2983, -380, -142, -1168, -371, +10, -384, -724, }, 29.302 + { +28118, +18400, -11563, -157, -4012, +1308, -199, -11792, +7222, +10997, -5639, -4233, -2301, -2934, +4504, +364, -1845, -1024, -2737, -1299, +240, -966, -422, -53, -3194, -483, -435, -1176, -132, +127, -258, -452, }, 29.303 + { +26552, +19152, -9368, -160, -4867, +986, +473, -13162, +5114, +12399, -4354, -3860, -1375, -4191, +3967, +1296, -1787, -1124, -2703, -1337, +286, -1074, -1007, +244, -3127, -928, -436, -993, +94, +254, +31, -338, }, 29.304 + { +24559, +20217, -7367, -220, -5053, +163, +912, -13440, +2241, +12957, -1945, -4140, -3, -5230, +2779, +2633, -1975, -895, -2652, -1685, +399, -1133, -1787, +451, -3100, -1099, -141, -1148, +476, +550, +59, -556, }, 29.305 + { +23258, +20668, -6394, +41, -4001, -1343, +259, -12280, -447, +12376, +814, -4410, +990, -5553, +1277, +3778, -1842, -823, -2296, -2428, +66, -675, -2623, +69, -2488, -1174, +108, -1212, +763, +685, -33, -620, }, 29.306 + { +23142, +19464, -5694, +1043, -3149, -2286, -1288, -10731, -2354, +11827, +2425, -4171, +1875, -6154, +693, +4142, -1325, -613, -2234, -3206, -20, -772, -3178, +251, -2328, -913, +289, -1277, +940, +736, -150, -671, }, 29.307 + { +22552, +18662, -5393, +2289, -1879, -3683, -2436, -8894, -4473, +11069, +4563, -5019, +3166, -6153, -527, +5142, -1047, -592, -2109, -3335, -857, -775, -3407, +489, -1798, -1280, +535, -1129, +1014, +574, -236, -416, }, 29.308 + { +22401, +17758, -5842, +3364, -812, -4784, -3176, -6717, -5712, +8976, +6974, -6176, +3397, -4371, -2591, +6388, -734, -1317, -1243, -3549, -1586, -824, -3469, +452, -886, -1990, +679, -751, +619, +748, -301, -324, }, 29.309 + { +22309, +16537, -6181, +4660, -360, -5405, -3571, -5406, -6202, +6988, +8656, -6084, +2058, -2265, -3682, +6212, +772, -2272, -843, -3239, -2023, -881, -3727, +370, -424, -2103, +394, -539, +433, +863, -135, -441, }, 29.310 + { +21791, +15541, -6192, +5616, -505, -5546, -3072, -4658, -6616, +5207, +9841, -5865, +904, -1208, -3643, +5823, +1664, -2499, -798, -2591, -2431, -478, -3918, -635, -47, -1868, +308, -596, +226, +890, +22, -361, }, 29.311 + { +21324, +14642, -6583, +6799, -1051, -6105, -1417, -3904, -7362, +3483, +10991, -5815, -496, +549, -4041, +4979, +2787, -2309, -896, -2206, -2499, +60, -3674, -2156, -266, -1362, +446, -246, -422, +573, +555, -41, }, 29.312 + { +20752, +13927, -7556, +7887, -383, -7140, -472, -2508, -7640, +1050, +11820, -4742, -2329, +2225, -4014, +3077, +4488, -1969, -1094, -1484, -3038, +789, -3176, -3637, -596, -1084, +354, +499, -803, -174, +1114, +269, }, 29.313 + { +19965, +13135, -8141, +8473, +760, -7513, -787, -971, -6960, -1942, +12233, -3129, -3764, +3112, -3442, +1359, +4791, -618, -1183, -1102, -2895, +601, -2684, -3990, -954, -1401, +153, +1055, -625, -482, +888, +405, }, 29.314 + { +19143, +11685, -8033, +9384, +754, -7209, -418, -807, -6484, -2771, +11238, -2375, -3772, +3580, -3133, +167, +4612, -12, -608, -927, -2580, +196, -2728, -3474, -1079, -1676, -444, +1107, -287, -167, +508, -54, }, 29.315 + { +17857, +10290, -7109, +9878, +454, -6436, -46, -1046, -5905, -3006, +10009, -1912, -3542, +3960, -2520, -1113, +4554, +356, -838, +40, -2468, -172, -2487, -3471, -559, -1557, -1179, +703, -47, +127, +577, -318, }, 29.316 + { +16296, +9009, -5714, +9900, +226, -5547, +70, -922, -5384, -3238, +8823, -1282, -3406, +3868, -1537, -1923, +3996, +793, -1145, +249, -1720, -492, -2325, -3083, -467, -1071, -1564, +201, -55, +203, +765, -336, }, 29.317 + { +15841, +6997, -6669, +11869, +1968, -7696, -859, +385, -4403, -1539, +6206, -3126, -2033, +3213, -1498, -707, +2441, -260, -30, +640, -527, +1221, -934, -1381, +294, -1105, -1226, -270, -1487, -1152, -350, -611, }, 29.318 + { +13568, +6667, -4985, +10337, +1992, -6022, -629, +40, -3621, -1574, +5221, -2329, -1990, +2774, -1185, -903, +2184, +6, -131, +493, -301, +1057, -963, -1225, +288, -1053, -961, -56, -1078, -893, -506, -522, }, 29.319 + { +11497, +6501, -3490, +8587, +2327, -4433, -803, -59, -2956, -1671, +4442, -1603, -1990, +2273, -678, -964, +1803, +277, -100, +341, -258, +879, -733, -1205, +106, -817, -829, +182, -726, -774, -439, -507, }, 29.320 + { +9657, +6295, -2357, +7055, +2839, -3195, -922, +87, -2426, -1717, +3756, -1022, -1971, +1799, -285, -852, +1503, +322, +17, +329, -329, +745, -562, -1092, +21, -498, -600, +37, -450, -530, -354, -499, }, 29.321 + { +8080, +5958, -1527, +5929, +3206, -2314, -807, +279, -2098, -1713, +3210, -663, -1953, +1446, +14, -682, +1140, +403, +168, +150, -283, +600, -477, -850, +175, -366, -595, +17, -334, -374, -332, -390, }, 29.322 + { +6742, +5563, -934, +5119, +3472, -1654, -579, +468, -1830, -1693, +2733, -440, -1854, +1199, +270, -615, +927, +597, +39, +58, -146, +541, -282, -642, +203, -260, -523, -66, -324, -342, -189, -288, }, 29.323 + { +5645, +5082, -470, +4564, +3569, -1149, -280, +632, -1648, -1657, +2279, -195, -1747, +997, +500, -550, +854, +535, -56, +205, +54, +502, -244, -453, +284, -250, -567, -159, -320, -231, -40, -147, }, 29.324 + { +4739, +4548, -15, +4161, +3424, -612, +92, +576, -1502, -1483, +1923, -133, -1573, +1049, +513, -481, +827, +418, +204, +407, -41, +456, -23, -319, +105, -295, -566, -165, -125, -78, -45, -303, }, 29.325 + { +4000, +4116, +315, +3739, +3361, -78, +141, +471, -1088, -1423, +1428, +104, -1192, +778, +494, -118, +776, +531, +352, +301, +46, +496, -16, -403, -75, -250, -372, +7, -75, -290, -272, -334, }, 29.326 + { +3315, +3731, +744, +3252, +3208, +505, +104, +326, -724, -1258, +1022, +253, -920, +621, +766, +320, +638, +429, +479, +312, +62, +342, -149, -425, +78, -14, -324, -163, -364, -342, -177, -191, }, 29.327 + { +2721, +3507, +1076, +2691, +3219, +926, -155, +334, -235, -1266, +533, +565, -478, +790, +1052, +241, +481, +577, +434, +197, -68, +166, +67, -116, +62, -279, -535, -276, -242, -195, -120, -171, }, 29.328 + { +2164, +3272, +1472, +2240, +2998, +1160, -8, +380, -347, -1061, +577, +981, +39, +670, +997, +273, +443, +502, +183, +101, +156, +367, +108, -320, -359, -368, -337, -186, -156, -185, -219, -252, }, 29.329 + { +1934, +3190, +1503, +1841, +2991, +1228, -234, +344, -22, -479, +868, +985, +160, +811, +840, +155, +222, +329, +446, +340, +153, +57, -306, -454, -236, -196, -253, -198, -267, -270, -212, -218, }, 29.330 + { +1850, +2863, +1570, +2109, +2264, +770, +377, +952, +272, -269, +977, +887, +259, +859, +502, -89, +465, +710, +360, -49, -274, -104, -140, -299, -180, -223, -354, -327, -223, -222, -195, -175, }, 29.331 + { +1880, +2606, +1259, +1967, +2141, +1272, +1090, +983, +171, -143, +1137, +1038, +78, +386, +659, +433, +428, +299, -214, -286, +0, +94, -163, -340, -274, -342, -349, -267, -185, -155, -161, -219, }, 29.332 + { +1397, +2225, +1498, +2218, +2597, +1375, +970, +1179, +446, +55, +983, +782, +92, +766, +779, +21, -117, -30, -43, +45, +38, -51, -292, -398, -291, -331, -321, -187, -130, -199, -179, -163, }, 29.333 + { +1635, +3062, +2249, +1880, +1916, +1343, +1114, +965, +534, +333, +634, +1026, +601, -88, -96, -36, +19, +140, +79, -54, -187, -223, -327, -363, -331, -232, -228, -189, -124, -136, -165, -244, }, 29.334 + { +1621, +2982, +2331, +1859, +1672, +1505, +1317, +1168, +916, +338, +486, +1012, +283, -527, -167, +103, +151, +173, -30, -202, -207, -185, -337, -340, -290, -264, -241, -183, -115, -121, -178, -226, }, 29.335 + { +1602, +2643, +1775, +1564, +1563, +1546, +1646, +1829, +1322, +708, +618, +118, +151, +107, -304, -55, +284, +102, -151, -125, -138, -202, -309, -317, -234, -259, -302, -184, -120, -109, -170, -206, }, 29.336 + { +1689, +2725, +1687, +1342, +1018, +1221, +1839, +1792, +1379, +895, +468, +478, +768, +67, -215, -9, -169, +55, +46, -227, -303, -177, -209, -261, -200, -191, -162, -205, -213, -154, -174, -239, }, 29.337 + { +1884, +2685, +1171, +1190, +1175, +880, +977, +1283, +1525, +1401, +1097, +684, +686, +975, +274, -642, -241, -46, -48, +8, -211, -255, -203, -172, -169, -156, -217, -131, -186, -249, -160, -234, }, 29.338 + { +1711, +2523, +1308, +1090, +1055, +1174, +1022, +299, +477, +1301, +1459, +1119, +863, +804, +1042, +601, -340, -501, -204, -29, -21, -94, -220, -196, -156, -184, -116, -170, -201, -183, -255, -271, }, 29.339 + { +1817, +2536, +946, +809, +944, +1085, +1157, +217, -175, +767, +1098, +779, +1147, +1424, +1313, +1026, +631, +198, -302, -492, -270, -64, -131, -189, -253, -238, -160, -88, -70, -213, -184, -209, }, 29.340 + { +2191, +2839, +854, +984, +1168, +1002, +768, -219, -19, +1063, +561, +60, +636, +861, +1348, +1294, +885, +891, +475, -73, -432, -506, -288, -67, -118, -220, -240, -103, -74, -138, -148, -245, }, 29.341 + { +2451, +2833, +673, +1459, +1780, +1173, +305, -947, -35, +1449, +504, -211, +108, +410, +948, +640, +824, +1192, +884, +675, +272, -177, -565, -472, -224, -108, -84, -125, -187, -164, -89, -188, }, 29.342 + { +3086, +3702, +648, +1075, +1515, +1169, +441, -1098, -143, +1309, +271, -221, +106, +208, +526, +378, +428, +792, +941, +752, +488, +344, +62, -247, -504, -376, -181, +22, -47, -250, -217, -168, }, 29.343 + { +3569, +4097, +532, +1316, +1840, +1093, -29, -1514, +254, +1604, -129, -469, -58, +189, +685, +94, +33, +566, +399, +418, +683, +566, +398, +298, -51, -324, -429, -122, -77, -175, -112, -284, }, 29.344 + { +4125, +4461, +378, +1609, +2191, +994, -587, -1865, +674, +1689, -401, -500, -250, +88, +680, -19, +36, +317, +78, +227, +154, +381, +584, +347, +348, +259, -144, -157, -249, -295, -182, -189, }, 29.345 + { +4867, +5214, +256, +1466, +2150, +866, -894, -1915, +1051, +1495, -779, -414, -262, +45, +633, -205, +3, +311, -89, +0, -11, +125, +199, +237, +418, +383, +270, +312, -107, -370, -261, -364, }, 29.346 + { +5316, +5480, +203, +2110, +2686, +411, -1842, -1931, +1799, +1361, -1123, -406, -380, +95, +608, -401, +32, +304, -272, -6, -184, -72, +198, -153, +69, +403, +277, +536, +348, -42, -176, -397, }, 29.347 + { +5892, +6233, +160, +2100, +2860, +142, -2433, -1800, +2326, +963, -1427, -273, -439, +158, +610, -591, -43, +281, -390, -16, -246, -165, +68, -360, -9, +156, +82, +484, +326, +166, +189, -170, }, 29.348 + { +6296, +6975, +282, +2083, +3088, -133, -3093, -1657, +2878, +590, -1820, -143, -472, +190, +638, -719, -106, +233, -510, -92, -328, -237, +113, -522, -223, +109, -26, +254, +179, +32, +200, +156, }, 29.349 + { +6592, +7845, +648, +1757, +3189, -161, -3619, -1575, +3255, +370, -2151, -143, -426, +168, +727, -779, -195, +244, -572, -180, -428, -336, +66, -505, -282, -26, -117, +217, +77, -98, +16, -149, }, 29.350 + { +6774, +8708, +1082, +1524, +3240, -264, -3922, -1540, +3434, +295, -2349, -304, -372, +149, +756, -675, -383, +223, -505, -236, -520, -494, -9, -552, -315, -62, -148, +121, +173, -299, -365, -62, }, 29.351 + { +6908, +9422, +1625, +1424, +3190, -389, -4004, -1611, +3471, +335, -2543, -391, -396, +68, +811, -604, -534, +182, -441, -272, -536, -643, -94, -634, -428, -131, -91, +267, -223, -392, -234, -275, }, 29.352 + { +7138, +10189, +2126, +1133, +2968, -382, -3722, -1762, +3018, +580, -2559, -606, -255, -134, +669, -325, -681, -12, -293, -317, -621, -648, -141, -715, -656, -53, -111, -126, -38, -347, -470, -236, }, 29.353 + { +7313, +10455, +2943, +1070, +2390, +272, -3497, -2310, +2731, +755, -2380, -670, -474, -246, +602, -255, -558, -320, -482, -158, -477, -799, -319, -604, -503, -410, -501, +108, -160, -398, -359, -347, }, 29.354 + { +7826, +10161, +3173, +1967, +2130, +423, -3555, -2463, +2451, +634, -1952, -839, -706, -181, +512, -312, -450, -587, -636, +17, -569, -882, -377, -371, -655, -672, -473, -170, -109, -345, -438, -377, }, 29.355 + { +8467, +9477, +3103, +3430, +2024, +440, -3655, -2401, +2236, -26, -1277, -712, -1114, -26, +375, -495, -221, -726, -826, +29, -851, -620, -323, -809, -370, -647, -794, -102, -163, -412, -424, -337, }, 29.356 + { +9286, +8516, +2179, +5700, +2660, -483, -3558, -1721, +1619, -1074, -311, -359, -1649, +39, +247, -528, -41, -857, -1059, -36, -827, -638, -733, -625, -208, -781, -693, -299, -176, -287, -276, -526, }, 29.357 + { +10487, +8297, +724, +7001, +3276, -1546, -2976, -375, +714, -2874, +551, +663, -2103, -61, +34, -604, +320, -1061, -1370, +301, -1334, -957, -278, -1039, -89, -630, -732, -236, -218, -112, -316, -769, }, 29.358 + { +11694, +8483, -1085, +7688, +4377, -2639, -2748, +1388, +290, -5170, +695, +2234, -2233, -376, -167, -879, +703, -1107, -1401, -21, -1755, -792, -436, -1099, +19, -701, -676, +56, -177, -420, -299, -499, }, 29.359 + { +12813, +8986, -2960, +7720, +5822, -3441, -2888, +3186, +503, -7344, -143, +3835, -1619, -861, -365, -1277, +915, -643, -1945, -184, -1723, -1371, -165, -1036, -149, -608, -623, +361, -273, -675, -81, -360, }, 29.360 + { +14282, +9854, -5144, +6666, +7543, -3247, -3573, +4303, +1159, -8673, -1552, +4734, -435, -1066, -737, -1669, +1323, -711, -2400, +154, -2059, -1735, -117, -896, -79, -641, -571, +431, -255, -662, -37, -376, }, 29.361 + { +15850, +10514, -7059, +5564, +8654, -2773, -4154, +5402, +1737, -9668, -3061, +5015, +1018, -866, -1440, -1886, +1527, -978, -2388, +41, -2052, -1988, -323, -629, -13, -650, -699, +444, -203, -546, -140, -354, }, 29.362 + { +17808, +11057, -9134, +4383, +9339, -1778, -4546, +6062, +2149, -10167, -4257, +4712, +2487, -456, -1988, -2239, +1739, -1173, -2546, +134, -2148, -2055, -395, -540, +91, -587, -935, +488, -19, -574, -174, -369, }, 29.363 + { +20383, +11132, -11423, +3225, +9645, -449, -4728, +6097, +2297, -10259, -4895, +4011, +3369, +308, -2432, -2790, +2050, -1452, -2764, +266, -2368, -1811, -610, -479, +220, -714, -1063, +583, +89, -687, -231, -413, }, 29.364 + { +22418, +11798, -13840, +2373, +9532, +812, -4649, +5776, +2876, -10183, -5672, +3197, +3848, +1355, -2692, -3324, +2269, -1738, -2840, +474, -2481, -1785, -640, -534, +229, -841, -1060, +727, -62, -819, -169, -447, }, 29.365 + { +24894, +11396, -15645, +2370, +8933, +1292, -4281, +5629, +3954, -10488, -6364, +2682, +3969, +2394, -2882, -3405, +2175, -2174, -2424, +697, -2794, -1803, -440, -660, +159, -906, -842, +819, -413, -760, -126, -429, }, 29.366 + { +26219, +12293, -17420, +2685, +7926, +1207, -3924, +5306, +5940, -10486, -7929, +2418, +4103, +2810, -2438, -3395, +1620, -2289, -1991, +723, -2963, -1849, -215, -902, +78, -722, -742, +870, -694, -718, -23, -517, }, 29.367 + { +28416, +11175, -18030, +3639, +6517, +524, -3997, +5626, +7964, -10885, -9328, +2435, +4025, +2769, -1736, -3204, +870, -2252, -1569, +634, -3242, -1541, -240, -1235, +91, -529, -623, +850, -941, -678, +99, -756, }, 29.368 + { +29176, +11689, -18551, +4399, +5252, -160, -4585, +5761, +10465, -11051, -10563, +2051, +3915, +2524, -384, -3448, +237, -1642, -1718, +678, -3401, -1225, -371, -1551, +5, -226, -521, +663, -896, -768, +144, -1146, }, 29.369 + { +29021, +13077, -18841, +4810, +4427, -776, -5593, +5564, +12643, -10486, -11302, +1156, +3758, +2201, +1006, -3601, -405, -695, -2158, +611, -3242, -1002, -587, -1809, -96, +32, -433, +355, -533, -1081, -66, -1282, }, 29.370 + { +30639, +12013, -18276, +5087, +3533, -892, -7519, +6359, +13438, -9871, -11200, +130, +3528, +2142, +1859, -3611, -530, -415, -2173, +244, -2952, -752, -1000, -1830, -214, +226, -496, +424, -528, -1428, -247, -1261, }, 29.371 + { +31129, +12133, -17589, +4753, +3258, -1123, -8951, +6078, +13955, -8365, -10965, -1246, +3253, +2362, +2106, -3221, -543, -421, -2041, -9, -2564, -798, -1213, -1842, -312, +214, -362, +364, -897, -1374, -502, -1281, }, 29.372 + { +30719, +13121, -16780, +4200, +3198, -1555, -9649, +4676, +14307, -6216, -10726, -2675, +2883, +2776, +1878, -2607, -273, -769, -1833, +57, -2369, -947, -1301, -1967, -305, +248, -529, +122, -1019, -1330, -719, -996, }, 29.373 + { +29697, +14733, -15818, +3462, +3061, -1780, -9577, +2144, +14501, -3727, -10382, -3699, +2209, +3218, +1410, -1818, +264, -1375, -1409, +257, -2249, -1183, -1411, -1971, -160, -60, -974, +340, -1284, -1182, -516, -1030, }, 29.374 + { +28002, +16846, -14478, +2412, +2676, -1519, -8873, -1372, +14440, -1063, -9859, -4131, +1096, +3328, +1195, -1203, +1073, -1927, -1076, +655, -2259, -1480, -1460, -1775, -599, -341, -1181, +468, -1245, -932, -470, -1164, }, 29.375 + { +25869, +18455, -12266, +1637, +1978, -1262, -8280, -4934, +14128, +1672, -9443, -4041, -152, +2529, +1995, -1259, +1882, -1726, -1545, +1491, -2530, -1653, -1433, -2120, -1079, -408, -1374, +717, -856, -1223, -178, -1188, }, 29.376 + { +24864, +17912, -9358, +1641, +576, -357, -8615, -7257, +13351, +3934, -9073, -3482, -838, +841, +3250, -1322, +2217, -796, -2111, +1754, -2153, -2158, -1467, -2434, -1624, -253, -1302, +874, -576, -1341, -96, -1263, }, 29.377 + { +23420, +17860, -6501, +1165, -717, +588, -8140, -9637, +11644, +6449, -8639, -3126, -461, -1536, +4057, -378, +1614, +434, -2303, +1248, -1439, -2499, -1782, -2484, -2002, -134, -998, +651, -243, -1476, -235, -998, }, 29.378 + { +22006, +18635, -5893, +1609, -295, -1121, -6611, -10352, +8438, +8556, -7366, -3845, +1086, -3469, +3525, +1549, +597, +1088, -1819, +227, -740, -2416, -2356, -1773, -2500, -256, -642, +230, -150, -1358, -351, -903, }, 29.379 + { +22224, +17778, -6386, +3076, +518, -3282, -6409, -9035, +5543, +9128, -5573, -4587, +2339, -4194, +2628, +2481, +473, +849, -1362, -75, -999, -1551, -2497, -1277, -2514, -1057, -402, -20, +22, -1408, -555, -809, }, 29.380 + { +22103, +17015, -6884, +4461, +1233, -5006, -6070, -7906, +2832, +9189, -3231, -5657, +3433, -4282, +1463, +3242, -717, +1493, -1177, -711, -254, -881, -2411, -866, -2491, -1884, -465, -353, +374, -1387, -1115, -592, }, 29.381 + { +22560, +15777, -7251, +5550, +797, -5686, -5009, -7186, +427, +9113, -1133, -6601, +3854, -2859, -422, +3276, -587, +291, -113, -529, +173, -114, -2517, -809, -1886, -2312, -1324, -304, +246, -1137, -1252, -701, }, 29.382 + { +22731, +15350, -9222, +6868, +2173, -7663, -4747, -4975, -1211, +7055, +1768, -6971, +2930, -1113, -1589, +2833, -506, -636, +510, +745, -151, +413, -2257, -1147, -1254, -2415, -1827, -858, -136, -928, -699, -812, }, 29.383 + { +23304, +14017, -11279, +9072, +3099, -9814, -4178, -2550, -2580, +4834, +3988, -6788, +1843, +177, -2381, +2443, -295, -988, +882, +1070, +364, +564, -2129, -1074, -1171, -2223, -1782, -1409, -1115, -600, -62, -717, }, 29.384 + { +23618, +12255, -12665, +11454, +3209, -11235, -3282, -912, -3248, +2468, +5358, -5978, +1078, +518, -3093, +2872, +91, -1576, +1462, +574, +484, +1620, -2554, -835, -966, -2532, -1116, -1629, -2136, -622, +243, -448, }, 29.385 + { +23507, +10176, -12976, +13613, +2604, -11794, -2177, +221, -4379, +941, +6866, -5844, +60, +1571, -3421, +2227, +1420, -1610, +744, +868, +160, +1913, -1757, -1375, -527, -2462, -1299, -900, -2681, -1245, +284, -163, }, 29.386 + { +22437, +8395, -11784, +14554, +1462, -10835, -1161, -107, -4923, +595, +7185, -5944, -419, +2664, -3581, +1327, +2496, -1354, +156, +805, -57, +1910, -1336, -1388, -199, -2269, -1525, -558, -2342, -1654, -242, -88, }, 29.387 + { +20519, +7379, -9918, +14135, +1130, -9407, -1215, -80, -4674, -389, +7077, -5070, -1127, +3004, -2779, +575, +2442, -923, +375, +352, -401, +2124, -1583, -1128, +325, -2275, -1384, -459, -2045, -1486, -593, -444, }, 29.388 + { +18163, +7171, -8342, +13120, +1703, -8708, -1203, +485, -4645, -1323, +6947, -3981, -1909, +3255, -1914, -231, +2372, -512, +246, +503, -605, +1638, -1102, -1353, +431, -1611, -1452, -256, -1866, -1326, -460, -644, }, 29.389 + { +14734, +5366, -4938, +13261, +853, -8371, +138, +318, -3336, +134, +2204, -3293, +1697, +2006, -2237, -277, +1106, -520, -774, +253, -99, +68, -412, +780, +809, +219, +346, -370, -906, -336, -779, -1298, }, 29.390 + { +12591, +5345, -3597, +11397, +1333, -6737, -45, +46, -2876, +145, +2069, -2657, +1229, +1805, -1739, -516, +791, -312, -657, +44, -12, +385, -291, +437, +830, +261, +90, -313, -700, -424, -611, -816, }, 29.391 + { +10805, +5339, -2604, +9725, +1921, -5525, -310, +43, -2429, +58, +1959, -2032, +690, +1674, -1216, -766, +650, -159, -575, +29, +105, +445, -262, +423, +590, +102, +242, -169, -667, -426, -434, -541, }, 29.392 + { +9340, +5201, -1982, +8478, +2304, -4592, -320, +86, -2009, +7, +1880, -1679, +320, +1616, -995, -817, +572, -17, -496, +83, +280, +281, -168, +371, +343, +122, +380, -5, -602, -322, -317, -483, }, 29.393 + { +8188, +4843, -1495, +7540, +2395, -3667, -312, +176, -1589, -77, +1770, -1446, +114, +1442, -804, -782, +564, +82, -423, +254, +211, +181, -62, +208, +366, +208, +389, +140, -452, -279, -247, -426, }, 29.394 + { +7139, +4447, -1005, +6621, +2495, -2780, -305, +313, -1320, -50, +1606, -1337, +16, +1312, -654, -711, +624, +129, -237, +218, +117, +290, -83, +217, +421, +287, +411, +153, -317, -192, -175, -342, }, 29.395 + { +6157, +4147, -661, +5795, +2719, -2091, -278, +447, -1015, -108, +1345, -1106, -12, +1133, -544, -455, +616, +156, -87, +162, +222, +352, -56, +280, +494, +294, +391, +184, -187, +6, -183, -528, }, 29.396 + { +5279, +3795, -302, +5095, +2792, -1423, -200, +524, -834, -167, +1181, -897, -46, +946, -299, -307, +520, +329, -7, +248, +337, +305, +68, +311, +476, +300, +386, +295, -101, -189, -428, -616, }, 29.397 + { +4525, +3459, -28, +4546, +2834, -885, -89, +549, -694, -192, +1043, -644, -76, +759, -74, -153, +593, +505, +119, +343, +347, +334, +158, +340, +453, +359, +386, +40, -308, -328, -435, -568, }, 29.398 + { +3930, +3246, +221, +4012, +2721, -518, +143, +558, -699, -125, +1073, -572, -271, +859, +240, +26, +775, +548, +199, +453, +346, +378, +240, +360, +327, +89, +121, -123, -319, -354, -529, -642, }, 29.399 + { +3660, +3270, +329, +3382, +2495, -259, +336, +625, -667, -168, +978, -390, -146, +1158, +544, +64, +837, +706, +404, +422, +317, +415, +105, -19, +35, +69, +43, -172, -504, -539, -442, -551, }, 29.400 + { +3142, +2802, +557, +3432, +2389, -71, +540, +456, -686, +42, +1063, -160, +119, +1196, +649, +468, +1015, +684, +339, +353, +244, +13, -220, -126, +48, +81, -160, -332, -500, -382, -372, -555, }, 29.401 + { +2901, +2760, +686, +3156, +2256, -27, +369, +564, -227, +172, +1095, +54, +380, +1501, +986, +535, +850, +558, +60, -34, -144, -62, -229, -185, +27, -136, -229, -282, -406, -348, -382, -501, }, 29.402 + { +2508, +2594, +1005, +2823, +1909, +401, +624, +677, +80, +149, +1195, +622, +765, +1450, +899, +441, +488, -3, -301, -63, -155, -197, -378, -249, +15, -114, -216, -325, -386, -326, -435, -465, }, 29.403 + { +2206, +2342, +933, +2683, +2333, +903, +669, +761, +492, +499, +1258, +984, +954, +1127, +508, -78, +61, +24, -139, -253, -442, -276, -171, -30, -76, -244, -225, -191, -331, -440, -399, -321, }, 29.404 + { +1974, +2815, +1553, +2323, +2233, +1046, +992, +1282, +753, +707, +1323, +599, +390, +690, +158, -204, -61, -149, -350, -307, -284, -187, -98, -47, -143, -282, -239, -272, -323, -315, -319, -272, }, 29.405 + { +1654, +2776, +1836, +2401, +3022, +1959, +967, +1094, +948, +444, +652, +267, +140, +546, +166, -270, -194, -277, -387, -222, -184, -102, -101, -213, -211, -214, -174, -207, -336, -339, -249, -198, }, 29.406 + { +1869, +3354, +2494, +2832, +2716, +1654, +1450, +1127, +173, -258, +546, +432, -146, +288, +167, -560, -266, -9, -321, -261, -193, -155, -101, -190, -238, -205, -240, -223, -233, -279, -241, -223, }, 29.407 + { +2251, +4370, +3095, +2273, +2143, +1471, +1134, +828, +318, +171, +218, -108, -7, +202, -108, -329, -135, -186, -250, -123, -231, -173, -170, -206, -184, -240, -217, -223, -224, -243, -163, -183, }, 29.408 + { +2659, +4415, +2723, +1899, +1660, +1369, +1422, +927, +331, +708, +366, -215, -222, -87, +228, -79, -456, -205, +38, -181, -201, -158, -281, -171, -233, -218, -175, -209, -188, -206, -158, -146, }, 29.409 + { +2110, +3925, +2617, +1488, +1521, +1321, +1000, +1375, +1006, +577, +1002, +281, -242, +99, -57, -249, -82, -20, -257, -120, -41, -272, -333, -251, -182, -210, -176, -126, -157, -179, -176, -194, }, 29.410 + { +1815, +3251, +2187, +1550, +1381, +941, +1057, +773, +515, +1445, +1370, +807, +715, +171, +116, +49, -344, -256, +25, -69, -365, -300, -115, -199, -312, -112, -74, -117, -199, -216, -192, -267, }, 29.411 + { +1453, +2017, +1172, +1714, +1993, +1501, +661, -199, +441, +1198, +925, +1207, +1374, +1313, +1201, +202, -18, +29, -479, -298, -15, -198, -383, -148, -84, -172, -178, -112, -77, -224, -241, -216, }, 29.412 + { +1882, +2639, +981, +885, +1287, +1149, +657, -264, +342, +1130, +630, +742, +1292, +1636, +1472, +886, +568, +182, -94, -158, -412, -373, +6, -144, -402, -52, +23, -169, -270, -217, -171, -242, }, 29.413 + { +2138, +2960, +1101, +1064, +1446, +1136, +291, -438, +715, +1105, +64, +265, +594, +767, +1266, +1060, +858, +969, +438, -42, -101, -297, -344, -218, -121, -114, -231, -67, -73, -307, -272, -133, }, 29.414 + { +2460, +3291, +1078, +1222, +1735, +1211, -80, -710, +954, +1086, -141, +205, +328, +431, +693, +253, +688, +1146, +655, +645, +331, -174, -61, -188, -361, -99, -16, -187, -277, -187, -156, -227, }, 29.415 + { +2893, +3811, +1105, +1203, +1818, +1171, -395, -714, +1243, +818, -421, +245, +254, +371, +579, -124, +129, +613, +507, +652, +517, +400, +268, -71, -95, -9, -228, -164, -144, -359, -299, -148, }, 29.416 + { +3308, +4221, +1114, +1356, +2071, +1044, -891, -658, +1576, +583, -594, +223, +142, +308, +585, -177, -43, +346, +34, +199, +317, +405, +505, +368, +236, +145, +52, -93, -322, -363, -224, -252, }, 29.417 + { +3900, +4867, +998, +1260, +2220, +839, -1162, -422, +1621, +246, -664, +254, +85, +242, +512, -240, -75, +270, -146, -7, -102, +10, +325, +287, +509, +621, +248, +30, -87, -358, -365, -226, }, 29.418 + { +4379, +5375, +1025, +1329, +2414, +620, -1641, -92, +1872, -196, -752, +327, -63, +215, +556, -301, -147, +211, -180, -88, -262, -176, -67, -67, +404, +602, +521, +379, +47, -155, -101, -270, }, 29.419 + { +4917, +5923, +933, +1451, +2663, +215, -2061, +412, +1970, -661, -792, +379, -89, +99, +514, -309, -198, +208, -222, -155, -360, -296, -176, -258, +109, +365, +340, +336, +360, +108, +10, -101, }, 29.420 + { +5325, +6387, +1044, +1617, +2857, -114, -2569, +894, +2226, -1191, -880, +471, -93, +10, +443, -288, -328, +216, -163, -257, -444, -325, -267, -361, +2, +132, +152, +154, +168, +115, +205, +89, }, 29.421 + { +5680, +6946, +1250, +1595, +2986, -178, -3103, +1203, +2516, -1694, -900, +579, -179, -49, +355, -219, -348, +53, -131, -293, -494, -294, -363, -474, -96, +59, +126, -24, -77, -107, +65, +185, }, 29.422 + { +6420, +7593, +839, +1808, +3146, -725, -3065, +1505, +2329, -1963, -819, +612, -243, -161, +340, -128, -458, -62, -108, -328, -544, -296, -472, -531, -38, -40, +40, -115, -239, -173, -70, -95, }, 29.423 + { +6890, +8125, +798, +2033, +3239, -1037, -3175, +1581, +2439, -2196, -937, +706, -276, -254, +344, -74, -579, -163, -59, -291, -673, -428, -436, -541, -74, -59, -108, -153, -248, -283, -175, -228, }, 29.424 + { +7112, +8504, +1011, +2420, +3353, -1361, -3255, +1549, +2556, -2243, -1200, +741, -167, -319, +199, +28, -584, -316, +19, -391, -797, -406, -435, -548, -248, -164, +60, -169, -402, -374, -175, -285, }, 29.425 + { +7285, +8820, +1447, +2597, +3239, -1169, -3229, +1126, +2635, -2125, -1498, +885, -99, -519, +165, +47, -347, -428, -288, -299, -829, -481, -398, -641, -383, -145, +82, -141, -416, -423, -333, -478, }, 29.426 + { +7520, +8869, +2021, +2814, +2876, -582, -3127, +494, +2536, -1844, -1576, +724, +34, -625, -7, +239, -155, -630, -485, -225, -859, -553, -623, -612, -241, -315, +42, -51, -367, -610, -501, -479, }, 29.427 + { +7879, +8478, +2398, +3646, +2683, -425, -3110, +367, +2156, -1723, -1287, +263, +38, -359, -259, +217, +107, -737, -613, -82, -1068, -775, -685, -547, -228, -402, +0, +62, -472, -776, -425, -752, }, 29.428 + { +8205, +7639, +2366, +5376, +3131, -1245, -3272, +1332, +1408, -2244, -393, -194, -320, +234, -603, -6, +519, -774, -631, -35, -1347, -848, -738, -677, -167, -469, +8, -127, -364, -733, -690, -706, }, 29.429 + { +9071, +7121, +1359, +7044, +3754, -2464, -2808, +2381, +60, -2776, +793, -372, -1036, +563, -545, -275, +838, -803, -718, +19, -1374, -976, -1066, -680, +3, -628, -230, -55, -414, -742, -545, -882, }, 29.430 + { +10148, +7203, -207, +7831, +4875, -3407, -2535, +3529, -1225, -3617, +2016, -129, -1945, +583, -98, -688, +1031, -623, -939, +116, -1314, -1178, -1259, -633, -72, -818, -379, -21, -446, -673, -502, -1013, }, 29.431 + { +11044, +7769, -1943, +7882, +6483, -3989, -2591, +4784, -2149, -4901, +3054, +635, -2734, +50, +522, -825, +921, -244, -1180, +190, -1284, -1180, -1357, -904, -121, -897, -516, -101, -271, -733, -400, -911, }, 29.432 + { +11990, +8411, -3500, +7279, +8002, -4096, -2789, +6028, -2844, -6395, +3677, +1736, -3160, -867, +846, -555, +671, +81, -1262, +34, -1076, -1221, -1513, -1089, -353, -964, -456, -261, -256, -672, -256, -770, }, 29.433 + { +13335, +8653, -4769, +6560, +8870, -3919, -2715, +7255, -3621, -7665, +3846, +2827, -3088, -1854, +732, -91, +613, +191, -1151, -200, -889, -1355, -1616, -1202, -620, -945, -484, -248, -378, -527, -120, -768, }, 29.434 + { +14852, +8670, -5913, +6073, +9001, -3654, -2195, +8358, -4463, -8616, +3590, +3721, -2575, -2699, +236, +272, +868, +133, -945, -394, -1059, -1238, -1780, -1341, -641, -1048, -561, -27, -440, -570, -19, -740, }, 29.435 + { +16451, +8693, -7064, +5832, +8573, -3576, -1333, +9514, -5301, -9295, +3094, +4207, -1784, -3244, -399, +318, +1449, +54, -659, -662, -1314, -1021, -2073, -1203, -803, -1212, -404, +103, -451, -722, -56, -638, }, 29.436 + { +18423, +8132, -8075, +6128, +7681, -4035, +138, +10573, -6216, -9800, +2747, +4350, -1192, -3295, -1042, +104, +2016, +289, -589, -954, -1505, -917, -2153, -1097, -1071, -1185, -298, +285, -530, -966, -69, -449, }, 29.437 + { +20202, +8717, -10102, +5865, +7549, -3841, +390, +11057, -6161, -10160, +2346, +4324, -998, -3105, -1402, -423, +2652, +520, -1022, -905, -1505, -1084, -2016, -1271, -995, -1072, -334, +432, -570, -1222, +2, -286, }, 29.438 + { +22529, +8456, -11824, +5892, +7303, -4055, +930, +11197, -5866, -10497, +2199, +4298, -1350, -2705, -1409, -1011, +2979, +873, -1590, -561, -1535, -1262, -1879, -1318, -879, -952, -350, +491, -720, -1269, +134, -272, }, 29.439 + { +23974, +9134, -13513, +5844, +7038, -4057, +615, +11611, -4790, -11317, +1983, +4325, -1634, -2352, -1084, -1939, +3123, +1383, -1969, -242, -1583, -1428, -1611, -1435, -861, -839, -383, +423, -787, -1337, +408, -512, }, 29.440 + { +25044, +9817, -14614, +5833, +6675, -4269, -71, +12212, -3614, -11890, +1484, +4440, -1786, -1990, -859, -2687, +2944, +1877, -2005, -175, -1440, -1495, -1418, -1531, -909, -716, -428, +289, -816, -1306, +466, -753, }, 29.441 + { +26536, +9314, -14645, +5829, +6191, -4884, -796, +12908, -2788, -12074, +1081, +4219, -1691, -1613, -960, -3033, +2556, +2030, -1647, -335, -1214, -1268, -1603, -1435, -985, -580, -535, +122, -796, -1260, +177, -737, }, 29.442 + { +27183, +9606, -14376, +5620, +5875, -5416, -2052, +13586, -1628, -12058, +571, +3654, -1110, -1358, -1213, -3155, +2048, +1957, -895, -643, -907, -799, -1977, -1199, -984, -549, -700, +25, -836, -1353, +35, -751, }, 29.443 + { +27148, +10286, -13645, +5373, +5534, -6103, -3440, +14036, -378, -11705, -177, +2878, -226, -1089, -1747, -3125, +1710, +1453, +80, -816, -863, -89, -2314, -1012, -907, -744, -724, -326, -1037, -1054, -249, -864, }, 29.444 + { +26584, +11121, -12486, +5232, +5105, -6806, -4740, +13839, +1078, -11022, -1066, +2034, +722, -813, -2405, -2897, +1499, +637, +937, -473, -1208, +661, -2238, -1145, -718, -867, -1215, -685, -932, -951, -292, -941, }, 29.445 + { +25805, +11950, -11123, +5119, +4637, -7115, -6017, +12797, +2771, -10082, -1948, +1322, +1341, -452, -2821, -2640, +1355, -222, +1382, +402, -1584, +1029, -1649, -1467, -434, -1354, -1712, -685, -1153, -608, -115, -1081, }, 29.446 + { +24754, +12672, -9499, +5075, +3967, -6831, -7500, +11069, +4769, -9261, -2671, +911, +1238, +136, -2811, -2628, +1336, -1074, +1459, +1369, -1523, +816, -817, -1570, -995, -1254, -2045, -954, -1214, -280, +201, -1144, }, 29.447 + { +23625, +13743, -8416, +5130, +3177, -5952, -8511, +8195, +6835, -8201, -3226, +701, +799, +463, -2132, -2701, +1161, -1431, +1042, +2182, -1162, +681, -474, -1699, -1321, -1011, -2142, -1212, -1223, -47, +480, -1192, }, 29.448 + { +22165, +15115, -7785, +5546, +2568, -5733, -8429, +4589, +8489, -6649, -4078, +663, +623, +133, -953, -2723, +670, -1020, -128, +2751, -525, +300, -532, -1412, -1518, -711, -1869, -1605, -920, -465, +529, -917, }, 29.449 + { +22262, +14424, -6906, +6480, +1678, -6039, -7848, +2265, +8205, -4418, -5059, +773, +1015, -648, +127, -2327, +238, -660, -1047, +2455, +302, -278, -464, -941, -1372, -464, -1422, -1493, -1408, -881, +595, -495, }, 29.450 + { +21426, +14579, -5798, +6478, +1251, -5676, -7497, -360, +8046, -2301, -6017, +896, +1618, -1474, +1197, -1714, -587, -84, -1747, +1143, +1103, -253, -569, -193, -1153, -2, -1077, -1593, -1678, -1403, +210, -122, }, 29.451 + { +19944, +15360, -4754, +5956, +1176, -5025, -7238, -2954, +7860, -653, -6260, +621, +2153, -1709, +1912, -1547, -1249, +742, -2688, +57, +1079, +401, -432, +447, -710, -64, -484, -1682, -1600, -2206, -540, +94, }, 29.452 + { +20147, +14018, -3775, +6372, +90, -4104, -7066, -4495, +7159, +825, -6523, +620, +3112, -2199, +2066, -1581, -1430, +939, -2947, -332, +348, +613, +1047, +312, -702, +618, -378, -1616, -1651, -2440, -1434, -218, }, 29.453 + { +19984, +13391, -3853, +7072, -294, -4065, -6337, -5631, +5959, +2227, -6012, -65, +4276, -2601, +1149, -793, -2128, +1041, -2372, -946, +540, +152, +1289, +1452, -1002, +964, +82, -1959, -1450, -2309, -2165, -747, }, 29.454 + { +20430, +12454, -5495, +8998, +65, -5776, -5336, -5251, +4459, +2909, -5003, -707, +4833, -2860, -19, +113, -2229, +469, -1412, -634, +320, -217, +361, +2809, -484, +184, +1137, -2340, -1770, -1410, -2528, -1555, }, 29.455 + { +21692, +10456, -7798, +12335, +68, -8763, -3715, -3473, +2378, +2906, -3129, -2190, +5102, -2356, -1660, +915, -1539, -297, -715, +276, -315, -459, +27, +2282, +814, +228, +658, -1653, -2043, -1236, -2088, -2094, }, 29.456 + { +22414, +8463, -8975, +14734, -856, -9903, -2019, -2434, +827, +2536, -1717, -3048, +4909, -1972, -2551, +1285, -549, -637, -715, +674, -143, -626, -627, +1991, +1177, +722, +464, -1119, -1865, -1815, -1391, -1829, }, 29.457 + { +22530, +6646, -9511, +16483, -1322, -11024, -644, -496, -1479, +1598, +531, -3996, +3822, -711, -2705, +845, +188, -390, -681, +346, -68, -65, -1383, +1684, +1452, +284, +1178, -797, -2128, -1411, -1375, -1644, }, 29.458 + { +21322, +5400, -8796, +17260, -1500, -11305, +474, +113, -2907, +1438, +1455, -4669, +3322, +481, -2925, +742, +471, -590, -202, +63, -265, +281, -1317, +1179, +1229, +431, +1123, -441, -2004, -992, -1149, -2020, }, 29.459 + { +19175, +5030, -7462, +16622, -929, -10530, +416, +343, -3120, +766, +1767, -4343, +2822, +1079, -2638, +519, +570, -563, -289, +165, -315, +82, -803, +997, +763, +599, +901, -468, -1286, -794, -1066, -1838, }, 29.460 + { +16819, +5384, -6370, +14965, +290, -9700, +208, +612, -3392, +183, +2183, -3797, +2080, +1803, -2493, -16, +1023, -550, -707, +329, -153, -121, -550, +1037, +727, +224, +746, -397, -1126, -361, -1019, -1629, }, 29.461 + { +14912, +6709, -4328, +10591, -498, -7109, +111, -741, -770, +328, -733, -960, +2191, +30, -1474, -311, +350, -380, -1280, +108, +235, +180, +74, +223, +54, +624, +423, -99, +35, -79, -285, -105, }, 29.462 + { +12603, +6186, -2629, +9885, -405, -6060, +108, -976, -537, +418, -737, -896, +2184, +171, -1454, -339, +212, -324, -1080, +111, +88, +93, +170, +250, +211, +621, +320, -131, +116, -1, -403, -106, }, 29.463 + { +10408, +5748, -848, +8724, -167, -4613, -400, -1217, -70, +524, -929, -678, +2111, +202, -1239, -402, +223, -337, -970, +153, +57, +16, +164, +314, +375, +524, +121, +6, +131, -34, -146, -32, }, 29.464 + { +8810, +5752, -110, +7195, +525, -3549, -713, -1201, +150, +589, -802, -524, +1697, +366, -971, -531, +153, -232, -820, +124, +74, +31, +92, +425, +518, +160, +114, +336, +59, -121, +192, +176, }, 29.465 + { +7707, +5602, +35, +6275, +1122, -3180, -685, -740, +80, +415, -374, -403, +1135, +566, -689, -718, +117, -57, -675, +45, +161, +35, +47, +597, +362, +73, +358, +355, +34, +128, +414, +95, }, 29.466 + { +7097, +5535, -192, +5388, +1340, -2724, -316, -506, -92, +415, +68, -445, +787, +694, -670, -663, +194, +20, -606, +105, +221, -83, +318, +654, +165, +211, +501, +464, +163, +305, +282, -143, }, 29.467 + { +6452, +5181, -188, +4851, +1397, -2250, -47, -387, -147, +524, +273, -528, +602, +655, -502, -522, +157, +53, -489, +203, +143, +158, +611, +321, +242, +571, +633, +422, +125, +234, -5, -218, }, 29.468 + { +5779, +4631, +28, +4565, +1363, -1816, +67, -196, +8, +488, +200, -488, +649, +572, -444, -381, +184, +6, -287, +343, +218, +465, +530, +350, +563, +605, +532, +190, +1, +83, -90, -218, }, 29.469 + { +5208, +4384, +145, +3924, +1403, -1285, +290, -147, -75, +540, +306, -396, +492, +507, -283, -289, +166, +176, +48, +344, +475, +764, +468, +481, +475, +299, +347, +79, -73, +8, -92, -335, }, 29.470 + { +4512, +3969, +359, +3651, +1556, -960, +277, -42, +99, +522, +205, -303, +469, +444, -138, -122, +272, +416, +283, +588, +781, +710, +302, +187, +175, +216, +260, +77, -143, -145, -168, -400, }, 29.471 + { +3801, +3629, +701, +3369, +1505, -562, +487, -64, +147, +580, +155, -276, +520, +581, +54, +7, +535, +858, +532, +711, +669, +180, +6, +159, +92, +196, +192, -93, -202, -135, -272, -498, }, 29.472 + { +3442, +3530, +703, +2812, +1660, -44, +424, -101, +187, +562, +336, -54, +523, +647, +416, +546, +884, +888, +356, +303, +242, +72, +10, +71, +14, +72, +66, -163, -241, -221, -397, -501, }, 29.473 + { +2690, +3000, +1279, +2876, +1515, +205, +493, -52, +442, +658, +264, +192, +1000, +1052, +635, +643, +744, +413, +42, +208, +138, +112, -80, -143, -63, -30, +7, -171, -300, -327, -429, -392, }, 29.474 + { +2478, +3269, +1270, +2133, +1692, +521, +531, +45, +514, +1060, +829, +686, +1118, +1030, +491, +45, +183, +420, +250, +132, -125, -159, -155, -121, -114, -108, -174, -265, -205, -328, -363, -352, }, 29.475 + { +1870, +2687, +1568, +2459, +1988, +651, +612, +481, +1093, +1477, +1114, +836, +591, +278, +48, +164, +470, +379, -76, -182, +38, -195, -357, -228, -185, -143, -188, -137, -211, -282, -321, -361, }, 29.476 + { +2002, +3298, +2072, +1782, +1264, +1387, +2004, +1233, +1029, +1042, +338, -15, +176, +284, +423, +207, -57, +116, -13, -210, -269, -453, -350, -132, -143, -177, -143, -97, -213, -359, -341, -306, }, 29.477 + { +2146, +3307, +2355, +2752, +2119, +1859, +2021, +710, +97, +234, +110, +124, +235, +191, +340, -11, -121, +97, -245, -337, -346, -487, -277, -43, -78, -145, -151, -149, -204, -284, -366, -347, }, 29.478 + { +2369, +3977, +3947, +3602, +1697, +1277, +778, -51, +139, +274, +157, +44, -14, +65, +388, -56, -226, -108, -386, -368, -349, -275, -166, -135, -161, -68, -48, -184, -269, -324, -303, -300, }, 29.479 + { +2991, +5611, +4893, +2413, +32, +530, +1206, +716, -81, -249, -72, +167, +231, -189, +96, +62, -289, -321, -341, -226, -287, -249, -289, -147, -48, -120, -84, -169, -256, -385, -287, -211, }, 29.480 + { +3480, +5919, +3215, +1230, +711, +1536, +1856, +445, -348, +146, +147, -235, +202, -60, -65, -10, -330, -145, -168, -321, -230, -233, -366, -152, -34, -139, -131, -161, -196, -267, -285, -233, }, 29.481 + { +2004, +3234, +1971, +1898, +2099, +2208, +2155, +993, +558, +802, +440, -18, -153, -3, +129, -234, -279, -55, -99, -109, -245, -275, -242, -234, -224, -178, -205, -148, -89, -176, -206, -280, }, 29.482 + { +1279, +2318, +1457, +1126, +1665, +2069, +1778, +1033, +1441, +1718, +1054, +741, +475, +244, +79, -171, -166, -218, -231, -69, -145, -125, -126, -248, -153, -180, -287, -235, -255, -196, -120, -109, }, 29.483 + { +1453, +2492, +1452, +1154, +1435, +1406, +842, +362, +1287, +1720, +1252, +1179, +1008, +731, +566, +64, -227, -101, -154, -275, -230, -121, -97, -71, -157, -175, -212, -268, -250, -286, -220, -166, }, 29.484 + { +1879, +2842, +1125, +1084, +1653, +1253, +390, -18, +973, +1151, +667, +1023, +1287, +1158, +966, +422, +174, +136, -200, -125, -209, -336, -116, -116, -96, -37, -181, -264, -245, -282, -257, -233, }, 29.485 + { +2149, +3242, +1318, +1052, +1535, +1017, +118, +168, +1096, +645, +127, +653, +733, +907, +1209, +756, +503, +444, +179, +76, -160, -223, -173, -251, -109, -40, -121, -158, -228, -282, -247, -243, }, 29.486 + { +2317, +3435, +1467, +1216, +1790, +944, -476, +147, +1327, +465, +25, +491, +329, +437, +651, +458, +687, +794, +439, +296, +209, +11, -156, -194, -142, -157, -160, -145, -173, -218, -241, -271, }, 29.487 + { +2632, +3865, +1576, +1194, +1850, +818, -747, +351, +1336, +91, -24, +570, +326, +220, +377, +87, +100, +501, +607, +596, +401, +255, +179, -41, -117, -38, -173, -278, -200, -177, -186, -241, }, 29.488 + { +2913, +4307, +1690, +1174, +1997, +721, -1042, +507, +1361, -158, -88, +596, +317, +156, +293, -13, -74, +80, +115, +344, +456, +579, +399, +152, +182, +78, -95, -162, -227, -292, -160, -212, }, 29.489 + { +3419, +4851, +1663, +1035, +2035, +628, -1177, +737, +1236, -536, -64, +690, +334, +51, +172, -13, -135, -42, -10, -2, -68, +347, +513, +426, +347, +211, +168, -24, -193, -236, -186, -272, }, 29.490 + { +3767, +5304, +1782, +1016, +2102, +463, -1378, +1048, +1239, -936, -179, +746, +362, +62, +89, -105, -187, -70, -33, -113, -245, -31, +98, +248, +442, +396, +305, +172, +12, -165, -166, -183, }, 29.491 + { +4285, +5774, +1650, +1174, +2192, +50, -1405, +1467, +1118, -1334, -217, +829, +333, +12, +50, -124, -225, -140, -22, -146, -307, -135, -82, -31, +86, +236, +387, +312, +118, +25, +51, -123, }, 29.492 + { +4848, +6188, +1491, +1445, +2261, -490, -1401, +1942, +965, -1671, -300, +836, +385, -47, +8, -178, -306, -200, +51, -186, -351, -153, -292, -30, +25, -103, +13, +150, +219, +188, +112, +17, }, 29.493 + { +5454, +6649, +1314, +1669, +2321, -943, -1366, +2334, +803, -1890, -325, +781, +385, -83, +115, -228, -488, -225, +76, -126, -377, -187, -365, -53, +30, -174, -150, -173, -42, +89, +185, +106, }, 29.494 + { +5926, +7107, +1339, +1747, +2383, -1252, -1530, +2755, +780, -2246, -303, +735, +323, -85, +73, -145, -589, -384, +135, -187, -469, -43, -386, -191, +46, -215, -180, -236, -326, -211, +7, +83, }, 29.495 + { +6333, +7526, +1384, +2014, +2467, -1782, -1590, +3195, +714, -2494, -349, +719, +280, -145, +55, -69, -636, -504, +150, -221, -574, -43, -314, -228, -37, -138, -204, -369, -416, -299, -97, -205, }, 29.496 + { +6696, +8017, +1498, +2006, +2624, -2005, -1798, +3417, +748, -2614, -432, +706, +173, -173, +53, -56, -573, -718, +132, -67, -717, -164, -301, -196, -38, -159, -197, -465, -469, -327, -185, -358, }, 29.497 + { +6930, +8687, +1750, +1599, +2863, -1765, -2210, +3311, +900, -2491, -605, +596, +191, -265, +91, -35, -551, -808, +27, +34, -661, -338, -391, -71, -59, -282, -167, -426, -499, -386, -346, -349, }, 29.498 + { +7032, +9112, +2294, +1319, +2928, -1295, -2725, +3058, +1141, -2349, -736, +409, +218, -319, +37, -5, -474, -896, -105, +108, -719, -327, -414, -210, -8, -342, -280, -290, -610, -529, -264, -398, }, 29.499 + { +7290, +9148, +2788, +1517, +2890, -1004, -3145, +2936, +1182, -2207, -713, +170, +226, -310, -137, +66, -236, -1052, -288, +218, -703, -396, -407, -298, -61, -288, -332, -407, -637, -624, -99, -427, }, 29.500 + { +8295, +8777, +2246, +2812, +2858, -1707, -2793, +3041, +460, -1834, -416, -196, +229, -361, -255, +143, -68, -1152, -427, +236, -539, -557, -489, -199, -168, -280, -301, -623, -729, -417, -190, -475, }, 29.501 + { +8813, +8385, +2070, +3791, +3408, -2249, -3089, +3581, -338, -1829, +311, -486, -198, -209, -270, -126, +417, -1313, -692, +394, -483, -630, -627, -124, -246, -308, -391, -642, -737, -489, -253, -480, }, 29.502 + { +9480, +7764, +1344, +5665, +3938, -3530, -2582, +4359, -1779, -1905, +1349, -610, -594, -360, -91, -401, +691, -1075, -1088, +435, -349, -619, -660, -124, -373, -324, -465, -444, -823, -782, -95, -634, }, 29.503 + { +10219, +7759, +108, +6635, +4903, -4328, -2227, +5026, -3212, -2275, +2513, -596, -1046, -594, +196, -690, +587, -537, -1473, +302, -113, -638, -684, -100, -439, -459, -480, -472, -766, -889, -314, -724, }, 29.504 + { +11359, +8080, -1537, +6725, +6202, -4589, -2055, +5443, -4331, -2746, +3483, -358, -1535, -803, +500, -787, +107, +0, -1473, -127, +202, -644, -687, +80, -605, -513, -488, -741, -549, -859, -768, -615, }, 29.505 + { +12561, +8515, -3181, +6443, +7273, -4422, -1771, +5642, -5238, -3343, +4113, +235, -1988, -1143, +783, -757, -401, +173, -1070, -614, +288, -431, -703, +306, -751, -608, -594, -870, -585, -862, -824, -695, }, 29.506 + { +13637, +9078, -4327, +5307, +8230, -3683, -1700, +6016, -6052, -3983, +4365, +989, -2192, -1647, +1018, -629, -785, -62, -507, -850, +26, -33, -720, +529, -810, -802, -657, -1006, -784, -809, -610, -865, }, 29.507 + { +14620, +9720, -5196, +3985, +8621, -2703, -1406, +6384, -6867, -4537, +4323, +1689, -2163, -2167, +1076, -438, -1009, -536, -136, -784, -345, +300, -530, +532, -827, -847, -766, -1246, -914, -773, -428, -804, }, 29.508 + { +16072, +9930, -6183, +3360, +8255, -2295, -119, +6470, -7878, -4616, +4153, +2063, -2029, -2471, +1020, -386, -950, -1040, -67, -497, -520, +425, -98, +296, -886, -669, -1038, -1392, -1030, -835, -225, -497, }, 29.509 + { +17538, +10139, -7275, +3167, +7496, -2312, +1507, +6655, -8887, -4746, +4122, +2161, -1895, -2506, +749, -326, -908, -1248, -345, -284, -377, +510, +186, +31, -841, -583, -1261, -1430, -1259, -849, -50, -134, }, 29.510 + { +18795, +10599, -8283, +2946, +6835, -2703, +2875, +7278, -9742, -5079, +4325, +2043, -1829, -2306, +376, -514, -590, -1442, -695, -362, +63, +785, +55, -22, -629, -692, -1264, -1504, -1464, -809, +17, +195, }, 29.511 + { +19828, +11378, -9267, +2629, +6374, -3347, +3612, +8402, -10339, -5537, +4515, +1859, -1884, -1929, -100, -800, -262, -1561, -976, -577, +410, +1421, -419, +34, -250, -981, -1080, -1605, -1632, -802, +11, +380, }, 29.512 + { +21206, +11505, -9851, +2389, +6035, -4347, +4232, +9433, -10759, -5759, +4577, +1581, -1877, -1583, -452, -1192, +46, -1648, -1025, -873, +537, +2263, -927, +52, +224, -1290, -882, -1564, -1935, -752, -159, +454, }, 29.513 + { +21951, +12180, -10180, +1892, +5955, -5226, +3946, +10828, -10791, -5984, +4342, +1308, -1588, -1445, -711, -1558, +306, -1741, -844, -1199, +362, +3030, -1015, -204, +814, -1397, -873, -1354, -2329, -849, -416, +417, }, 29.514 + { +22506, +12779, -10294, +1612, +5688, -5970, +3299, +11834, -10475, -5915, +3858, +872, -1070, -1438, -1116, -1691, +435, -1836, -594, -1442, -11, +3401, -605, -538, +1220, -1085, -1193, -1113, -2738, -1072, -644, +153, }, 29.515 + { +23186, +13097, -10391, +2031, +4838, -6522, +2825, +12019, -9671, -5661, +3239, +340, -378, -1439, -1649, -1540, +599, -1995, -278, -1529, -462, +3340, +152, -492, +1137, -401, -1605, -1222, -2820, -1325, -987, -68, }, 29.516 + { +22882, +14119, -9689, +1389, +4734, -6999, +1524, +12257, -8386, -5521, +2330, +28, +188, -1505, -1990, -1510, +944, -2230, -172, -1187, -1194, +2809, +1343, -197, +605, +402, -2099, -1365, -2620, -1824, -1038, -503, }, 29.517 + { +21870, +15422, -8022, +32, +4928, -6961, -638, +12423, -6481, -5741, +1679, -358, +537, -1263, -2316, -1338, +1170, -2350, -127, -788, -1648, +1934, +2335, +603, -234, +775, -1895, -1692, -2402, -2007, -1134, -816, }, 29.518 + { +21377, +15848, -6611, -135, +4095, -6589, -2340, +11613, -4347, -6089, +1401, -892, +589, -722, -2599, -1204, +1299, -2460, -64, -474, -1793, +1309, +2278, +1468, -710, +729, -1381, -1948, -2200, -1989, -1059, -1104, }, 29.519 + { +21825, +15338, -6288, +1723, +2245, -6807, -2394, +9743, -2760, -5631, +785, -1266, +822, -455, -2395, -1291, +1244, -2162, -287, +63, -1716, +759, +1340, +2033, -170, +136, -645, -1936, -2205, -1413, -1181, -1687, }, 29.520 + { +22088, +14986, -6294, +3940, +475, -7388, -1931, +7563, -1485, -4751, -302, -1228, +1282, -606, -1733, -1685, +1011, -1322, -834, +679, -1560, -371, +652, +2168, +634, +122, -548, -1338, -1967, -1463, -1230, -1785, }, 29.521 + { +21218, +15763, -6154, +5244, -207, -8203, -1741, +5343, +1, -4070, -1324, -1042, +1940, -1042, -1041, -1719, +173, +234, -1546, +421, -980, -1263, -189, +2163, +1362, +537, -295, -894, -1836, -1649, -862, -1860, }, 29.522 + { +20943, +15351, -5193, +5824, -681, -8421, -2182, +3733, +912, -3280, -2125, -629, +2393, -1338, -793, -1272, -318, +619, -1449, -542, -613, -929, -1049, +1622, +1869, +1834, -606, -1014, -899, -1858, -1052, -1583, }, 29.523 + { +20467, +15036, -4299, +6074, -972, -8163, -2993, +2103, +1953, -2525, -2906, +84, +2478, -1496, -381, -1209, -661, +522, -1431, -1137, -494, -29, -1724, +1410, +1857, +2078, +198, -1222, -492, -1845, -1016, -1459, }, 29.524 + { +19997, +14492, -3439, +6231, -1292, -7499, -3870, +428, +3016, -1672, -3589, +505, +3009, -1682, -424, -1271, -888, +168, -1633, -640, -998, +512, -655, +572, +1038, +2022, +1564, -1436, -837, -970, -1064, -1590, }, 29.525 + { +19121, +13891, -1956, +5864, -1769, -5712, -5524, -1209, +4728, -1224, -4384, +1529, +2886, -1835, -216, -2037, -717, +368, -2459, +62, -470, -20, +501, +397, +27, +1794, +1472, -406, -774, -1035, -530, -1651, }, 29.526 + { +18795, +12787, -866, +5679, -2785, -3778, -6009, -3416, +6104, -148, -5120, +1968, +2942, -2232, -361, -2334, -318, +255, -2810, +772, +147, -722, +931, +1048, -622, +926, +926, +464, +8, -1388, -195, -1234, }, 29.527 + { +19769, +11583, -2448, +6778, -3321, -3974, -5178, -3690, +5661, +410, -4626, +1587, +2861, -2687, -704, -1965, -264, +354, -2735, +728, +431, -372, +846, +890, -556, +313, +642, +248, +534, -654, -743, -572, }, 29.528 + { +20742, +9918, -4333, +9177, -3673, -5562, -3412, -3017, +4558, +903, -4422, +932, +3308, -2821, -1440, -1193, +107, +341, -2476, +352, +665, +234, +482, +681, -223, -107, +450, +161, +378, +311, -786, -592, }, 29.529 + { +20393, +8513, -5551, +11591, -3341, -7618, -1960, -1344, +2974, +225, -3410, +284, +3332, -2616, -1768, -458, +23, +66, -1947, +502, +187, +334, +642, +553, -324, +98, +28, -212, +831, +137, -320, -307, }, 29.530 + { +19863, +7195, -5891, +13080, -3237, -8975, -179, -735, +1159, +597, -2780, -566, +3377, -1932, -1835, -26, +57, -431, -1301, +563, -286, +265, +803, +515, -423, +180, +122, -246, +644, +165, -191, +77, }, 29.531 + { +18658, +6850, -5751, +12388, -2703, -7823, +255, -1504, +610, +770, -2248, -983, +3161, -1268, -1738, +128, -21, -478, -1161, +338, -70, +251, +391, +591, -323, +20, +528, -36, +54, +115, -36, +34, }, 29.532 + { +17076, +6736, -5238, +11355, -1525, -7217, -40, -1078, -147, +458, -1371, -990, +2637, -628, -1439, -189, +204, -339, -1390, +203, +285, +214, +63, +453, -132, +311, +558, +23, -66, -152, +62, -43, }, 29.533 + { +13623, +7663, -736, +5443, -2593, -2244, -1530, -1649, +1729, -32, -2266, +999, +1978, -1230, -677, -1107, +219, -259, -1521, +393, -253, -340, +340, +425, +603, +1120, -212, -683, -191, -585, -148, +387, }, 29.534 + { +11820, +7583, -426, +4965, -1356, -2529, -1167, -1245, +983, +124, -1778, +794, +1769, -842, -700, -980, +259, -378, -1380, +412, -355, -376, +513, +422, +537, +830, -258, -264, -158, -658, +7, +383, }, 29.535 + { +10321, +7312, -105, +4864, -813, -2658, -650, -1140, +594, +154, -1345, +747, +1470, -560, -589, -773, +109, -428, -1061, +264, -409, -228, +464, +450, +557, +455, -229, +107, -87, -614, +63, +459, }, 29.536 + { +8832, +6788, +754, +4529, -737, -2058, -537, -1141, +593, +102, -1073, +689, +1331, -427, -481, -535, -57, -390, -871, +136, -280, -172, +355, +496, +482, +211, +7, +299, +18, -389, +32, +568, }, 29.537 + { +7264, +6341, +1804, +3830, -547, -1150, -702, -1198, +746, +193, -1033, +629, +1243, -340, -243, -463, -211, -272, -673, +38, -232, -89, +255, +491, +349, +237, +305, +440, +181, -306, +96, +481, }, 29.538 + { +5764, +5793, +2760, +3310, -250, -431, -863, -1206, +942, +277, -1025, +490, +1124, +11, -135, -654, -133, +3, -652, -89, -115, -120, +324, +473, +214, +489, +656, +578, +94, -300, +162, +271, }, 29.539 + { +4877, +5432, +2934, +2887, +9, -98, -665, -1051, +773, +328, -754, +397, +892, +204, -54, -717, +22, +137, -707, -136, -8, -16, +384, +457, +358, +804, +826, +406, -152, -241, +83, +160, }, 29.540 + { +4273, +4974, +2996, +2688, +19, +236, -317, -1082, +645, +529, -499, +171, +725, +487, -28, -702, +171, +109, -663, +33, +8, +168, +685, +509, +520, +907, +639, +123, -222, -249, +142, +242, }, 29.541 + { +3881, +4471, +2801, +2721, +214, +232, -276, -784, +726, +443, -495, +187, +790, +514, -89, -624, +292, +140, -590, +200, +269, +545, +770, +316, +532, +788, +265, -82, -82, -100, +41, +29, }, 29.542 + { +3766, +4300, +2408, +2391, +333, +347, -106, -602, +651, +407, -345, +364, +720, +250, +52, -284, +220, +186, -143, +547, +529, +560, +390, +206, +482, +471, +188, -7, -119, -170, +39, -9, }, 29.543 + { +3436, +3912, +2322, +2385, +450, +371, -77, -417, +729, +455, -307, +332, +707, +317, +188, -91, +487, +565, +170, +463, +431, +296, +60, +230, +424, +421, +106, -107, -113, -167, +28, -121, }, 29.544 + { +3183, +3685, +2212, +2271, +537, +324, +19, -108, +778, +330, -270, +582, +667, +327, +729, +405, +569, +537, +26, +242, +252, -24, +148, +398, +218, +251, +64, -101, -137, -167, -61, -180, }, 29.545 + { +2975, +3602, +2238, +1946, +368, +615, +350, -208, +659, +572, -66, +604, +1024, +904, +959, +291, +202, +264, -144, +133, +221, +2, +109, +243, +252, +133, -64, -129, -180, -137, -144, -273, }, 29.546 + { +2802, +3321, +2156, +2179, +535, +317, +283, +375, +791, +445, +493, +1260, +1224, +697, +585, -84, -52, +130, -53, +215, +5, -34, +157, +233, +121, -41, -96, -197, -124, -177, -272, -304, }, 29.547 + { +2567, +3351, +2539, +1843, +97, +744, +689, +452, +1235, +1224, +767, +951, +804, +213, +156, -203, +95, +139, -182, +93, +76, +25, +66, +145, -99, -130, -124, -168, -143, -326, -266, -289, }, 29.548 + { +2718, +3449, +2308, +1797, +208, +761, +1522, +1644, +1223, +789, +460, +314, +454, -11, +113, +21, -170, +13, +13, +85, +59, -34, -70, +29, -183, -196, -119, -202, -174, -262, -320, -243, }, 29.549 + { +2540, +3343, +2399, +2066, +1062, +1501, +1604, +1736, +1082, -140, -197, +490, +498, -164, -13, -43, -88, +38, +21, +50, -52, -74, -79, -137, -262, -173, -156, -121, -156, -298, -206, -189, }, 29.550 + { +2234, +3727, +3392, +2599, +1296, +1388, +1575, +990, +120, +142, -3, +141, +343, -173, +83, -53, -176, +87, -65, -57, -14, -108, -214, -261, -285, -100, -90, -157, -152, -234, -209, -204, }, 29.551 + { +2985, +5564, +3761, +1458, +757, +1364, +784, +451, +634, -7, -242, +3, +522, +51, -283, +33, -103, -187, +6, +14, -99, -195, -315, -245, -150, -121, -75, -132, -198, -215, -225, -243, }, 29.552 + { +3536, +5654, +3321, +1733, +414, +394, +1272, +1090, -2, -98, +317, +30, +224, +141, -65, -151, -228, -176, -28, +9, -112, -143, -326, -205, -121, -146, -154, -155, -169, -220, -257, -233, }, 29.553 + { +2423, +4490, +3856, +2307, +306, +542, +1485, +1042, +272, +121, +367, +345, +305, +76, +54, -98, -197, -211, -235, -76, +30, -102, -249, -110, -163, -144, -218, -256, -176, -211, -237, -223, }, 29.554 + { +2207, +4508, +3055, +1310, +930, +958, +1117, +900, +798, +352, +193, +679, +614, +197, +54, +57, -131, -330, -215, -106, -182, -79, -43, -101, -76, -110, -233, -306, -312, -262, -203, -241, }, 29.555 + { +2155, +4216, +2568, +1005, +1213, +966, +459, +898, +1067, +401, +559, +752, +475, +636, +473, -23, -19, +1, -327, -285, -98, -96, -180, -15, +129, -115, -171, -209, -363, -372, -286, -209, }, 29.556 + { +2070, +3883, +2353, +1160, +1380, +728, +99, +912, +928, +215, +528, +873, +808, +593, +419, +448, +247, -17, -66, -137, -244, -204, -83, -38, -42, +64, -18, -242, -235, -315, -412, -310, }, 29.557 + { +2125, +3872, +2333, +1117, +1382, +652, -82, +932, +929, -32, +165, +810, +760, +591, +704, +380, +171, +402, +223, -173, -55, +18, -230, -138, +84, +9, -127, -88, -152, -290, -286, -341, }, 29.558 + { +2204, +3829, +2303, +1430, +1528, +266, -259, +1194, +944, -279, +37, +705, +496, +385, +633, +421, +252, +297, +317, +192, +43, +66, +57, +9, -58, -33, -24, -181, -247, -150, -214, -284, }, 29.559 + { +2377, +4116, +2337, +1342, +1538, +248, -324, +1198, +907, -340, -9, +552, +446, +300, +373, +259, +71, +202, +429, +213, +40, +308, +228, +122, +212, +69, -122, -224, -230, -240, -255, -174, }, 29.560 + { +2547, +4334, +2430, +1433, +1566, +87, -418, +1351, +878, -486, -33, +547, +363, +146, +403, +264, -240, -131, +304, +205, +66, +265, +312, +373, +311, +248, +138, -166, -373, -314, -205, -258, }, 29.561 + { +2830, +4723, +2442, +1353, +1596, +57, -445, +1370, +794, -551, +26, +483, +302, +84, +326, +353, -232, -336, -50, +55, -20, +99, +386, +443, +376, +430, +300, -2, -200, -321, -318, -255, }, 29.562 + { +3101, +5094, +2484, +1317, +1620, -48, -486, +1479, +713, -731, +26, +531, +246, -26, +207, +395, -120, -435, -199, -118, -261, -82, +201, +404, +445, +420, +397, +148, -80, -175, -230, -288, }, 29.563 + { +3513, +5583, +2388, +1169, +1692, -102, -510, +1532, +632, -825, +39, +484, +162, -19, +107, +357, -62, -406, -271, -220, -305, -288, -44, +301, +381, +318, +417, +216, -33, -33, -125, -197, }, 29.564 + { +3971, +6063, +2297, +1049, +1754, -235, -496, +1678, +453, -941, +114, +521, +25, -141, +100, +323, -30, -393, -314, -245, -341, -357, -157, +129, +280, +188, +259, +194, -7, -19, -69, -59, }, 29.565 + { +4462, +6601, +2162, +929, +1825, -406, -449, +1847, +245, -1033, +198, +531, -55, -243, +34, +274, -46, -317, -280, -344, -378, -331, -147, -22, +200, +127, +86, +97, -172, -74, +29, -12, }, 29.566 + { +4929, +7134, +2067, +832, +1905, -671, -420, +2107, +13, -1176, +285, +566, -115, -373, -56, +231, -88, -317, -242, -369, -432, -373, -60, -90, +32, +212, -22, -102, -274, -226, -80, -18, }, 29.567 + { +5380, +7722, +2007, +689, +2018, -933, -447, +2383, -171, -1301, +369, +562, -128, -427, -220, +187, -78, -332, -233, -409, -419, -408, -34, +5, -132, +185, +51, -252, -327, -342, -282, -98, }, 29.568 + { +5728, +8332, +2054, +461, +2152, -1109, -551, +2612, -297, -1395, +446, +591, -229, -430, -303, +22, -78, -336, -214, -416, -470, -471, -25, +180, -147, -54, +113, -193, -423, -380, -487, -230, }, 29.569 + { +6113, +8894, +2133, +278, +2235, -1274, -667, +2769, -471, -1368, +504, +562, -301, -464, -281, -179, -193, -277, -163, -442, -520, -538, -26, +230, -9, -150, -82, -60, -486, -442, -508, -419, }, 29.570 + { +6822, +9262, +1874, +539, +2127, -1579, -524, +2787, -765, -1217, +595, +512, -360, -580, -126, -403, -358, -224, -134, -389, -601, -579, +2, +211, +8, +23, -240, -219, -412, -487, -530, -498, }, 29.571 + { +7515, +9472, +1708, +950, +1940, -1744, -475, +2685, -890, -1100, +601, +523, -322, -777, -22, -467, -558, -250, -104, -316, -558, -673, -18, +285, -56, +161, -229, -389, -420, -494, -565, -489, }, 29.572 + { +7940, +9637, +1858, +1251, +1898, -1722, -763, +2646, -912, -1044, +619, +459, -176, -902, -97, -399, -684, -474, -18, -221, -503, -687, -201, +491, -97, +79, -100, -413, -500, -584, -564, -465, }, 29.573 + { +8437, +9625, +1884, +1715, +2059, -1879, -1105, +2725, -1064, -1040, +741, +338, -154, -826, -248, -438, -648, -774, -57, -33, -524, -628, -313, +497, +49, -120, -60, -285, -620, -701, -513, -517, }, 29.574 + { +9220, +9383, +1442, +2663, +2411, -2496, -1180, +2907, -1426, -1017, +899, +285, -271, -686, -239, -660, -556, -895, -297, +126, -442, -632, -203, +342, +145, -93, -144, -242, -638, -729, -500, -582, }, 29.575 + { +9906, +8999, +886, +4046, +2822, -3537, -956, +3303, -2122, -1097, +1212, +287, -466, -677, -82, -821, -584, -919, -622, +120, -110, -798, -101, +317, +50, +139, -325, -314, -494, -726, -682, -494, }, 29.576 + { +10165, +8622, +635, +5498, +3208, -4703, -409, +3974, -3274, -1343, +1812, +349, -758, -791, +168, -846, -676, -904, -937, -105, +296, -819, -186, +443, -101, +357, -353, -431, -390, -698, -845, -370, }, 29.577 + { +10778, +9125, -461, +5499, +4480, -4885, -762, +4363, -3869, -1600, +2274, +309, -1021, -799, +442, -989, -823, -718, -1054, -519, +402, -449, -376, +548, -68, +372, -259, -484, -358, -718, -919, -405, }, 29.578 + { +11808, +9598, -1631, +4810, +5752, -4539, -1177, +4391, -4229, -1790, +2570, +358, -1408, -786, +715, -1102, -1041, -581, -992, -885, +191, -44, -368, +438, +142, +323, -208, -398, -399, -804, -937, -537, }, 29.579 + { +12864, +10102, -2814, +4041, +6509, -3716, -1366, +4112, -4371, -1965, +2757, +499, -1803, -807, +909, -1173, -1234, -559, -856, -1084, -225, +261, -140, +202, +383, +376, -191, -207, -486, -953, -891, -645, }, 29.580 + { +13770, +10842, -3762, +2948, +6944, -2626, -1423, +3706, -4498, -2054, +2738, +733, -2151, -912, +1063, -1203, -1347, -631, -679, -1132, -639, +290, +229, +18, +464, +552, -134, -53, -593, -1082, -910, -725, }, 29.581 + { +14673, +11578, -4475, +1691, +7096, -1713, -1082, +3280, -4814, -1919, +2563, +861, -2306, -1111, +1114, -1240, -1354, -818, -528, -1086, -897, +19, +528, +85, +343, +790, +8, -1, -705, -1107, -997, -856, }, 29.582 + { +15287, +12615, -5054, +450, +7031, -997, -525, +3136, -5350, -1613, +2407, +806, -2180, -1353, +994, -1181, -1315, -1000, -400, -980, -938, -358, +637, +322, +261, +1020, +234, -8, -727, -1060, -1088, -991, }, 29.583 + { +16341, +13198, -5831, -183, +6631, -925, +450, +3048, -6132, -1100, +2328, +438, -1973, -1456, +665, -1224, -1147, -1229, -302, -819, -969, -597, +502, +511, +258, +1295, +390, -116, -684, -1059, -1180, -1113, }, 29.584 + { +17889, +13289, -7003, +251, +5613, -1102, +1630, +2856, -6736, -544, +2351, -201, -1577, -1545, +280, -1291, -936, -1371, -191, -616, -996, -677, +307, +583, +290, +1693, +557, -380, -523, -1129, -1279, -1128, }, 29.585 + { +19421, +13294, -8130, +984, +4304, -1338, +2588, +2708, -7031, -194, +2313, -845, -1057, -1787, -127, -1222, -940, -1254, -198, -479, -881, -843, +201, +539, +228, +2168, +760, -747, -401, -1194, -1459, -1011, }, 29.586 + { +20606, +13470, -8907, +1610, +3084, -1671, +3262, +2674, -6933, -54, +2126, -1222, -615, -2058, -501, -1073, -920, -1108, -226, -364, -678, -985, +112, +592, +23, +2550, +1067, -1061, -439, -1160, -1596, -844, }, 29.587 + { +21678, +13397, -9105, +1972, +1964, -2147, +3689, +2647, -6634, +29, +1710, -1374, -333, -2266, -901, -865, -791, -1224, -108, -330, -517, -988, -65, +848, -297, +2505, +1436, -1115, -771, -1020, -1548, -824, }, 29.588 + { +22043, +13828, -8808, +1968, +1087, -2691, +3735, +2813, -6153, -63, +1327, -1523, -22, -2413, -1231, -625, -620, -1517, +116, -296, -490, -687, -330, +1228, -654, +1883, +1897, -817, -1166, -848, -1353, -842, }, 29.589 + { +21862, +14553, -8083, +1733, +298, -3191, +3378, +3080, -5574, -270, +1014, -1790, +389, -2456, -1466, -480, -483, -1820, +297, -178, -667, -4, -656, +1283, -726, +917, +2011, -106, -1245, -999, -903, -756, }, 29.590 + { +21352, +15281, -6885, +1395, -334, -3665, +2670, +3546, -5077, -445, +803, -2146, +977, -2334, -1692, -440, -333, -2064, +440, -23, -774, +810, -1201, +1101, -364, -194, +1769, +892, -1065, -1132, -267, -995, }, 29.591 + { +20861, +15614, -5482, +1081, -870, -4341, +1898, +3930, -4851, -435, +471, -2413, +1653, -2264, -1871, -605, -244, -2109, +276, +437, -945, +994, -1311, +557, +83, -748, +1003, +1546, -293, -1147, -222, -1064, }, 29.592 + { +20341, +15837, -4243, +1301, -1450, -5105, +1347, +3961, -4522, -413, +325, -2497, +2316, -2115, -2138, -652, -297, -1870, +211, +677, -1276, +1047, -1153, -118, +720, -740, -74, +2033, +582, -1274, -145, -714, }, 29.593 + { +19636, +16119, -3188, +1683, -1865, -5991, +823, +3722, -4115, -322, +190, -2340, +2786, -2019, -2280, -876, -206, -1208, -519, +732, -1211, +541, -669, -258, +512, +140, -566, +1174, +1263, -677, -170, -802, }, 29.594 + { +18858, +16285, -2143, +1991, -1980, -6784, +50, +3403, -3485, -245, +189, -2095, +3079, -1823, -2721, -438, -196, -1206, -875, +432, -1124, +431, -376, -252, +414, +1193, -856, -296, +1960, -172, -317, -664, }, 29.595 + { +18488, +15830, -1291, +2547, -2229, -7386, -730, +2796, -2460, -104, -268, -1138, +2825, -2015, -2015, -709, -496, -920, -1536, +112, -516, +216, -578, +707, +252, +875, +136, -1180, +1044, +302, +130, -464, }, 29.596 + { +18032, +15462, -771, +3171, -2446, -7862, -1764, +2636, -1567, +5, -496, -701, +2816, -1760, -1991, -874, -746, -1167, -1739, +343, -701, +364, +15, +532, +203, +973, +810, -1570, -221, +371, +695, -210, }, 29.597 + { +18183, +14237, -213, +3919, -3116, -7974, -2292, +2020, -153, +42, -1423, +627, +2562, -2113, -1333, -1554, -1186, -770, -1762, -91, -66, +691, -288, +385, +793, +1048, +304, -885, -866, -584, +1104, +190, }, 29.598 + { +17916, +13240, +200, +4684, -3796, -7718, -2760, +1604, +850, +225, -1927, +1081, +2619, -2191, -1377, -2216, -746, -653, -2263, +733, +68, +56, +169, +482, +600, +1299, +31, -544, -723, -1663, +902, +562, }, 29.599 + { +17044, +12267, +1399, +4803, -4676, -5966, -3841, +281, +3320, -114, -3303, +2279, +2401, -2496, -1283, -2365, -671, -464, -1900, +808, -230, -25, +729, +96, +303, +1800, +66, -835, -309, -1837, -28, +731, }, 29.600 + { +17131, +11616, +1113, +3708, -4510, -4182, -4413, -204, +4141, -354, -3431, +2353, +1909, -2319, -1067, -2887, -24, -22, -2046, +700, -301, +199, +609, -123, +449, +1846, +102, -822, -495, -1668, -259, +595, }, 29.601 + { +17804, +10827, -833, +4161, -4620, -3463, -2984, -1411, +4085, +122, -3689, +2063, +1883, -2404, -1128, -2081, +2, -158, -1877, +784, -113, -307, +389, +403, +575, +1373, +163, -658, -728, -1403, -144, +238, }, 29.602 + { +17770, +9675, -2120, +5437, -4251, -3736, -2292, -788, +3134, -434, -2948, +1807, +1772, -2590, -638, -1520, -124, -311, -1778, +1073, -328, -581, +430, +559, +654, +1248, -5, -604, -701, -1222, +85, +89, }, 29.603 + { +16983, +8744, -2777, +6694, -3792, -4443, -901, -815, +1755, -54, -2575, +1415, +1766, -2182, -536, -1198, -147, -428, -1414, +749, -461, -344, +355, +328, +855, +1312, -290, -626, -512, -1025, +51, +365, }, 29.604 + { +15530, +7980, -1979, +6512, -3528, -3269, -860, -1658, +1879, -8, -2551, +1210, +1950, -1724, -587, -1052, -96, -226, -1441, +427, -306, -235, +212, +345, +877, +1182, -243, -745, -344, -674, -107, +390, }, 29.605 + { +13644, +7839, +340, +4237, -4066, -2089, +181, -157, -98, -716, -1664, +1617, +1169, -1811, +342, -1102, -326, +22, -1305, +431, -226, -614, +436, +265, -325, +880, +370, -95, +206, -791, -194, -105, }, 29.606 + { +11477, +7542, +1372, +3307, -3045, -1070, -418, -498, +213, -531, -1761, +1305, +1366, -1451, +150, -939, -219, -56, -1110, +275, -259, -524, +318, +167, -195, +840, +316, +6, -31, -753, +66, +40, }, 29.607 + { +9185, +7569, +2375, +2356, -1914, -448, -695, -709, +367, -353, -1571, +1152, +1173, -975, +111, -735, -206, -120, -786, +213, -329, -455, +368, +102, -13, +690, +287, +199, -74, -549, +265, +253, }, 29.608 + { +7687, +7172, +2505, +2384, -1188, -623, -434, -481, +255, -398, -1198, +1009, +1022, -762, +89, -484, -279, -47, -579, +42, -268, -226, +195, +11, +172, +581, +417, +303, -47, -184, +406, +81, }, 29.609 + { +6794, +6483, +2410, +2627, -840, -796, -81, -127, -26, -355, -786, +799, +900, -672, +188, -249, -386, -6, -336, -8, -247, -119, +38, +96, +339, +606, +665, +312, -3, +47, +278, -125, }, 29.610 + { +5907, +5826, +2525, +2670, -555, -752, +41, +149, -99, -234, -613, +533, +888, -428, +180, -214, -321, +180, -187, -225, -103, +27, -39, +368, +489, +694, +754, +175, -13, +28, +125, -216, }, 29.611 + { +5068, +5227, +2668, +2678, -280, -715, +86, +472, -115, -212, -504, +385, +890, -299, +204, -116, -199, +274, -206, -202, +165, +190, +121, +464, +488, +765, +530, -95, +33, +85, +32, -285, }, 29.612 + { +4430, +4893, +2607, +2422, +45, -558, +143, +594, -112, -70, -407, +181, +893, +9, +138, -80, -17, +293, -18, +126, +441, +150, +103, +549, +369, +433, +333, -10, +90, +43, -106, -245, }, 29.613 + { +3711, +4345, +2802, +2585, +142, -598, +212, +846, -12, -130, -349, +202, +915, +136, +144, +26, +282, +585, +264, +261, +271, +98, +65, +247, +259, +366, +292, +2, +95, +26, -184, -171, }, 29.614 + { +3270, +4161, +2763, +2345, +192, -419, +378, +857, +49, -39, -256, +254, +934, +196, +366, +592, +573, +461, +232, +248, -23, -159, +76, +241, +206, +248, +207, +95, +139, -106, -191, -197, }, 29.615 + { +2943, +3918, +2802, +2227, +112, -304, +629, +924, +29, +150, -154, +182, +1323, +752, +534, +526, +437, +413, +22, -194, -72, +85, -38, +83, +224, +251, +213, +42, +65, -167, -226, -198, }, 29.616 + { +2772, +3851, +2788, +1975, +65, -69, +845, +1077, -57, +182, +530, +759, +1311, +513, +472, +465, +64, +67, -3, -148, -49, +2, -85, +278, +204, -7, +177, +109, -60, -207, -187, -266, }, 29.617 + { +2741, +3962, +2753, +1658, -41, +420, +934, +1003, +697, +759, +554, +442, +1100, +376, +43, +199, +55, +12, -47, -241, +16, +219, -40, +38, -37, +66, +191, +16, -90, -266, -234, -204, }, 29.618 + { +3100, +4428, +2177, +1205, +75, +902, +1974, +1358, +427, +424, +567, +206, +484, +165, +130, +95, -110, -9, -43, +93, +142, -69, -204, -13, -9, +23, +198, -26, -264, -205, -104, -146, }, 29.619 + { +3210, +4553, +1862, +1097, +1209, +1702, +1662, +1004, +308, +184, +225, +17, +388, +79, +50, +47, -163, +200, +252, -95, -147, -45, -164, -179, -57, +145, +35, -75, -120, -139, -145, -187, }, 29.620 + { +2744, +4295, +2964, +2006, +764, +1468, +1817, +756, +4, +41, +245, +14, +163, +49, +70, +100, +168, +231, -53, -108, -40, -137, -327, -125, -50, -25, +121, +79, -87, -207, -216, -224, }, 29.621 + { +3644, +5506, +2291, +880, +1111, +1504, +1276, +605, -113, -2, +218, +64, +212, -104, +192, +519, +136, -208, +41, +48, -219, -274, -268, -122, -133, +102, +215, +67, -186, -291, -229, -287, }, 29.622 + { +3729, +5991, +1991, +263, +1099, +1310, +1186, +802, +62, -222, +346, +155, +106, +141, +330, +491, +26, -42, +16, -23, -226, -214, -280, -265, -52, +117, +214, +32, -128, -310, -288, -270, }, 29.623 + { +2626, +5352, +3385, +581, +252, +872, +1262, +1271, +175, -237, +438, +384, +61, +61, +469, +546, +232, -19, -21, +71, -83, -296, -233, -189, -195, +42, +177, +99, -95, -207, -255, -295, }, 29.624 + { +2086, +4619, +3769, +1305, +139, +491, +966, +1193, +432, -210, +327, +607, +212, +43, +405, +422, +412, +221, +64, +98, -131, -143, -94, -220, -249, -9, +178, +14, -136, -131, -163, -256, }, 29.625 + { +2139, +4433, +3497, +1555, +347, +189, +878, +1324, +318, -496, +231, +753, +258, +26, +394, +493, +349, +186, +248, +240, -44, -89, -49, -142, -57, -56, +21, +118, -122, -273, -226, -136, }, 29.626 + { +2311, +4528, +3281, +1515, +485, +155, +824, +1324, +265, -492, +160, +527, +142, +7, +422, +391, +265, +431, +202, +86, +149, +36, +38, -14, +14, +37, +95, +88, -115, -263, -276, -244, }, 29.627 + { +2483, +4762, +3179, +1400, +563, +131, +828, +1336, +202, -523, +128, +527, +103, -226, +171, +342, +142, +412, +338, +45, +92, -94, +172, +187, +6, +205, +202, +105, -77, -196, -299, -324, }, 29.628 + { +2726, +5137, +3097, +1180, +674, +184, +755, +1346, +184, -531, +98, +477, +195, -246, -36, +193, -87, +205, +506, +62, -30, -76, +59, +215, +91, +296, +329, +186, +97, -139, -324, -248, }, 29.629 + { +3045, +5527, +3012, +1062, +756, +111, +709, +1423, +99, -641, +145, +477, +146, -204, -123, +100, -177, -119, +444, +91, -147, -88, -72, +196, +100, +177, +408, +293, +113, +30, -141, -297, }, 29.630 + { +3436, +6020, +2910, +889, +868, +57, +655, +1504, +22, -713, +161, +469, +124, -165, -125, -15, -195, -258, +287, +219, -316, -262, -35, +129, +77, +61, +409, +298, +70, +141, -16, -144, }, 29.631 + { +3894, +6586, +2783, +668, +954, -13, +635, +1573, -146, -783, +246, +445, +2, -172, -63, -91, -294, -318, +133, +279, -237, -506, -107, +75, +8, +47, +226, +248, +95, +53, -4, -57, }, 29.632 + { +4405, +7200, +2656, +443, +1039, -128, +662, +1690, -398, -841, +393, +450, -138, -226, +1, -146, -386, -359, +40, +223, -89, -563, -227, +109, -110, -3, +147, +88, +56, +29, -5, -116, }, 29.633 + { +4876, +7873, +2612, +205, +1070, -269, +712, +1849, -697, -944, +597, +475, -291, -315, +82, -190, -515, -429, -4, +168, -34, -473, -351, +121, -57, -127, +140, -117, -82, +81, -67, -139, }, 29.634 + { +5345, +8532, +2640, -20, +1042, -466, +776, +2045, -1057, -1078, +828, +511, -446, -439, +123, -190, -656, -517, -117, +119, +9, -405, -323, -39, +71, -105, -9, -130, -314, -1, -54, -197, }, 29.635 + { +5755, +9172, +2804, -162, +957, -687, +828, +2288, -1359, -1285, +1083, +619, -595, -549, +140, -166, -730, -627, -255, +75, +66, -414, -171, -94, -6, +93, -105, -228, -284, -205, -114, -134, }, 29.636 + { +6053, +9828, +3094, -338, +874, -821, +750, +2423, -1504, -1522, +1217, +797, -715, -693, +145, -172, -790, -680, -456, -66, +242, -494, -151, +117, -189, +150, +39, -395, -358, -190, -293, -70, }, 29.637 + { +6365, +10439, +3396, -513, +841, -814, +596, +2360, -1502, -1631, +1210, +940, -723, -805, +124, -197, -871, -667, -563, -359, +324, -281, -332, +308, -121, -25, +252, -378, -573, -197, -328, -115, }, 29.638 + { +6691, +10976, +3599, -570, +917, -864, +376, +2212, -1463, -1679, +1089, +1036, -703, -886, +72, -213, -1017, -664, -582, -629, +140, +41, -340, +170, +189, -205, +228, -137, -721, -390, -282, -214, }, 29.639 + { +7655, +11301, +2983, -165, +1190, -1185, +265, +2137, -1680, -1486, +973, +1045, -655, -1003, +145, -320, -1056, -774, -554, -718, -142, +148, -1, -9, +263, -7, +1, +12, -602, -637, -348, -173, }, 29.640 + { +8725, +11372, +2035, +795, +1645, -1977, +191, +2335, -2001, -1434, +933, +1003, -589, -1155, +213, -455, -1024, -893, -641, -701, -356, -16, +344, +128, +51, +231, -87, -31, -405, -710, -562, -171, }, 29.641 + { +9575, +11154, +1237, +2394, +2028, -3285, +418, +2886, -2551, -1615, +1186, +934, -650, -1197, +283, -624, -1011, -875, -759, -706, -442, -240, +477, +441, -54, +319, -30, -127, -305, -565, -677, -372, }, 29.642 + { +10190, +10640, +774, +4347, +2002, -4744, +1042, +3458, -3410, -1873, +1669, +748, -934, -1066, +314, -877, -1066, -778, -875, -839, -432, -417, +363, +615, +59, +388, -7, -218, -333, -323, -683, -569, }, 29.643 + { +11656, +10948, -887, +4545, +3052, -4722, +604, +3331, -3530, -1765, +1917, +460, -1170, -858, +331, -1145, -1038, -801, -770, -934, -391, -415, +118, +836, +219, +336, +68, -117, -415, -229, -603, -466, }, 29.644 + { +13296, +11164, -2472, +4349, +3911, -4234, +37, +3058, -3561, -1609, +2035, +238, -1451, -733, +380, -1485, -961, -904, -594, -975, -451, -230, -189, +825, +484, +313, +29, -4, -374, -223, -531, -267, }, 29.645 + { +14547, +11879, -3970, +3666, +4639, -3257, -708, +2677, -3398, -1566, +2096, +56, -1592, -844, +432, -1787, -948, -1000, -471, -858, -654, +26, -371, +599, +668, +477, -138, +127, -242, -320, -341, -194, }, 29.646 + { +16244, +12044, -5188, +3051, +4787, -2203, -1047, +2078, -3288, -1206, +1927, -153, -1529, -1122, +410, -1934, -1051, -951, -400, -689, -749, +91, -214, +211, +759, +692, -292, +255, -104, -432, -82, -239, }, 29.647 + { +17280, +12976, -6370, +2340, +4641, -1173, -1098, +1398, -2972, -1077, +1787, -398, -1249, -1610, +388, -1966, -1197, -775, -431, -518, -766, +52, -3, +3, +536, +1033, -423, +244, +74, -499, +32, -201, }, 29.648 + { +18875, +13104, -7286, +2064, +3976, -486, -755, +780, -2840, -753, +1487, -511, -1136, -1879, +201, -1926, -1197, -654, -442, -429, -635, -89, +257, -23, +237, +1321, -511, +32, +268, -506, +24, +2, }, 29.649 + { +20130, +13417, -7954, +1823, +3146, -160, -302, +339, -2656, -706, +1344, -730, -995, -2122, -28, -1814, -1115, -678, -496, -246, -631, -73, +307, +224, -38, +1338, -479, -375, +351, -455, +133, +122, }, 29.650 + { +20900, +14050, -8284, +1502, +2221, -215, +187, +146, -2582, -775, +1230, -1057, -723, -2335, -281, -1549, -1106, -814, -527, -46, -662, -26, +311, +623, -314, +1032, -275, -849, +139, -141, +262, +150, }, 29.651 + { +21506, +14520, -8163, +1322, +1076, -434, +702, +70, -2585, -746, +944, -1321, -256, -2471, -490, -1259, -1129, -1001, -507, +204, -799, +188, +407, +732, -431, +631, -175, -1085, -90, -20, +511, +450, }, 29.652 + { +22045, +14638, -7551, +1339, -401, -605, +1069, +20, -2608, -672, +522, -1429, +425, -2597, -667, -990, -1249, -1112, -381, +216, -660, +423, +180, +808, -430, +149, -101, -901, -420, -144, +988, +646, }, 29.653 + { +22374, +14605, -6584, +1379, -2012, -818, +1269, -52, -2715, -579, +90, -1306, +1138, -2771, -762, -975, -1284, -1081, -478, +502, -689, +317, +67, +770, -529, -3, +37, -932, -233, -321, +645, +1063, }, 29.654 + { +21971, +14982, -5381, +1465, -3401, -1307, +1361, -157, -2826, -434, -42, -1263, +1888, -2842, -1101, -790, -1377, -899, -394, +320, -814, +398, -273, +728, -246, -176, +85, -530, -151, -691, +222, +1349, }, 29.655 + { +21578, +15032, -3953, +1480, -4478, -2119, +1347, -259, -2912, +19, -196, -1128, +2559, -2963, -1432, -703, -946, -870, -888, +371, -914, +216, -287, +839, -198, -30, +401, -611, -215, -354, -239, +533, }, 29.656 + { +20935, +14892, -2350, +1522, -5169, -3135, +939, +47, -2856, +331, -223, -886, +3031, -3198, -1627, +82, -1303, -1105, -934, +12, -879, +350, -351, +790, +317, +101, -59, -207, +109, -776, -140, -183, }, 29.657 + { +19989, +14916, -1024, +1608, -5475, -4473, +295, +1065, -2834, +220, +84, -593, +2619, -2455, -1492, -396, -1160, -1373, -1255, +21, -642, +54, -86, +1220, -111, +160, +248, -322, +230, -981, +131, -465, }, 29.658 + { +19442, +14440, -244, +2209, -5944, -5867, +441, +1708, -2969, +837, -323, -569, +3451, -2723, -1540, -344, -1757, -1134, -1142, -251, -519, +531, -17, +686, +62, +600, -73, -568, +824, -1013, -326, +77, }, 29.659 + { +19215, +13282, +497, +2823, -6861, -6114, +314, +2076, -2340, +432, -449, +228, +3074, -2653, -1482, -1155, -1421, -644, -1745, -8, +375, -76, -205, +1100, -38, +316, +113, -497, +839, -778, -681, +216, }, 29.660 + { +18399, +12398, +1273, +2931, -6997, -6116, +179, +2120, -1724, +857, -1704, +1041, +3221, -3315, -1375, -1169, -1113, -795, -1352, +352, -102, -102, +206, +701, -238, +511, +174, -405, +646, -548, -516, -399, }, 29.661 + { +17103, +12076, +1628, +2442, -6317, -5062, -1021, +2253, +17, -617, -1910, +2032, +2182, -3218, -758, -1593, -918, +124, -1676, +57, +262, -74, -107, +549, -37, +456, +200, -287, +594, -479, -420, -621, }, 29.662 + { +17339, +11281, -244, +2822, -5940, -4177, +36, +1140, -56, -183, -2196, +2015, +1763, -3155, -461, -1392, -347, -94, -1944, +612, +306, -660, +4, +659, -17, +432, +20, -3, +720, -783, -494, -283, }, 29.663 + { +16567, +9681, +78, +3330, -6088, -2392, -403, +490, +834, -1104, -2339, +2535, +1400, -3259, +240, -1123, -378, -183, -1760, +840, -40, -771, +203, +636, -208, +524, +221, -45, +609, -787, -453, -228, }, 29.664 + { +15277, +8488, +278, +3885, -5037, -2468, -191, +698, +82, -1238, -1833, +2336, +911, -2516, +590, -1228, -341, -135, -1481, +650, -204, -726, +413, +395, -341, +823, +281, -147, +494, -733, -476, -140, }, 29.665 + { +14508, +10388, +2390, +614, -9568, -3171, +2824, +3138, -360, -1806, -3125, +365, +1587, -1832, +1166, -336, -464, +624, -617, +527, +1, -567, -177, -592, -325, +573, -499, -34, +977, -258, +261, -46, }, 29.666 + { +12204, +10145, +3137, +1381, -8141, -4350, +1999, +2595, +500, -763, -2949, -365, +1128, -983, +987, -357, -350, +719, -509, +347, +303, -394, -148, -488, -492, +295, -634, +121, +1110, -75, +436, -20, }, 29.667 + { +10618, +9407, +3284, +1743, -6720, -3899, +1478, +1813, +596, -356, -2413, -640, +1096, -622, +604, -220, -317, +679, -315, +187, +316, -151, -180, -467, -394, +122, -486, +261, +994, +154, +417, -67, }, 29.668 + { +8737, +8566, +3830, +1870, -5294, -3295, +668, +1407, +736, -98, -1874, -761, +1017, -457, +347, -65, -252, +598, -129, +108, +374, +35, -238, -389, -303, +101, -170, +351, +816, +261, +307, -90, }, 29.669 + { +7322, +7990, +4204, +1759, -4233, -2859, +204, +1225, +706, +89, -1428, -779, +812, -371, +310, +13, -255, +576, +48, +68, +394, +93, -230, -185, -105, +97, -62, +325, +596, +234, +208, -140, }, 29.670 + { +5934, +7313, +4453, +1864, -3250, -2602, -73, +1073, +737, +266, -1100, -695, +649, -339, +267, +163, -183, +531, +195, +93, +388, +271, +42, +55, -87, -115, -13, +235, +333, +198, +167, -56, }, 29.671 + { +5000, +6676, +4573, +2086, -2672, -2459, -188, +999, +803, +304, -865, -518, +450, -355, +364, +251, -120, +548, +192, +279, +680, +344, +32, +73, -196, -341, +1, +192, +208, +250, +135, -143, }, 29.672 + { +4456, +6275, +4433, +1984, -2322, -2108, -127, +872, +815, +394, -642, -454, +355, -269, +459, +303, -78, +714, +511, +458, +618, +237, -33, -56, -404, -289, +129, +56, +240, +141, -2, +127, }, 29.673 + { +3914, +5714, +4351, +2080, -2013, -1928, -97, +902, +872, +413, -420, -323, +306, -177, +447, +601, +422, +769, +448, +347, +442, +17, -200, -32, -412, -202, +177, -120, +89, +302, +138, +79, }, 29.674 + { +3687, +5529, +4104, +1830, -1878, -1601, +73, +886, +904, +439, -190, -238, +213, +104, +832, +826, +315, +493, +327, +220, +233, -30, -126, -120, -318, -150, -96, +60, +301, +96, +30, +144, }, 29.675 + { +3580, +5372, +3781, +1521, -1776, -1190, +327, +859, +987, +532, -67, +9, +629, +331, +636, +568, +95, +278, +193, +191, +184, -23, -203, -172, -324, -16, +176, -130, +89, +51, +115, +194, }, 29.676 + { +3492, +5329, +3471, +1350, -1561, -940, +597, +949, +959, +721, +441, +128, +352, +175, +389, +425, +9, +204, +280, +156, +63, -22, -262, -158, +108, -5, -216, -107, +108, +31, +78, +239, }, 29.677 + { +3432, +5245, +3183, +1194, -1128, -596, +840, +1170, +1253, +888, +199, -114, +53, +17, +302, +263, +132, +181, +140, +117, +66, -50, -59, +236, -176, -301, -113, -66, -72, -13, +269, +19, }, 29.678 + { +3390, +5248, +2963, +1119, -596, -247, +1125, +1471, +935, +484, +120, -201, +1, -69, +296, +276, +64, +116, +141, +246, -26, +224, +239, -232, -240, -143, -165, -208, -22, +53, +4, +96, }, 29.679 + { +3459, +5308, +2829, +1096, -226, +235, +1196, +1070, +638, +314, +33, -149, +26, -184, +259, +284, -110, +166, +359, +85, +180, +500, -207, -255, -125, -253, -294, -112, -3, -243, +82, +267, }, 29.680 + { +3444, +5608, +3052, +1048, -153, +152, +952, +951, +500, +280, +174, -297, -12, -51, +82, +247, +11, +278, +212, +303, +571, -23, -220, +24, -291, -435, -178, -82, -257, -114, +197, +358, }, 29.681 + { +3631, +5987, +3171, +840, -377, -261, +737, +1132, +564, +264, +192, -346, -126, +1, +155, +186, +152, +235, +119, +688, +415, -209, -47, -46, -307, -433, -160, -284, -252, +134, +257, +168, }, 29.682 + { +3555, +6368, +3416, +601, -552, -585, +576, +1098, +540, +380, +255, -412, -120, +84, +90, +257, +276, +51, +139, +958, +303, -229, +70, -105, -327, -291, -183, -450, -241, +244, +389, -20, }, 29.683 + { +3304, +6445, +3877, +542, -780, -691, +604, +1149, +403, +125, +220, -232, -86, +58, +247, +261, +126, +140, +91, +859, +535, -186, +15, -49, -295, -232, -192, -427, -225, +175, +356, +33, }, 29.684 + { +3095, +6398, +4320, +718, -1060, -852, +617, +1319, +551, -131, -94, -318, -227, +167, +484, +239, +130, +167, -116, +734, +786, -134, -76, +64, -201, -204, -176, -362, -225, +158, +343, -8, }, 29.685 + { +3043, +6443, +4566, +841, -1213, -1017, +635, +1471, +644, -187, -192, -362, -461, -72, +479, +445, +148, +181, -13, +421, +845, +87, -217, -18, -79, -55, -112, -366, -227, +211, +309, +49, }, 29.686 + { +3132, +6650, +4683, +897, -1394, -1203, +748, +1560, +723, -251, -284, -272, -531, -243, +278, +347, +138, +203, +193, +288, +760, +331, -284, -258, -57, +43, +11, -256, -228, +216, +280, +136, }, 29.687 + { +3367, +6988, +4849, +842, -1674, -1375, +807, +1795, +719, -420, -285, -270, -512, -280, +138, +254, -47, -57, +304, +307, +642, +594, -125, -511, -291, +9, +125, -134, -237, +289, +287, +139, }, 29.688 + { +3586, +7407, +5080, +656, -1907, -1495, +823, +2057, +683, -633, -291, -228, -494, -258, +64, +194, -36, -286, +173, +318, +479, +623, +210, -460, -540, -128, +140, -101, -240, +315, +252, +163, }, 29.689 + { +3913, +8036, +5294, +392, -2186, -1751, +902, +2457, +567, -915, -352, -187, -458, -275, +94, +106, -67, -364, +29, +257, +307, +466, +372, -273, -572, -259, +20, -46, -279, +200, +193, +90, }, 29.690 + { +4032, +8688, +5666, +129, -2445, -1998, +927, +2764, +585, -1205, -445, -136, -465, -297, +145, +30, -86, -398, -75, +234, +196, +315, +365, -111, -602, -339, +4, +2, -305, +120, +111, -149, }, 29.691 + { +4592, +9563, +5846, -404, -2900, -2105, +1130, +3189, +362, -1558, -421, -109, -448, -336, +218, +21, -218, -346, -123, +178, +175, +130, +357, -19, -545, -388, -95, -2, -115, +87, -12, -264, }, 29.692 + { +5108, +10372, +5960, -878, -3340, -2212, +1378, +3487, +158, -1928, -397, -33, -497, -372, +269, +15, -353, -346, -123, +153, +121, -36, +345, +17, -453, -394, -151, -80, -129, +237, -86, -306, }, 29.693 + { +5903, +11205, +5822, -1373, -3825, -2282, +1849, +3676, -196, -2204, -349, +96, -588, -398, +334, +40, -480, -394, -80, +155, +103, -202, +283, +76, -376, -305, -191, -130, -153, +273, -64, -333, }, 29.694 + { +6463, +12077, +6105, -1736, -4427, -2497, +2172, +3937, -457, -2637, -316, +269, -650, -515, +328, +128, -574, -464, -145, +165, +112, -359, +102, +133, -284, -189, -158, -224, -158, +175, +22, -412, }, 29.695 + { +6842, +12772, +6370, -1805, -4912, -2802, +2482, +4054, -577, -3009, -381, +505, -711, -614, +320, +143, -632, -456, -212, +124, +133, -429, -89, +129, -159, -163, +4, -302, -109, +98, -9, -351, }, 29.696 + { +7495, +13436, +6402, -1641, -5389, -3222, +2902, +4096, -819, -3320, -508, +760, -709, -801, +367, +144, -733, -443, -242, +90, +109, -405, -353, -3, +96, -160, +135, -243, -147, +159, -109, -342, }, 29.697 + { +8302, +13982, +6007, -1545, -5551, -3449, +3272, +3931, -1108, -3384, -659, +902, -637, -984, +381, +171, -829, -414, -266, +67, +40, -321, -455, -318, +312, -35, +128, -72, -215, +189, -55, -445, }, 29.698 + { +9896, +14670, +4570, -1730, -5262, -3249, +3511, +3414, -1572, -3150, -826, +851, -414, -1191, +310, +159, -852, -430, -228, +45, -97, -288, -414, -643, +337, +260, +1, +181, -141, +21, +120, -543, }, 29.699 + { +11175, +14744, +3448, -993, -4976, -3811, +3696, +3441, -2038, -3160, -852, +834, -325, -1343, +248, +102, -877, -401, -118, -49, -199, -292, -342, -788, +115, +605, -66, +267, +58, -136, +206, -540, }, 29.700 + { +12433, +14644, +2289, -11, -4664, -4428, +3847, +3503, -2546, -3196, -721, +719, -321, -1413, +201, -27, -944, -298, +67, -214, -293, -242, -375, -807, -141, +822, +24, +219, +276, -175, +133, -469, }, 29.701 + { +14253, +15077, +91, +194, -3679, -4227, +3554, +3173, -2873, -3182, -505, +510, -236, -1531, +106, -141, -941, -242, +293, -223, -457, -200, -494, -638, -319, +772, +318, +229, +335, -59, -21, -432, }, 29.702 + { +16147, +15220, -1962, +114, -2901, -3609, +3134, +2739, -3044, -3270, -314, +358, -218, -1704, +85, -332, -895, -157, +414, -203, -648, -134, -650, -486, -341, +596, +483, +347, +229, -1, -55, -568, }, 29.703 + { +17862, +15961, -4207, -422, -1951, -2655, +2484, +2264, -2914, -3618, -117, +208, -161, -1924, +25, -473, -800, -35, +478, -79, -937, -17, -769, -367, -225, +425, +413, +582, +113, -133, +87, -734, }, 29.704 + { +19449, +16392, -5859, -1112, -1427, -1629, +1942, +1918, -2765, -3978, -8, +84, -134, -2062, -13, -566, -654, +37, +477, +32, -1157, +83, -816, -331, +13, +340, +96, +768, +67, -341, +213, -694, }, 29.705 + { +21050, +17015, -7348, -2198, -1140, -508, +1499, +1662, -2610, -4451, +6, -138, -34, -2121, -29, -596, -503, +48, +407, +189, -1351, +208, -923, -200, +286, +156, -272, +696, +143, -514, +278, -464, }, 29.706 + { +22180, +17691, -8318, -3153, -1264, +222, +1444, +1546, -2552, -4822, -136, -360, +172, -2054, -32, -523, -483, -7, +341, +375, -1419, +217, -913, -27, +273, +51, -545, +431, +314, -476, +252, -284, }, 29.707 + { +23145, +18305, -8899, -3912, -1872, +754, +1676, +1457, -2542, -5140, -436, -571, +593, -1943, -18, -391, -590, -105, +360, +600, -1486, +265, -834, -64, +157, -1, -808, +207, +535, -343, +188, -148, }, 29.708 + { +24201, +18791, -9169, -4533, -3193, +1197, +2201, +1353, -2588, -5477, -898, -646, +1316, -1907, +112, -361, -830, -56, +459, +703, -1301, +324, -1128, -106, +17, -169, -828, +111, +625, -123, +274, -146, }, 29.709 + { +25039, +18854, -8960, -4922, -4675, +1488, +2597, +1309, -2785, -5629, -1226, -537, +1894, -1872, +177, -569, -818, +47, +414, +930, -1141, -66, -1306, -147, -197, -117, -643, -26, +588, +205, +269, -377, }, 29.710 + { +25483, +18997, -8159, -5303, -6464, +1415, +3101, +1247, -3048, -5328, -1549, -448, +2627, -1908, -26, -525, -721, +144, +628, +830, -1334, -263, -1576, -203, -94, -5, -521, -41, +604, +221, +328, -313, }, 29.711 + { +25310, +19394, -7240, -5364, -8082, +861, +3602, +1021, -2853, -4841, -1925, -274, +3034, -1996, -184, -315, -585, +480, +190, +564, -1199, -604, -1602, -1, -64, +5, -267, -39, +307, +300, +702, -524, }, 29.712 + { +25187, +19126, -5747, -5306, -10048, +5, +3816, +1259, -2439, -4328, -2144, -285, +3285, -2132, -193, +313, -577, +11, -100, +308, -1123, -638, -1463, +80, -40, +174, -302, -152, +368, +273, +817, -512, }, 29.713 + { +24584, +19059, -4370, -5103, -11540, -1206, +4149, +1948, -2239, -3792, -2260, -463, +3232, -1933, +310, +264, -1049, -39, -461, +305, -807, -683, -1310, +216, -69, -19, -134, -7, +199, +192, +1012, -495, }, 29.714 + { +24229, +18498, -3219, -4673, -13052, -2239, +4802, +2529, -2152, -3029, -2527, -945, +3759, -1608, +81, +180, -1445, -83, -369, +279, -585, -589, -996, -15, -262, +176, +17, -164, +214, +234, +1010, -493, }, 29.715 + { +23479, +17761, -2169, -4054, -14542, -2764, +5166, +3024, -1593, -2674, -3100, -489, +3855, -1932, +199, -475, -1408, +376, -646, +385, -160, -507, -1201, -125, -73, +89, +2, -134, +277, +184, +889, -456, }, 29.716 + { +22902, +16611, -1241, -3921, -14659, -3126, +5151, +3820, -1738, -2209, -3026, -680, +3843, -2076, -205, -376, -1050, +290, -561, +675, -171, -734, -967, -54, -279, +107, +127, -143, +289, +105, +906, -440, }, 29.717 + { +21520, +15491, -466, -3170, -14169, -3623, +5060, +3934, -933, -1908, -3770, -160, +3317, -2389, +45, -293, -930, +570, -302, +294, -117, -531, -816, -259, -393, +309, +177, -338, +355, +325, +623, -455, }, 29.718 + { +20196, +14258, -26, -2087, -13378, -3959, +4522, +4579, -753, -2187, -3650, -282, +3062, -2403, +220, -314, -596, +900, -834, +333, +193, -640, -766, -353, -377, +474, -67, -401, +722, +187, +352, -286, }, 29.719 + { +18562, +12495, +606, -395, -12713, -4067, +4718, +3983, -631, -1865, -4106, +267, +2676, -2530, +544, -90, -270, +517, -885, +629, +178, -816, -539, -358, -375, +420, -176, -225, +814, +58, +205, -176, }, 29.720 + { +16507, +11335, +1670, +425, -11680, -3415, +3753, +3482, -140, -2175, -3676, +452, +2142, -2340, +899, +31, -525, +540, -719, +620, +74, -768, -288, -458, -444, +527, -237, -258, +969, -83, +155, -100, }, 29.721 + { +15749, +11088, +540, -1465, -10587, +5, +4768, +1482, -1271, -1294, -2408, -204, +2109, -2180, +700, +142, -524, +394, -343, +524, -78, -510, -510, -119, -176, +83, +45, -8, -121, -132, +846, -57, }, 29.722 + { +12780, +11168, +3101, -713, -10375, -2419, +3165, +2486, +741, -926, -2637, -901, +1193, -1380, +1171, +201, -695, +683, -287, +203, +326, -265, -402, +216, -760, -316, +56, -240, +385, +349, +800, +38, }, 29.723 + { +10481, +10174, +3731, +12, -8189, -2627, +2287, +2162, +639, -620, -1980, -947, +827, -877, +947, +162, -591, +622, -179, +124, +414, -151, -214, +218, -687, -257, +155, -179, +273, +413, +653, +58, }, 29.724 + { +8668, +9236, +4001, +664, -6447, -2669, +1688, +1709, +604, -245, -1509, -943, +653, -570, +711, +170, -456, +560, -83, +116, +460, +30, -144, +259, -390, -222, +102, -244, +172, +370, +519, +108, }, 29.725 + { +7283, +8384, +4111, +1067, -5156, -2491, +1257, +1309, +661, +29, -1138, -850, +514, -376, +522, +237, -336, +496, +41, +153, +499, +232, +59, +319, -295, -329, -17, -275, -28, +319, +573, +102, }, 29.726 + { +6272, +7691, +4060, +1222, -4187, -2162, +939, +1051, +723, +183, -806, -720, +436, -270, +454, +290, -208, +496, +100, +362, +696, +335, +52, +222, -281, -423, -148, -305, -83, +332, +591, +108, }, 29.727 + { +5580, +7158, +3875, +1174, -3460, -1834, +755, +904, +761, +294, -524, -552, +331, -184, +477, +333, -134, +601, +379, +449, +583, +227, -20, +147, -340, -469, -157, -333, -172, +385, +542, +14, }, 29.728 + { +5099, +6769, +3611, +1012, -2865, -1522, +671, +853, +823, +385, -298, -392, +284, -75, +496, +488, +66, +592, +366, +331, +409, +167, -75, +79, -239, -485, -266, -327, -145, +317, +622, +200, }, 29.729 + { +4774, +6505, +3318, +801, -2367, -1254, +708, +915, +878, +465, -124, -221, +265, +118, +634, +457, -4, +374, +332, +279, +241, +173, -17, +50, -250, -474, -271, -392, +13, +518, +389, +79, }, 29.730 + { +4533, +6373, +3052, +547, -1931, -979, +831, +1054, +874, +581, -34, -52, +431, +69, +479, +349, -93, +183, +314, +308, +170, +203, +2, -44, -122, -409, -440, -16, +135, +84, +235, +185, }, 29.731 + { +4382, +6335, +2815, +384, -1572, -712, +951, +1234, +846, +634, +201, -204, +344, +11, +311, +320, -174, +46, +261, +434, +123, +92, +101, +62, -245, -261, -49, -321, -116, +108, +125, +189, }, 29.732 + { +4310, +6316, +2697, +377, -1265, -560, +1000, +1283, +976, +592, +177, -342, +94, +124, +234, +277, -211, -42, +322, +339, +136, +155, +187, -53, -7, +128, -468, -481, -77, +89, +78, +112, }, 29.733 + { +4220, +6370, +2803, +455, -1043, -593, +884, +1257, +898, +647, +131, -407, +17, -24, +259, +268, -143, -71, +248, +315, +54, +318, +56, +134, +452, -358, -580, -280, -245, +17, +207, +32, }, 29.734 + { +4238, +6578, +2947, +418, -979, -561, +705, +1063, +778, +509, +327, -311, -141, -2, +117, +252, +15, +34, +169, +147, +205, +145, +62, +724, +153, -621, -342, -314, -253, +63, +216, -198, }, 29.735 + { +4312, +6878, +3119, +203, -1024, -566, +664, +1052, +477, +317, +296, -326, +41, -20, +78, +256, -64, +129, +238, +109, +104, +11, +281, +812, -119, -527, -289, -348, -126, +151, +43, -331, }, 29.736 + { +4243, +7275, +3432, -18, -1154, -711, +722, +1244, +373, +111, +88, -498, -48, +145, +283, +267, -58, +72, +167, +174, +186, -87, +222, +896, -239, -530, -150, -376, +16, +248, -104, -319, }, 29.737 + { +4240, +7629, +3820, -212, -1418, -875, +841, +1446, +395, +35, -59, -651, -337, +57, +348, +394, +138, +74, +125, +94, +212, -51, +148, +896, -296, -557, -109, -348, +139, +310, -89, -337, }, 29.738 + { +4267, +8079, +4161, -358, -1708, -1137, +1013, +1624, +419, -13, -148, -667, -486, -153, +260, +306, +109, +213, +291, +100, +122, +47, -84, +791, +19, -750, -253, -252, +190, +325, -24, -265, }, 29.739 + { +4428, +8579, +4533, -649, -2161, -1157, +1152, +1818, +471, -285, -99, -625, -629, -167, +110, +208, -67, +58, +397, +149, +182, +241, -312, +521, +338, -764, -423, -220, +99, +352, +41, -277, }, 29.740 + { +4663, +9147, +5017, -957, -2713, -1191, +1270, +2062, +456, -561, -64, -490, -728, -151, +48, +95, -93, -149, +333, +236, +4, +377, -80, +107, +501, -359, -693, -415, +113, +346, +3, -240, }, 29.741 + { +4794, +9798, +5715, -1328, -3293, -1331, +1372, +2391, +376, -861, -165, -318, -751, -218, +113, -43, -176, -257, +208, +326, -101, +123, +104, -60, +376, +187, -610, -661, -80, +210, +60, -231, }, 29.742 + { +4706, +10404, +6857, -1587, -4043, -1501, +1416, +2768, +428, -1274, -318, -83, -773, -321, +190, -68, -276, -333, +89, +301, +70, -126, -66, -7, +48, +426, +52, -740, -438, +212, -62, -314, }, 29.743 + { +5492, +11533, +6802, -2410, -4639, -1493, +1942, +3028, +51, -1662, -327, +15, -748, -355, +194, -55, -404, -364, +59, +221, +123, -131, -285, -124, -44, +334, +429, -330, -642, -6, -1, -451, }, 29.744 + { +5983, +12434, +7309, -2945, -5475, -1428, +2301, +3203, -66, -2148, -439, +316, -869, -393, +284, -166, -434, -371, -45, +257, +65, -121, -270, -467, -42, +274, +467, +199, -506, -380, +16, -415, }, 29.745 + { +6553, +13345, +7759, -3488, -6279, -1393, +2735, +3371, -353, -2547, -584, +610, -877, -578, +354, -136, -577, -381, +10, +115, +137, -230, -229, -570, -338, +370, +460, +362, -28, -508, -363, -242, }, 29.746 + { +7471, +14327, +7633, -4021, -6946, -1337, +3324, +3391, -814, -2875, -657, +809, -860, -751, +399, -191, -586, -460, +66, +94, +17, -214, -308, -558, -507, +258, +589, +343, +231, -149, -748, -423, }, 29.747 + { +8279, +15118, +7553, -4198, -7540, -1469, +3893, +3301, -1178, -3117, -875, +1005, -790, -1000, +413, -197, -660, -436, +72, +94, -104, -258, -361, -556, -505, +12, +646, +436, +181, +263, -660, -907, }, 29.748 + { +9124, +15874, +7171, -4175, -7769, -1782, +4384, +3236, -1562, -3240, -1066, +1125, -708, -1207, +337, -154, -693, -392, +105, +118, -192, -387, -322, -628, -341, -94, +398, +659, +143, +329, -199, -1184, }, 29.749 + { +10600, +16582, +5950, -4368, -7541, -1867, +4737, +3086, -2067, -3335, -1044, +1123, -740, -1306, +237, -176, -627, -343, +172, +164, -330, -475, -330, -675, -210, +76, +40, +658, +284, +168, +174, -1087, }, 29.750 + { +12376, +17175, +4171, -4522, -7036, -1733, +4785, +2866, -2442, -3529, -868, +972, -750, -1432, +142, -233, -536, -280, +203, +260, -566, -441, -421, -666, -125, +321, -234, +424, +421, +32, +318, -810, }, 29.751 + { +14090, +17881, +2149, -4729, -6335, -1510, +4556, +2689, -2622, -3826, -676, +683, -672, -1544, +43, -207, -493, -179, +161, +384, -803, -320, -525, -640, -11, +437, -358, +48, +480, -16, +337, -499, }, 29.752 + { +16479, +18100, -251, -5038, -5617, -895, +4158, +2494, -2872, -4087, -506, +369, -589, -1544, +53, -264, -351, -200, +196, +385, -925, -184, -637, -545, +96, +400, -519, -169, +313, +46, +383, -236, }, 29.753 + { +18719, +18354, -2535, -5382, -5077, -235, +3760, +2374, -3095, -4427, -427, +22, -354, -1411, +7, -243, -275, -312, +263, +406, -941, -99, -688, -428, +90, +202, -566, -359, +122, +172, +472, -78, }, 29.754 + { +20632, +18711, -4603, -5686, -4881, +473, +3484, +2242, -3308, -4836, -393, -315, +167, -1349, -10, -178, -419, -353, +354, +511, -957, -1, -751, -448, -19, +72, -604, -458, +57, +275, +400, +168, }, 29.755 + { +22360, +19050, -6299, -6014, -5124, +1226, +3414, +2007, -3540, -5278, -311, -473, +850, -1407, +137, -306, -606, -202, +424, +682, -953, +71, -1092, -494, -36, -56, -597, -263, -49, +181, +480, +340, }, 29.756 + { +23853, +19254, -7494, -6434, -5724, +1855, +3501, +1649, -3877, -5514, -94, -559, +1541, -1479, +150, -510, -585, -3, +419, +893, -1016, -259, -1392, -389, -165, +23, -418, -178, -252, +244, +451, +239, }, 29.757 + { +25329, +18892, -8176, -6707, -6565, +2362, +3636, +1174, -4256, -5023, -220, -362, +2101, -1684, +93, -508, -345, +44, +530, +734, -1282, -474, -1490, -397, +61, +190, -464, -83, -222, +71, +299, +421, }, 29.758 + { +26132, +18615, -8557, -6606, -7720, +2662, +3828, +564, -4070, -4493, -377, -142, +2382, -2009, +159, -193, -269, +57, +124, +489, -1273, -596, -1558, -23, +257, +40, -292, +5, -420, -52, +361, +377, }, 29.759 + { +26097, +18760, -8279, -6563, -9338, +2395, +4427, +354, -3683, -4052, -417, -411, +2686, -2127, +394, +208, -612, -267, -183, +547, -1260, -477, -1400, +110, +235, +53, -183, -98, -337, -206, +404, +296, }, 29.760 + { +26298, +17883, -7539, -6429, -11135, +2349, +5208, +297, -3531, -3208, -932, -479, +3059, -2027, +586, +52, -1210, -243, -201, +410, -847, -361, -1398, +182, +205, +3, -91, -95, -338, -279, +476, +239, }, 29.761 + { +25890, +16998, -6703, -6158, -12691, +2616, +5823, +131, -2985, -2746, -1498, -267, +3567, -2288, +598, -395, -1379, +90, -420, +614, -490, -504, -1389, +217, +123, -23, -40, -116, -280, -344, +578, +55, }, 29.762 + { +24947, +16037, -5788, -5689, -13461, +2608, +6096, +412, -2813, -2278, -1596, -192, +3523, -2540, +252, -341, -1212, +134, -205, +703, -394, -619, -1225, +253, -81, +26, +22, -90, -211, -394, +628, +37, }, 29.763 + { +23244, +14939, -4628, -4799, -13452, +2196, +6207, +481, -2338, -1733, -1999, -166, +3296, -2924, +380, -214, -1290, +655, -260, +536, -282, -573, -1003, -3, -66, +82, +42, -31, -237, -351, +712, -93, }, 29.764 + { +21175, +13481, -2942, -3774, -12857, +1570, +5657, +1162, -1877, -1714, -2063, -297, +2743, -2620, +466, -249, -749, +711, -463, +451, -19, -579, -1025, +20, -106, +79, +79, -61, -143, -304, +645, -60, }, 29.765 + { +18636, +12183, -1209, -2590, -11846, +582, +5371, +1609, -1826, -1340, -2309, -463, +2623, -2468, +485, +42, -543, +537, -540, +593, +20, -722, -705, -39, -175, +121, +49, +1, -116, -325, +749, +25, }, 29.766 + { +14783, +9489, -2982, -1023, -3993, +3280, +1929, -1888, -1700, +251, +285, -164, +1356, -1971, +151, -32, -982, +252, -342, +144, -27, -417, -521, +840, -3, +115, +200, -545, +44, -370, -154, +120, }, 29.767 + { +12635, +9338, -1709, -1092, -3762, +2615, +2298, -1249, -1537, +64, +39, -164, +1209, -1626, +74, +120, -732, +178, -175, +161, -27, -373, -563, +683, +104, +109, +334, -384, -11, -279, -152, +39, }, 29.768 + { +10824, +8969, -613, -1061, -3373, +2063, +2390, -782, -1282, -126, -128, -73, +1005, -1268, +42, +226, -527, +136, -29, +165, -13, -304, -520, +542, +230, +129, +323, -272, -56, -204, -196, -8, }, 29.769 + { +9429, +8572, +94, -1038, -2958, +1688, +2332, -399, -1026, -257, -166, -8, +812, -970, +100, +281, -355, +129, +93, +200, -9, -181, -418, +422, +262, +108, +261, -198, -85, -190, -163, -35, }, 29.770 + { +8397, +8228, +487, -1075, -2536, +1429, +2193, -104, -809, -286, -144, +0, +671, -693, +170, +287, -214, +140, +163, +259, +27, -77, -357, +258, +245, +93, +144, -149, -82, -138, -162, -157, }, 29.771 + { +7612, +7949, +682, -1088, -2127, +1227, +2044, +150, -627, -240, -104, +9, +638, -490, +230, +309, -107, +161, +239, +304, +6, -19, -321, +91, +206, +63, +62, -59, -63, -155, -170, -131, }, 29.772 + { +6952, +7827, +766, -1099, -1787, +1048, +1937, +367, -509, -160, +31, -46, +675, -344, +225, +366, -39, +163, +218, +347, -43, -35, -270, -73, +151, +125, +10, -31, -65, -114, -144, -245, }, 29.773 + { +6683, +7602, +752, -1154, -1469, +1022, +1800, +518, -463, -59, +237, -126, +665, -182, +167, +400, +1, +65, +208, +350, -66, -128, -244, -86, +66, +169, -26, -43, +21, -177, -95, +91, }, 29.774 + { +6328, +7603, +798, -1168, -1193, +1003, +1709, +558, -362, -97, +468, -68, +448, +37, +143, +230, +82, +36, +95, +341, -19, -201, -272, +32, -38, +101, +81, -48, -56, +78, +109, -161, }, 29.775 + { +6163, +7555, +882, -1153, -951, +1060, +1636, +512, -380, -40, +469, +81, +403, -73, +284, +126, -61, +146, +60, +209, +16, -67, -335, -42, +24, +86, +40, -88, +270, +181, -136, -94, }, 29.776 + { +6061, +7646, +945, -1152, -751, +1127, +1592, +462, -481, -102, +513, +8, +479, -8, +120, +232, -121, -17, +188, +182, -85, +28, -226, -217, -8, +203, -144, +134, +478, -84, -37, -109, }, 29.777 + { +6159, +7784, +897, -1252, -582, +1290, +1597, +367, -567, -244, +423, +7, +359, +71, +248, +105, -133, +44, +12, +207, +16, -67, -239, -155, +10, -42, -17, +448, +145, -81, +130, -268, }, 29.778 + { +6295, +8059, +874, -1507, -476, +1456, +1680, +362, -767, -349, +394, -179, +254, +82, +233, +237, -141, -70, +113, +103, -91, +65, -321, -165, +80, -154, +82, +449, -28, -5, +49, -241, }, 29.779 + { +6464, +8458, +884, -1785, -437, +1608, +1780, +391, -878, -494, +409, -232, +50, -6, +273, +208, -116, +68, +65, +99, -84, -65, -354, -36, +94, -209, +217, +427, -208, -3, +52, -229, }, 29.780 + { +6683, +8970, +878, -2165, -376, +1753, +1869, +420, -1047, -513, +453, -325, -68, -78, +177, +166, -163, +34, +201, +156, -170, -62, -410, -135, +213, -121, +156, +486, -231, -110, -45, -202, }, 29.781 + { +7075, +9466, +776, -2530, -318, +1953, +1897, +349, -1235, -528, +610, -389, -209, -190, +180, +87, -332, -2, +206, +167, -129, -48, -464, -135, +204, -153, +111, +606, -167, -304, -61, -230, }, 29.782 + { +7586, +10041, +588, -2915, -206, +2202, +1934, +234, -1428, -528, +819, -402, -344, -230, +142, +32, -392, -123, +176, +151, -193, +34, -366, -138, +241, -59, -155, +594, +203, -426, -180, -174, }, 29.783 + { +8284, +10637, +233, -3349, -82, +2488, +1888, +4, -1707, -479, +1011, -436, -518, -321, +180, -80, -546, -130, +97, -3, -257, -57, -259, -35, +170, +42, -299, +295, +418, -294, -381, -148, }, 29.784 + { +9095, +11203, -132, -3724, +50, +2818, +1819, -242, -2019, -371, +1236, -443, -675, -423, +213, -107, -683, -188, +152, -197, -308, -122, -264, +206, +142, +61, -245, -25, +422, +25, -540, -195, }, 29.785 + { +9889, +11877, -498, -4104, +128, +3146, +1756, -530, -2290, -350, +1519, -489, -802, -515, +198, -156, -758, -285, +204, -324, -438, -107, -349, +396, +198, +14, -193, -173, +148, +358, -427, -465, }, 29.786 + { +10582, +12562, -764, -4376, +91, +3406, +1737, -827, -2467, -415, +1769, -548, -939, -576, +195, -234, -826, -350, +190, -335, -585, -69, -435, +512, +288, -37, -200, -225, -129, +406, -34, -688, }, 29.787 + { +11306, +13237, -1039, -4536, -26, +3591, +1718, -1098, -2614, -469, +1956, -571, -1083, -632, +173, -288, -912, -416, +136, -318, -675, -9, -461, +518, +395, -47, -243, -278, -292, +231, +360, -602, }, 29.788 + { +12126, +13732, -1324, -4530, -169, +3644, +1688, -1289, -2721, -525, +2075, -627, -1199, -662, +140, -328, -973, -491, +59, -292, -671, -19, -361, +462, +431, -38, -247, -401, -359, +38, +478, -239, }, 29.789 + { +13174, +14048, -1834, -4351, -231, +3530, +1631, -1424, -2802, -592, +2109, -667, -1235, -700, +112, -376, -980, -597, +19, -296, -588, -73, -240, +447, +337, +12, -264, -517, -447, +2, +295, +152, }, 29.790 + { +13912, +14689, -2549, -4087, -276, +3213, +1690, -1511, -2845, -778, +2173, -760, -1162, -780, +32, -364, -1053, -628, -102, -130, -603, -57, -165, +414, +214, +87, -300, -593, -470, -60, +82, +348, }, 29.791 + { +15735, +14399, -3901, -3481, -192, +2964, +1469, -1601, -3017, -661, +2045, -910, -920, -980, +113, -561, -1039, -685, -48, -104, -573, +16, -218, +402, +105, +138, -407, -536, -465, -206, -44, +459, }, 29.792 + { +17507, +14116, -5426, -2751, -192, +2764, +1237, -1736, -3152, -642, +2056, -1032, -638, -1128, +153, -726, -1046, -569, -51, -121, -478, +1, -396, +547, -27, +111, -333, -501, -516, -340, +19, +317, }, 29.793 + { +19177, +13698, -6887, -1985, -243, +2671, +917, -1892, -3302, -557, +2196, -1213, -249, -1266, +144, -850, -933, -377, -271, +44, -521, -211, -328, +623, -195, +277, -239, -659, -459, -299, -118, +155, }, 29.794 + { +20876, +12896, -8162, -1221, -405, +2653, +504, -2083, -3425, -193, +2142, -1312, +212, -1534, +162, -820, -758, -426, -316, +25, -728, -166, -380, +694, -108, +401, -373, -670, -277, -461, -291, +192, }, 29.795 + { +22269, +11988, -9087, -514, -824, +2741, +141, -2324, -3367, +226, +1930, -1209, +579, -1900, +451, -737, -828, -320, -621, -37, -648, -370, -319, +1024, -166, +363, -328, -614, -348, -565, -333, +183, }, 29.796 + { +22436, +12036, -9756, +12, -1484, +2839, +192, -2651, -3134, +304, +2024, -1272, +960, -2016, +603, -606, -966, -471, -868, +179, -932, -258, -187, +1149, -274, +472, -264, -806, -269, -673, -333, +115, }, 29.797 + { +22976, +10737, -9315, +116, -2333, +3251, +276, -2916, -2945, +644, +1634, -1050, +1433, -2250, +799, -568, -1370, -360, -902, +24, -701, -266, -133, +1143, -162, +431, -320, -856, -257, -656, -421, +206, }, 29.798 + { +22156, +10670, -8825, +31, -3255, +3766, +558, -3195, -2534, +719, +1180, -629, +1637, -2399, +832, -768, -1413, -237, -975, +241, -538, -329, -188, +1315, -228, +362, -275, -900, -124, -757, -357, +287, }, 29.799 + { +21278, +9846, -7554, -398, -3803, +4159, +764, -3114, -2412, +808, +1003, -456, +1754, -2523, +558, -585, -1493, -124, -765, +323, -452, -399, -154, +1291, -276, +265, -134, -876, -130, -701, -238, +296, }, 29.800 + { +19461, +9711, -6136, -768, -4103, +4127, +1289, -3000, -2181, +873, +525, -145, +1756, -2618, +563, -484, -1372, +57, -547, +215, -362, -384, -264, +1161, -298, +275, -17, -893, -58, -554, -229, +265, }, 29.801 + { +17277, +9611, -4621, -998, -4208, +3875, +1658, -2589, -1841, +534, +392, -46, +1442, -2298, +316, -236, -1201, +192, -408, +85, -140, -396, -437, +993, -150, +202, +81, -782, +50, -474, -177, +231, }, 29.802 + { +14172, +9673, -3573, -888, -1759, +2079, +423, -1986, -1744, +555, +790, -69, +1145, -1353, +372, +59, -818, -47, -210, +85, -314, -228, -308, +651, -194, +55, +187, -514, -187, -359, -318, -25, }, 29.803 + { +12049, +9447, -2228, -1231, -1752, +1946, +840, -1465, -1503, +155, +682, -24, +949, -1008, +142, +192, -555, +85, -44, +97, -161, -260, -418, +506, -91, +11, +275, -348, -145, -288, -275, -84, }, 29.804 + { +10303, +9142, -1241, -1401, -1603, +1679, +1080, -926, -1326, -100, +605, -40, +855, -692, +34, +292, -275, +96, +72, +212, -127, -202, -437, +334, -5, -31, +233, -223, -120, -232, -200, -174, }, 29.805 + { +9017, +8838, -619, -1486, -1392, +1440, +1205, -522, -1133, -209, +558, -14, +754, -391, +50, +313, -71, +90, +164, +296, -77, -139, -435, +174, +4, -91, +133, -78, -72, -176, -176, -213, }, 29.806 + { +8142, +8597, -267, -1538, -1157, +1261, +1254, -258, -963, -244, +541, +75, +679, -187, +160, +270, +1, +140, +187, +302, -55, -83, -444, +4, -35, -132, +106, +52, -76, -189, -49, -190, }, 29.807 + { +7622, +8383, -48, -1578, -899, +1181, +1234, -71, -944, -214, +551, +137, +707, -144, +260, +320, -94, +109, +245, +239, -123, -2, -426, -196, -30, -52, +38, -6, +17, -57, -187, -8, }, 29.808 + { +7332, +8319, +57, -1601, -631, +1238, +1135, +21, -967, -327, +659, +76, +672, +38, +199, +349, -41, -97, +208, +331, -233, -127, -295, -155, -164, -26, -20, -11, +90, -178, +192, +245, }, 29.809 + { +7317, +8418, -7, -1642, -367, +1419, +1147, -111, -974, -384, +550, +84, +565, +94, +364, +313, -68, -10, +86, +197, -143, -149, -385, -44, -17, -229, -53, +121, -114, +140, +435, -168, }, 29.810 + { +7367, +8733, -36, -1826, -124, +1616, +1200, -184, -1158, -452, +570, -113, +408, +131, +319, +450, -22, -49, +185, +112, -380, -100, -266, -117, -72, -71, +10, -213, +51, +444, +58, -226, }, 29.811 + { +7780, +9068, -243, -2044, +77, +1858, +1206, -274, -1289, -551, +596, -178, +200, -29, +344, +432, -90, +103, +283, +41, -414, -210, -414, +8, +0, -140, +15, -152, +111, +292, -78, -206, }, 29.812 + { +8345, +9580, -574, -2318, +346, +2040, +1168, -408, -1458, -527, +676, -258, +1, -124, +320, +310, -183, +87, +370, +84, -415, -236, -480, -21, -74, -20, +45, -230, +106, +351, -132, -434, }, 29.813 + { +9094, +10154, -1025, -2554, +632, +2229, +994, -595, -1621, -437, +874, -416, -132, -257, +352, +267, -420, +47, +366, +3, -398, -143, -510, +98, -129, -195, +92, -138, -60, +248, +111, -492, }, 29.814 + { +10041, +10768, -1614, -2719, +916, +2381, +756, -898, -1763, -304, +1151, -599, -325, -310, +358, +208, -536, -91, +282, -46, -529, -37, -456, +197, -31, -321, -13, -176, -156, +116, +291, -363, }, 29.815 + { +11107, +11413, -2234, -2770, +1108, +2450, +521, -1208, -1885, -154, +1431, -759, -498, -367, +419, +97, -627, -128, +121, -90, -589, -28, -356, +273, +33, -279, -81, -291, -313, -16, +331, +7, }, 29.816 + { +12280, +12021, -2906, -2717, +1134, +2377, +314, -1466, -2001, -37, +1641, -947, -595, -443, +445, +1, -745, -215, +22, -112, -652, -10, -293, +280, +22, -180, -159, -383, -467, -188, +208, +307, }, 29.817 + { +13475, +12606, -3625, -2517, +1014, +2161, +183, -1625, -2084, +8, +1791, -1103, -612, -507, +435, -57, -847, -324, -41, -71, -678, +57, -282, +263, -37, -62, -209, -455, -522, -398, +113, +417, }, 29.818 + { +14812, +13011, -4511, -2154, +806, +1834, +70, -1725, -2175, +16, +1867, -1208, -532, -590, +417, -130, -929, -396, -58, -66, -662, +121, -368, +291, -144, -1, -180, -513, -541, -616, +106, +375, }, 29.819 + { +16380, +13067, -5650, -1592, +605, +1495, -131, -1780, -2290, +40, +2010, -1367, -305, -662, +396, -248, -905, -354, -222, +46, -645, +6, -354, +338, -292, +124, -80, -658, -520, -638, -12, +271, }, 29.820 + { +17982, +12702, -6846, -878, +421, +1177, -463, -1808, -2473, +274, +2108, -1572, +121, -826, +355, -267, -731, -513, -308, +176, -908, +60, -376, +313, -223, +268, -136, -780, -340, -699, -278, +268, }, 29.821 + { +19157, +12247, -7860, -132, +149, +912, -724, -1957, -2452, +536, +2076, -1557, +521, -1124, +525, -122, -855, -442, -535, +76, -863, -69, -379, +601, -217, +257, -79, -739, -389, -790, -342, +200, }, 29.822 + { +19711, +11522, -8169, +401, -329, +905, -928, -2048, -2370, +752, +2017, -1467, +767, -1174, +691, -185, -760, -679, -713, +177, -1039, -25, -158, +692, -291, +423, -59, -878, -408, -762, -397, +110, }, 29.823 + { +19465, +10779, -7703, +460, -893, +1187, -817, -2234, -2246, +1019, +1640, -1190, +1218, -1460, +857, -119, -1111, -511, -817, +81, -770, -57, -137, +805, -201, +370, -136, -863, -389, -713, -437, +67, }, 29.824 + { +18333, +10203, -6584, +85, -1382, +1684, -563, -2346, -2049, +928, +1357, -671, +1226, -1413, +733, -229, -1009, -521, -666, +153, -618, -188, -102, +925, -315, +267, -79, -795, -334, -687, -385, +130, }, 29.825 + { +16441, +9946, -5138, -473, -1669, +2005, -91, -2252, -1996, +837, +1093, -412, +1392, -1542, +535, -11, -1080, -203, -475, +134, -478, -260, -105, +753, -285, +165, +32, -670, -301, -515, -295, +22, }, 29.826 + { +13089, +9529, -4017, -237, +483, +1183, -334, -1490, -1552, +647, +1264, -471, +629, -605, +562, -36, -643, -387, -501, +84, -371, -60, -86, +640, -100, +137, -1, -574, -350, -440, -324, -139, }, 29.827 + { +11898, +9621, -3405, -1165, +243, +1679, +179, -1312, -1709, +64, +1140, -239, +692, -458, +479, +250, -561, -188, -174, +41, -320, -165, -304, +589, -101, -43, +124, -435, -309, -354, -282, -103, }, 29.828 + { +10997, +9658, -2780, -1802, -26, +1783, +569, -947, -1662, -248, +967, -127, +729, -294, +466, +390, -354, -145, +46, +95, -329, -112, -479, +387, +17, -149, +90, -226, -277, -280, -149, -147, }, 29.829 + { +10403, +9825, -2433, -2099, -53, +1814, +738, -808, -1574, -372, +873, -167, +701, -213, +490, +502, -294, -53, +103, +45, -399, -57, -537, +124, +113, -120, +21, -185, -188, -248, -114, -74, }, 29.830 + { +10392, +9882, -2497, -2112, +324, +1944, +702, -937, -1618, -322, +898, -262, +449, -113, +460, +482, -188, -10, +186, -20, -556, -166, -451, +104, +9, -20, +13, -185, -148, -338, -76, +107, }, 29.831 + { +10862, +9834, -2867, -1780, +884, +2063, +422, -1170, -1644, -165, +979, -389, +198, -268, +566, +314, -335, +218, +172, -127, -560, -306, -505, +230, +61, -85, -17, -114, -234, -393, -69, +141, }, 29.832 + { +11578, +9958, -3241, -1267, +1305, +1835, +61, -1353, -1523, +172, +1158, -610, -59, -256, +501, +100, -434, +87, +156, -173, -554, -216, -452, +238, -8, +72, -57, -233, -279, -439, -54, +128, }, 29.833 + { +12590, +10282, -3669, -831, +1213, +1299, -204, -1324, -1305, +642, +1310, -929, -150, -265, +378, -166, -511, -226, -25, -77, -591, -30, -316, +195, -77, +192, -79, -444, -281, -501, -173, +158, }, 29.834 + { +13820, +10820, -4370, -641, +688, +719, -208, -1170, -1120, +1054, +1422, -1268, +60, -395, +126, -158, -785, -547, -55, -15, -622, +139, -270, +187, +11, +211, -203, -518, -250, -711, -272, +251, }, 29.835 + { +14973, +10840, -5035, -319, +215, +327, -180, -1056, -1001, +1357, +1436, -1376, +373, -623, +75, -133, -1012, -696, -148, +89, -603, +166, -149, +257, +111, +201, -249, -478, -375, -806, -271, +241, }, 29.836 + { +15155, +10582, -5238, +16, +115, +211, -361, -1141, -1066, +1374, +1522, -1325, +512, -561, +33, -137, -860, -968, -261, +174, -757, +281, -16, +297, +93, +272, -236, -631, -384, -770, -341, +145, }, 29.837 + { +14475, +9926, -4814, +144, +323, +523, -528, -1336, -1319, +1198, +1433, -1025, +675, -646, +308, -70, -834, -739, -508, +86, -551, +161, +29, +400, +61, +248, -225, -631, -389, -587, -390, -22, }, 29.838 + { +11096, +9607, -2841, -481, +1236, +612, -162, -1033, -885, +1058, +1197, -645, +47, -150, +202, +5, -433, -652, -254, -16, -605, +40, +33, +357, +315, +288, -273, -769, -633, -453, +2, +259, }, 29.839 + }, 29.840 + 29.841 + /* HRIR Delays */ 29.842 + { 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, }
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 30.2 +++ b/Alc/mixer.c Tue Oct 25 13:02:31 2011 -0700 30.3 @@ -0,0 +1,848 @@ 30.4 +/** 30.5 + * OpenAL cross platform audio library 30.6 + * Copyright (C) 1999-2007 by authors. 30.7 + * This library is free software; you can redistribute it and/or 30.8 + * modify it under the terms of the GNU Library General Public 30.9 + * License as published by the Free Software Foundation; either 30.10 + * version 2 of the License, or (at your option) any later version. 30.11 + * 30.12 + * This library is distributed in the hope that it will be useful, 30.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 30.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30.15 + * Library General Public License for more details. 30.16 + * 30.17 + * You should have received a copy of the GNU Library General Public 30.18 + * License along with this library; if not, write to the 30.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 30.20 + * Boston, MA 02111-1307, USA. 30.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 30.22 + */ 30.23 + 30.24 +#include "config.h" 30.25 + 30.26 +#include <math.h> 30.27 +#include <stdlib.h> 30.28 +#include <string.h> 30.29 +#include <ctype.h> 30.30 +#include <assert.h> 30.31 + 30.32 +#include "alMain.h" 30.33 +#include "AL/al.h" 30.34 +#include "AL/alc.h" 30.35 +#include "alSource.h" 30.36 +#include "alBuffer.h" 30.37 +#include "alListener.h" 30.38 +#include "alAuxEffectSlot.h" 30.39 +#include "alu.h" 30.40 +#include "bs2b.h" 30.41 + 30.42 + 30.43 +static __inline ALdouble point32(const ALfloat *vals, ALint step, ALint frac) 30.44 +{ return vals[0]; (void)step; (void)frac; } 30.45 +static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac) 30.46 +{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)); } 30.47 +static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac) 30.48 +{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], 30.49 + frac * (1.0/FRACTIONONE)); } 30.50 + 30.51 +static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac) 30.52 +{ return vals[0] * (1.0/32767.0); (void)step; (void)frac; } 30.53 +static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac) 30.54 +{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/32767.0); } 30.55 +static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac) 30.56 +{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], 30.57 + frac * (1.0/FRACTIONONE)) * (1.0/32767.0); } 30.58 + 30.59 +static __inline ALdouble point8(const ALbyte *vals, ALint step, ALint frac) 30.60 +{ return vals[0] * (1.0/127.0); (void)step; (void)frac; } 30.61 +static __inline ALdouble lerp8(const ALbyte *vals, ALint step, ALint frac) 30.62 +{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/127.0); } 30.63 +static __inline ALdouble cubic8(const ALbyte *vals, ALint step, ALint frac) 30.64 +{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], 30.65 + frac * (1.0/FRACTIONONE)) * (1.0/127.0); } 30.66 + 30.67 +#ifdef __GNUC__ 30.68 +#define LIKELY(x) __builtin_expect(!!(x), 1) 30.69 +#define UNLIKELY(x) __builtin_expect(!!(x), 0) 30.70 +#else 30.71 +#define LIKELY(x) (x) 30.72 +#define UNLIKELY(x) (x) 30.73 +#endif 30.74 + 30.75 +#if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H) 30.76 +#include <arm_neon.h> 30.77 + 30.78 +static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2], 30.79 + ALfloat (*RESTRICT Coeffs)[2], 30.80 + ALfloat left, ALfloat right) 30.81 +{ 30.82 + ALuint c; 30.83 + float32x4_t leftright4; 30.84 + { 30.85 + float32x2_t leftright2 = vdup_n_f32(0.0); 30.86 + leftright2 = vset_lane_f32(left, leftright2, 0); 30.87 + leftright2 = vset_lane_f32(right, leftright2, 1); 30.88 + leftright4 = vcombine_f32(leftright2, leftright2); 30.89 + } 30.90 + for(c = 0;c < HRIR_LENGTH;c += 2) 30.91 + { 30.92 + const ALuint o0 = (Offset+c)&HRIR_MASK; 30.93 + const ALuint o1 = (o0+1)&HRIR_MASK; 30.94 + float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]), 30.95 + vld1_f32((float32_t*)&Values[o1][0])); 30.96 + float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]); 30.97 + 30.98 + vals = vmlaq_f32(vals, coefs, leftright4); 30.99 + 30.100 + vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals)); 30.101 + vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals)); 30.102 + } 30.103 +} 30.104 + 30.105 +#else 30.106 + 30.107 +static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2], 30.108 + ALfloat (*RESTRICT Coeffs)[2], 30.109 + ALfloat left, ALfloat right) 30.110 +{ 30.111 + ALuint c; 30.112 + for(c = 0;c < HRIR_LENGTH;c++) 30.113 + { 30.114 + const ALuint off = (Offset+c)&HRIR_MASK; 30.115 + Values[off][0] += Coeffs[c][0] * left; 30.116 + Values[off][1] += Coeffs[c][1] * right; 30.117 + } 30.118 +} 30.119 + 30.120 +#endif 30.121 + 30.122 +#define DECL_TEMPLATE(T, sampler) \ 30.123 +static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \ 30.124 + const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \ 30.125 + ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \ 30.126 +{ \ 30.127 + const ALuint NumChannels = Source->NumChannels; \ 30.128 + const T *RESTRICT data = srcdata; \ 30.129 + const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep; \ 30.130 + ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \ 30.131 + ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \ 30.132 + ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep; \ 30.133 + ALuint pos, frac; \ 30.134 + FILTER *DryFilter; \ 30.135 + ALuint BufferIdx; \ 30.136 + ALuint increment; \ 30.137 + ALuint i, out, c; \ 30.138 + ALfloat value; \ 30.139 + \ 30.140 + increment = Source->Params.Step; \ 30.141 + \ 30.142 + DryBuffer = Device->DryBuffer; \ 30.143 + ClickRemoval = Device->ClickRemoval; \ 30.144 + PendingClicks = Device->PendingClicks; \ 30.145 + DryFilter = &Source->Params.iirFilter; \ 30.146 + \ 30.147 + pos = 0; \ 30.148 + frac = *DataPosFrac; \ 30.149 + \ 30.150 + for(i = 0;i < NumChannels;i++) \ 30.151 + { \ 30.152 + ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i]; \ 30.153 + ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i]; \ 30.154 + ALfloat *RESTRICT History = Source->HrtfHistory[i]; \ 30.155 + ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \ 30.156 + ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos; \ 30.157 + ALuint Offset = Source->HrtfOffset + OutPos; \ 30.158 + ALfloat Coeffs[HRIR_LENGTH][2]; \ 30.159 + ALuint Delay[2]; \ 30.160 + ALfloat left, right; \ 30.161 + \ 30.162 + pos = 0; \ 30.163 + frac = *DataPosFrac; \ 30.164 + \ 30.165 + for(c = 0;c < HRIR_LENGTH;c++) \ 30.166 + { \ 30.167 + Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \ 30.168 + Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \ 30.169 + } \ 30.170 + \ 30.171 + Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \ 30.172 + Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \ 30.173 + \ 30.174 + if(LIKELY(OutPos == 0)) \ 30.175 + { \ 30.176 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.177 + value = lpFilter2PC(DryFilter, i, value); \ 30.178 + \ 30.179 + History[Offset&SRC_HISTORY_MASK] = value; \ 30.180 + left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \ 30.181 + right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \ 30.182 + \ 30.183 + ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \ 30.184 + Coeffs[0][0] * left; \ 30.185 + ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \ 30.186 + Coeffs[0][1] * right; \ 30.187 + } \ 30.188 + for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \ 30.189 + { \ 30.190 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.191 + value = lpFilter2P(DryFilter, i, value); \ 30.192 + \ 30.193 + History[Offset&SRC_HISTORY_MASK] = value; \ 30.194 + left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \ 30.195 + right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \ 30.196 + \ 30.197 + Delay[0] += DelayStep[0]; \ 30.198 + Delay[1] += DelayStep[1]; \ 30.199 + \ 30.200 + Values[Offset&HRIR_MASK][0] = 0.0f; \ 30.201 + Values[Offset&HRIR_MASK][1] = 0.0f; \ 30.202 + Offset++; \ 30.203 + \ 30.204 + for(c = 0;c < HRIR_LENGTH;c++) \ 30.205 + { \ 30.206 + const ALuint off = (Offset+c)&HRIR_MASK; \ 30.207 + Values[off][0] += Coeffs[c][0] * left; \ 30.208 + Values[off][1] += Coeffs[c][1] * right; \ 30.209 + Coeffs[c][0] += CoeffStep[c][0]; \ 30.210 + Coeffs[c][1] += CoeffStep[c][1]; \ 30.211 + } \ 30.212 + \ 30.213 + DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \ 30.214 + DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \ 30.215 + \ 30.216 + frac += increment; \ 30.217 + pos += frac>>FRACTIONBITS; \ 30.218 + frac &= FRACTIONMASK; \ 30.219 + OutPos++; \ 30.220 + Counter--; \ 30.221 + } \ 30.222 + \ 30.223 + Delay[0] >>= 16; \ 30.224 + Delay[1] >>= 16; \ 30.225 + for(;BufferIdx < BufferSize;BufferIdx++) \ 30.226 + { \ 30.227 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.228 + value = lpFilter2P(DryFilter, i, value); \ 30.229 + \ 30.230 + History[Offset&SRC_HISTORY_MASK] = value; \ 30.231 + left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \ 30.232 + right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \ 30.233 + \ 30.234 + Values[Offset&HRIR_MASK][0] = 0.0f; \ 30.235 + Values[Offset&HRIR_MASK][1] = 0.0f; \ 30.236 + Offset++; \ 30.237 + \ 30.238 + ApplyCoeffs(Offset, Values, Coeffs, left, right); \ 30.239 + DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \ 30.240 + DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \ 30.241 + \ 30.242 + frac += increment; \ 30.243 + pos += frac>>FRACTIONBITS; \ 30.244 + frac &= FRACTIONMASK; \ 30.245 + OutPos++; \ 30.246 + } \ 30.247 + if(LIKELY(OutPos == SamplesToDo)) \ 30.248 + { \ 30.249 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.250 + value = lpFilter2PC(DryFilter, i, value); \ 30.251 + \ 30.252 + History[Offset&SRC_HISTORY_MASK] = value; \ 30.253 + left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \ 30.254 + right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \ 30.255 + \ 30.256 + PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \ 30.257 + Coeffs[0][0] * left; \ 30.258 + PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \ 30.259 + Coeffs[0][1] * right; \ 30.260 + } \ 30.261 + OutPos -= BufferSize; \ 30.262 + } \ 30.263 + \ 30.264 + for(out = 0;out < Device->NumAuxSends;out++) \ 30.265 + { \ 30.266 + ALeffectslot *Slot = Source->Params.Send[out].Slot; \ 30.267 + ALfloat WetSend; \ 30.268 + ALfloat *RESTRICT WetBuffer; \ 30.269 + ALfloat *RESTRICT WetClickRemoval; \ 30.270 + ALfloat *RESTRICT WetPendingClicks; \ 30.271 + FILTER *WetFilter; \ 30.272 + \ 30.273 + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \ 30.274 + continue; \ 30.275 + \ 30.276 + WetBuffer = Slot->WetBuffer; \ 30.277 + WetClickRemoval = Slot->ClickRemoval; \ 30.278 + WetPendingClicks = Slot->PendingClicks; \ 30.279 + WetFilter = &Source->Params.Send[out].iirFilter; \ 30.280 + WetSend = Source->Params.Send[out].WetGain; \ 30.281 + \ 30.282 + for(i = 0;i < NumChannels;i++) \ 30.283 + { \ 30.284 + pos = 0; \ 30.285 + frac = *DataPosFrac; \ 30.286 + \ 30.287 + if(LIKELY(OutPos == 0)) \ 30.288 + { \ 30.289 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 30.290 + value = lpFilter1PC(WetFilter, i, value); \ 30.291 + \ 30.292 + WetClickRemoval[0] -= value * WetSend; \ 30.293 + } \ 30.294 + for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \ 30.295 + { \ 30.296 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 30.297 + value = lpFilter1P(WetFilter, i, value); \ 30.298 + \ 30.299 + WetBuffer[OutPos] += value * WetSend; \ 30.300 + \ 30.301 + frac += increment; \ 30.302 + pos += frac>>FRACTIONBITS; \ 30.303 + frac &= FRACTIONMASK; \ 30.304 + OutPos++; \ 30.305 + } \ 30.306 + if(LIKELY(OutPos == SamplesToDo)) \ 30.307 + { \ 30.308 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 30.309 + value = lpFilter1PC(WetFilter, i, value); \ 30.310 + \ 30.311 + WetPendingClicks[0] += value * WetSend; \ 30.312 + } \ 30.313 + OutPos -= BufferSize; \ 30.314 + } \ 30.315 + } \ 30.316 + *DataPosInt += pos; \ 30.317 + *DataPosFrac = frac; \ 30.318 +} 30.319 + 30.320 +DECL_TEMPLATE(ALfloat, point32) 30.321 +DECL_TEMPLATE(ALfloat, lerp32) 30.322 +DECL_TEMPLATE(ALfloat, cubic32) 30.323 + 30.324 +DECL_TEMPLATE(ALshort, point16) 30.325 +DECL_TEMPLATE(ALshort, lerp16) 30.326 +DECL_TEMPLATE(ALshort, cubic16) 30.327 + 30.328 +DECL_TEMPLATE(ALbyte, point8) 30.329 +DECL_TEMPLATE(ALbyte, lerp8) 30.330 +DECL_TEMPLATE(ALbyte, cubic8) 30.331 + 30.332 +#undef DECL_TEMPLATE 30.333 + 30.334 + 30.335 +#define DECL_TEMPLATE(T, sampler) \ 30.336 +static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \ 30.337 + const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \ 30.338 + ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \ 30.339 +{ \ 30.340 + const ALuint NumChannels = Source->NumChannels; \ 30.341 + const T *RESTRICT data = srcdata; \ 30.342 + ALfloat (*DryBuffer)[MAXCHANNELS]; \ 30.343 + ALfloat *ClickRemoval, *PendingClicks; \ 30.344 + ALuint pos, frac; \ 30.345 + ALfloat DrySend[MAXCHANNELS][MAXCHANNELS]; \ 30.346 + FILTER *DryFilter; \ 30.347 + ALuint BufferIdx; \ 30.348 + ALuint increment; \ 30.349 + ALuint i, out, c; \ 30.350 + ALfloat value; \ 30.351 + \ 30.352 + increment = Source->Params.Step; \ 30.353 + \ 30.354 + DryBuffer = Device->DryBuffer; \ 30.355 + ClickRemoval = Device->ClickRemoval; \ 30.356 + PendingClicks = Device->PendingClicks; \ 30.357 + DryFilter = &Source->Params.iirFilter; \ 30.358 + for(i = 0;i < NumChannels;i++) \ 30.359 + { \ 30.360 + for(c = 0;c < MAXCHANNELS;c++) \ 30.361 + DrySend[i][c] = Source->Params.DryGains[i][c]; \ 30.362 + } \ 30.363 + \ 30.364 + pos = 0; \ 30.365 + frac = *DataPosFrac; \ 30.366 + \ 30.367 + for(i = 0;i < NumChannels;i++) \ 30.368 + { \ 30.369 + pos = 0; \ 30.370 + frac = *DataPosFrac; \ 30.371 + \ 30.372 + if(OutPos == 0) \ 30.373 + { \ 30.374 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.375 + \ 30.376 + value = lpFilter2PC(DryFilter, i, value); \ 30.377 + for(c = 0;c < MAXCHANNELS;c++) \ 30.378 + ClickRemoval[c] -= value*DrySend[i][c]; \ 30.379 + } \ 30.380 + for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \ 30.381 + { \ 30.382 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.383 + \ 30.384 + value = lpFilter2P(DryFilter, i, value); \ 30.385 + for(c = 0;c < MAXCHANNELS;c++) \ 30.386 + DryBuffer[OutPos][c] += value*DrySend[i][c]; \ 30.387 + \ 30.388 + frac += increment; \ 30.389 + pos += frac>>FRACTIONBITS; \ 30.390 + frac &= FRACTIONMASK; \ 30.391 + OutPos++; \ 30.392 + } \ 30.393 + if(OutPos == SamplesToDo) \ 30.394 + { \ 30.395 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 30.396 + \ 30.397 + value = lpFilter2PC(DryFilter, i, value); \ 30.398 + for(c = 0;c < MAXCHANNELS;c++) \ 30.399 + PendingClicks[c] += value*DrySend[i][c]; \ 30.400 + } \ 30.401 + OutPos -= BufferSize; \ 30.402 + } \ 30.403 + \ 30.404 + for(out = 0;out < Device->NumAuxSends;out++) \ 30.405 + { \ 30.406 + ALeffectslot *Slot = Source->Params.Send[out].Slot; \ 30.407 + ALfloat WetSend; \ 30.408 + ALfloat *WetBuffer; \ 30.409 + ALfloat *WetClickRemoval; \ 30.410 + ALfloat *WetPendingClicks; \ 30.411 + FILTER *WetFilter; \ 30.412 + \ 30.413 + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \ 30.414 + continue; \ 30.415 + \ 30.416 + WetBuffer = Slot->WetBuffer; \ 30.417 + WetClickRemoval = Slot->ClickRemoval; \ 30.418 + WetPendingClicks = Slot->PendingClicks; \ 30.419 + WetFilter = &Source->Params.Send[out].iirFilter; \ 30.420 + WetSend = Source->Params.Send[out].WetGain; \ 30.421 + \ 30.422 + for(i = 0;i < NumChannels;i++) \ 30.423 + { \ 30.424 + pos = 0; \ 30.425 + frac = *DataPosFrac; \ 30.426 + \ 30.427 + if(OutPos == 0) \ 30.428 + { \ 30.429 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 30.430 + \ 30.431 + value = lpFilter1PC(WetFilter, i, value); \ 30.432 + WetClickRemoval[0] -= value * WetSend; \ 30.433 + } \ 30.434 + for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \ 30.435 + { \ 30.436 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 30.437 + \ 30.438 + value = lpFilter1P(WetFilter, i, value); \ 30.439 + WetBuffer[OutPos] += value * WetSend; \ 30.440 + \ 30.441 + frac += increment; \ 30.442 + pos += frac>>FRACTIONBITS; \ 30.443 + frac &= FRACTIONMASK; \ 30.444 + OutPos++; \ 30.445 + } \ 30.446 + if(OutPos == SamplesToDo) \ 30.447 + { \ 30.448 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 30.449 + \ 30.450 + value = lpFilter1PC(WetFilter, i, value); \ 30.451 + WetPendingClicks[0] += value * WetSend; \ 30.452 + } \ 30.453 + OutPos -= BufferSize; \ 30.454 + } \ 30.455 + } \ 30.456 + *DataPosInt += pos; \ 30.457 + *DataPosFrac = frac; \ 30.458 +} 30.459 + 30.460 +DECL_TEMPLATE(ALfloat, point32) 30.461 +DECL_TEMPLATE(ALfloat, lerp32) 30.462 +DECL_TEMPLATE(ALfloat, cubic32) 30.463 + 30.464 +DECL_TEMPLATE(ALshort, point16) 30.465 +DECL_TEMPLATE(ALshort, lerp16) 30.466 +DECL_TEMPLATE(ALshort, cubic16) 30.467 + 30.468 +DECL_TEMPLATE(ALbyte, point8) 30.469 +DECL_TEMPLATE(ALbyte, lerp8) 30.470 +DECL_TEMPLATE(ALbyte, cubic8) 30.471 + 30.472 +#undef DECL_TEMPLATE 30.473 + 30.474 + 30.475 +#define DECL_TEMPLATE(sampler) \ 30.476 +static MixerFunc Select_##sampler(enum FmtType FmtType) \ 30.477 +{ \ 30.478 + switch(FmtType) \ 30.479 + { \ 30.480 + case FmtByte: \ 30.481 + return Mix_ALbyte_##sampler##8; \ 30.482 + case FmtShort: \ 30.483 + return Mix_ALshort_##sampler##16; \ 30.484 + case FmtFloat: \ 30.485 + return Mix_ALfloat_##sampler##32; \ 30.486 + } \ 30.487 + return NULL; \ 30.488 +} 30.489 + 30.490 +DECL_TEMPLATE(point) 30.491 +DECL_TEMPLATE(lerp) 30.492 +DECL_TEMPLATE(cubic) 30.493 + 30.494 +#undef DECL_TEMPLATE 30.495 + 30.496 +MixerFunc SelectMixer(ALbuffer *Buffer, enum Resampler Resampler) 30.497 +{ 30.498 + switch(Resampler) 30.499 + { 30.500 + case POINT_RESAMPLER: 30.501 + return Select_point(Buffer->FmtType); 30.502 + case LINEAR_RESAMPLER: 30.503 + return Select_lerp(Buffer->FmtType); 30.504 + case CUBIC_RESAMPLER: 30.505 + return Select_cubic(Buffer->FmtType); 30.506 + case RESAMPLER_MIN: 30.507 + case RESAMPLER_MAX: 30.508 + break; 30.509 + } 30.510 + return NULL; 30.511 +} 30.512 + 30.513 +#define DECL_TEMPLATE(sampler) \ 30.514 +static MixerFunc Select_Hrtf_##sampler(enum FmtType FmtType) \ 30.515 +{ \ 30.516 + switch(FmtType) \ 30.517 + { \ 30.518 + case FmtByte: \ 30.519 + return Mix_Hrtf_ALbyte_##sampler##8; \ 30.520 + case FmtShort: \ 30.521 + return Mix_Hrtf_ALshort_##sampler##16; \ 30.522 + case FmtFloat: \ 30.523 + return Mix_Hrtf_ALfloat_##sampler##32; \ 30.524 + } \ 30.525 + return NULL; \ 30.526 +} 30.527 + 30.528 +DECL_TEMPLATE(point) 30.529 +DECL_TEMPLATE(lerp) 30.530 +DECL_TEMPLATE(cubic) 30.531 + 30.532 +#undef DECL_TEMPLATE 30.533 + 30.534 +MixerFunc SelectHrtfMixer(ALbuffer *Buffer, enum Resampler Resampler) 30.535 +{ 30.536 + switch(Resampler) 30.537 + { 30.538 + case POINT_RESAMPLER: 30.539 + return Select_Hrtf_point(Buffer->FmtType); 30.540 + case LINEAR_RESAMPLER: 30.541 + return Select_Hrtf_lerp(Buffer->FmtType); 30.542 + case CUBIC_RESAMPLER: 30.543 + return Select_Hrtf_cubic(Buffer->FmtType); 30.544 + case RESAMPLER_MIN: 30.545 + case RESAMPLER_MAX: 30.546 + break; 30.547 + } 30.548 + return NULL; 30.549 +} 30.550 + 30.551 + 30.552 +ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) 30.553 +{ 30.554 + ALbufferlistitem *BufferListItem; 30.555 + ALuint DataPosInt, DataPosFrac; 30.556 + ALuint BuffersPlayed; 30.557 + ALboolean Looping; 30.558 + ALuint increment; 30.559 + enum Resampler Resampler; 30.560 + ALenum State; 30.561 + ALuint OutPos; 30.562 + ALuint FrameSize; 30.563 + ALint64 DataSize64; 30.564 + ALuint i; 30.565 + 30.566 + /* Get source info */ 30.567 + State = Source->state; 30.568 + BuffersPlayed = Source->BuffersPlayed; 30.569 + DataPosInt = Source->position; 30.570 + DataPosFrac = Source->position_fraction; 30.571 + Looping = Source->bLooping; 30.572 + increment = Source->Params.Step; 30.573 + Resampler = Source->Resampler; 30.574 + FrameSize = Source->NumChannels * Source->SampleSize; 30.575 + 30.576 + /* Get current buffer queue item */ 30.577 + BufferListItem = Source->queue; 30.578 + for(i = 0;i < BuffersPlayed;i++) 30.579 + BufferListItem = BufferListItem->next; 30.580 + 30.581 + OutPos = 0; 30.582 + do { 30.583 + const ALuint BufferPrePadding = ResamplerPrePadding[Resampler]; 30.584 + const ALuint BufferPadding = ResamplerPadding[Resampler]; 30.585 + ALubyte StackData[STACK_DATA_SIZE]; 30.586 + ALubyte *SrcData = StackData; 30.587 + ALuint SrcDataSize = 0; 30.588 + ALuint BufferSize; 30.589 + 30.590 + /* Figure out how many buffer bytes will be needed */ 30.591 + DataSize64 = SamplesToDo-OutPos+1; 30.592 + DataSize64 *= increment; 30.593 + DataSize64 += DataPosFrac+FRACTIONMASK; 30.594 + DataSize64 >>= FRACTIONBITS; 30.595 + DataSize64 += BufferPadding+BufferPrePadding; 30.596 + DataSize64 *= FrameSize; 30.597 + 30.598 + BufferSize = ((DataSize64 > STACK_DATA_SIZE) ? STACK_DATA_SIZE : DataSize64); 30.599 + BufferSize -= BufferSize%FrameSize; 30.600 + 30.601 + if(Source->lSourceType == AL_STATIC) 30.602 + { 30.603 + const ALbuffer *ALBuffer = Source->Buffer; 30.604 + const ALubyte *Data = ALBuffer->data; 30.605 + ALuint DataSize; 30.606 + ALuint pos; 30.607 + 30.608 + /* If current pos is beyond the loop range, do not loop */ 30.609 + if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd) 30.610 + { 30.611 + Looping = AL_FALSE; 30.612 + 30.613 + if(DataPosInt >= BufferPrePadding) 30.614 + pos = (DataPosInt-BufferPrePadding)*FrameSize; 30.615 + else 30.616 + { 30.617 + DataSize = (BufferPrePadding-DataPosInt)*FrameSize; 30.618 + DataSize = minu(BufferSize, DataSize); 30.619 + 30.620 + memset(&SrcData[SrcDataSize], 0, DataSize); 30.621 + SrcDataSize += DataSize; 30.622 + BufferSize -= DataSize; 30.623 + 30.624 + pos = 0; 30.625 + } 30.626 + 30.627 + /* Copy what's left to play in the source buffer, and clear the 30.628 + * rest of the temp buffer */ 30.629 + DataSize = ALBuffer->size - pos; 30.630 + DataSize = minu(BufferSize, DataSize); 30.631 + 30.632 + memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize); 30.633 + SrcDataSize += DataSize; 30.634 + BufferSize -= DataSize; 30.635 + 30.636 + memset(&SrcData[SrcDataSize], 0, BufferSize); 30.637 + SrcDataSize += BufferSize; 30.638 + BufferSize -= BufferSize; 30.639 + } 30.640 + else 30.641 + { 30.642 + ALuint LoopStart = ALBuffer->LoopStart; 30.643 + ALuint LoopEnd = ALBuffer->LoopEnd; 30.644 + 30.645 + if(DataPosInt >= LoopStart) 30.646 + { 30.647 + pos = DataPosInt-LoopStart; 30.648 + while(pos < BufferPrePadding) 30.649 + pos += LoopEnd-LoopStart; 30.650 + pos -= BufferPrePadding; 30.651 + pos += LoopStart; 30.652 + pos *= FrameSize; 30.653 + } 30.654 + else if(DataPosInt >= BufferPrePadding) 30.655 + pos = (DataPosInt-BufferPrePadding)*FrameSize; 30.656 + else 30.657 + { 30.658 + DataSize = (BufferPrePadding-DataPosInt)*FrameSize; 30.659 + DataSize = minu(BufferSize, DataSize); 30.660 + 30.661 + memset(&SrcData[SrcDataSize], 0, DataSize); 30.662 + SrcDataSize += DataSize; 30.663 + BufferSize -= DataSize; 30.664 + 30.665 + pos = 0; 30.666 + } 30.667 + 30.668 + /* Copy what's left of this loop iteration, then copy repeats 30.669 + * of the loop section */ 30.670 + DataSize = LoopEnd*FrameSize - pos; 30.671 + DataSize = minu(BufferSize, DataSize); 30.672 + 30.673 + memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize); 30.674 + SrcDataSize += DataSize; 30.675 + BufferSize -= DataSize; 30.676 + 30.677 + DataSize = (LoopEnd-LoopStart) * FrameSize; 30.678 + while(BufferSize > 0) 30.679 + { 30.680 + DataSize = minu(BufferSize, DataSize); 30.681 + 30.682 + memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize); 30.683 + SrcDataSize += DataSize; 30.684 + BufferSize -= DataSize; 30.685 + } 30.686 + } 30.687 + } 30.688 + else 30.689 + { 30.690 + /* Crawl the buffer queue to fill in the temp buffer */ 30.691 + ALbufferlistitem *BufferListIter = BufferListItem; 30.692 + ALuint pos; 30.693 + 30.694 + if(DataPosInt >= BufferPrePadding) 30.695 + pos = (DataPosInt-BufferPrePadding)*FrameSize; 30.696 + else 30.697 + { 30.698 + pos = (BufferPrePadding-DataPosInt)*FrameSize; 30.699 + while(pos > 0) 30.700 + { 30.701 + if(!BufferListIter->prev && !Looping) 30.702 + { 30.703 + ALuint DataSize = minu(BufferSize, pos); 30.704 + 30.705 + memset(&SrcData[SrcDataSize], 0, DataSize); 30.706 + SrcDataSize += DataSize; 30.707 + BufferSize -= DataSize; 30.708 + 30.709 + pos = 0; 30.710 + break; 30.711 + } 30.712 + 30.713 + if(BufferListIter->prev) 30.714 + BufferListIter = BufferListIter->prev; 30.715 + else 30.716 + { 30.717 + while(BufferListIter->next) 30.718 + BufferListIter = BufferListIter->next; 30.719 + } 30.720 + 30.721 + if(BufferListIter->buffer) 30.722 + { 30.723 + if((ALuint)BufferListIter->buffer->size > pos) 30.724 + { 30.725 + pos = BufferListIter->buffer->size - pos; 30.726 + break; 30.727 + } 30.728 + pos -= BufferListIter->buffer->size; 30.729 + } 30.730 + } 30.731 + } 30.732 + 30.733 + while(BufferListIter && BufferSize > 0) 30.734 + { 30.735 + const ALbuffer *ALBuffer; 30.736 + if((ALBuffer=BufferListIter->buffer) != NULL) 30.737 + { 30.738 + const ALubyte *Data = ALBuffer->data; 30.739 + ALuint DataSize = ALBuffer->size; 30.740 + 30.741 + /* Skip the data already played */ 30.742 + if(DataSize <= pos) 30.743 + pos -= DataSize; 30.744 + else 30.745 + { 30.746 + Data += pos; 30.747 + DataSize -= pos; 30.748 + pos -= pos; 30.749 + 30.750 + DataSize = minu(BufferSize, DataSize); 30.751 + memcpy(&SrcData[SrcDataSize], Data, DataSize); 30.752 + SrcDataSize += DataSize; 30.753 + BufferSize -= DataSize; 30.754 + } 30.755 + } 30.756 + BufferListIter = BufferListIter->next; 30.757 + if(!BufferListIter && Looping) 30.758 + BufferListIter = Source->queue; 30.759 + else if(!BufferListIter) 30.760 + { 30.761 + memset(&SrcData[SrcDataSize], 0, BufferSize); 30.762 + SrcDataSize += BufferSize; 30.763 + BufferSize -= BufferSize; 30.764 + } 30.765 + } 30.766 + } 30.767 + 30.768 + /* Figure out how many samples we can mix. */ 30.769 + DataSize64 = SrcDataSize / FrameSize; 30.770 + DataSize64 -= BufferPadding+BufferPrePadding; 30.771 + DataSize64 <<= FRACTIONBITS; 30.772 + DataSize64 -= increment; 30.773 + DataSize64 -= DataPosFrac; 30.774 + 30.775 + BufferSize = (ALuint)((DataSize64+(increment-1)) / increment); 30.776 + BufferSize = minu(BufferSize, (SamplesToDo-OutPos)); 30.777 + 30.778 + SrcData += BufferPrePadding*FrameSize; 30.779 + Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac, 30.780 + OutPos, SamplesToDo, BufferSize); 30.781 + OutPos += BufferSize; 30.782 + 30.783 + /* Handle looping sources */ 30.784 + while(1) 30.785 + { 30.786 + const ALbuffer *ALBuffer; 30.787 + ALuint DataSize = 0; 30.788 + ALuint LoopStart = 0; 30.789 + ALuint LoopEnd = 0; 30.790 + 30.791 + if((ALBuffer=BufferListItem->buffer) != NULL) 30.792 + { 30.793 + DataSize = ALBuffer->size / FrameSize; 30.794 + LoopStart = ALBuffer->LoopStart; 30.795 + LoopEnd = ALBuffer->LoopEnd; 30.796 + if(LoopEnd > DataPosInt) 30.797 + break; 30.798 + } 30.799 + 30.800 + if(Looping && Source->lSourceType == AL_STATIC) 30.801 + { 30.802 + BufferListItem = Source->queue; 30.803 + DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart; 30.804 + break; 30.805 + } 30.806 + 30.807 + if(DataSize > DataPosInt) 30.808 + break; 30.809 + 30.810 + if(BufferListItem->next) 30.811 + { 30.812 + BufferListItem = BufferListItem->next; 30.813 + BuffersPlayed++; 30.814 + } 30.815 + else if(Looping) 30.816 + { 30.817 + BufferListItem = Source->queue; 30.818 + BuffersPlayed = 0; 30.819 + } 30.820 + else 30.821 + { 30.822 + State = AL_STOPPED; 30.823 + BufferListItem = Source->queue; 30.824 + BuffersPlayed = Source->BuffersInQueue; 30.825 + DataPosInt = 0; 30.826 + DataPosFrac = 0; 30.827 + break; 30.828 + } 30.829 + 30.830 + DataPosInt -= DataSize; 30.831 + } 30.832 + } while(State == AL_PLAYING && OutPos < SamplesToDo); 30.833 + 30.834 + /* Update source info */ 30.835 + Source->state = State; 30.836 + Source->BuffersPlayed = BuffersPlayed; 30.837 + Source->position = DataPosInt; 30.838 + Source->position_fraction = DataPosFrac; 30.839 + Source->Buffer = BufferListItem->buffer; 30.840 + Source->HrtfOffset += OutPos; 30.841 + if(State == AL_PLAYING) 30.842 + { 30.843 + Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos; 30.844 + Source->HrtfMoving = AL_TRUE; 30.845 + } 30.846 + else 30.847 + { 30.848 + Source->HrtfCounter = 0; 30.849 + Source->HrtfMoving = AL_FALSE; 30.850 + } 30.851 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 31.2 +++ b/Alc/panning.c Tue Oct 25 13:02:31 2011 -0700 31.3 @@ -0,0 +1,313 @@ 31.4 +/** 31.5 + * OpenAL cross platform audio library 31.6 + * Copyright (C) 1999-2010 by authors. 31.7 + * This library is free software; you can redistribute it and/or 31.8 + * modify it under the terms of the GNU Library General Public 31.9 + * License as published by the Free Software Foundation; either 31.10 + * version 2 of the License, or (at your option) any later version. 31.11 + * 31.12 + * This library is distributed in the hope that it will be useful, 31.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 31.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 31.15 + * Library General Public License for more details. 31.16 + * 31.17 + * You should have received a copy of the GNU Library General Public 31.18 + * License along with this library; if not, write to the 31.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 31.20 + * Boston, MA 02111-1307, USA. 31.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 31.22 + */ 31.23 + 31.24 +#include "config.h" 31.25 + 31.26 +#include <math.h> 31.27 +#include <stdlib.h> 31.28 +#include <string.h> 31.29 +#include <ctype.h> 31.30 +#include <assert.h> 31.31 + 31.32 +#include "alMain.h" 31.33 +#include "AL/al.h" 31.34 +#include "AL/alc.h" 31.35 +#include "alu.h" 31.36 + 31.37 +static void SetSpeakerArrangement(const char *name, ALfloat SpeakerAngle[MAXCHANNELS], 31.38 + enum Channel Speaker2Chan[MAXCHANNELS], ALint chans) 31.39 +{ 31.40 + char layout_str[256]; 31.41 + char *confkey, *next; 31.42 + char *sep, *end; 31.43 + enum Channel val; 31.44 + int i; 31.45 + 31.46 + if(!ConfigValueExists(NULL, name)) 31.47 + name = "layout"; 31.48 + 31.49 + strncpy(layout_str, GetConfigValue(NULL, name, ""), sizeof(layout_str)); 31.50 + layout_str[sizeof(layout_str)-1] = 0; 31.51 + 31.52 + if(!layout_str[0]) 31.53 + return; 31.54 + 31.55 + next = confkey = layout_str; 31.56 + while(next && *next) 31.57 + { 31.58 + confkey = next; 31.59 + next = strchr(confkey, ','); 31.60 + if(next) 31.61 + { 31.62 + *next = 0; 31.63 + do { 31.64 + next++; 31.65 + } while(isspace(*next) || *next == ','); 31.66 + } 31.67 + 31.68 + sep = strchr(confkey, '='); 31.69 + if(!sep || confkey == sep) 31.70 + continue; 31.71 + 31.72 + end = sep - 1; 31.73 + while(isspace(*end) && end != confkey) 31.74 + end--; 31.75 + *(++end) = 0; 31.76 + 31.77 + if(strcmp(confkey, "fl") == 0 || strcmp(confkey, "front-left") == 0) 31.78 + val = FRONT_LEFT; 31.79 + else if(strcmp(confkey, "fr") == 0 || strcmp(confkey, "front-right") == 0) 31.80 + val = FRONT_RIGHT; 31.81 + else if(strcmp(confkey, "fc") == 0 || strcmp(confkey, "front-center") == 0) 31.82 + val = FRONT_CENTER; 31.83 + else if(strcmp(confkey, "bl") == 0 || strcmp(confkey, "back-left") == 0) 31.84 + val = BACK_LEFT; 31.85 + else if(strcmp(confkey, "br") == 0 || strcmp(confkey, "back-right") == 0) 31.86 + val = BACK_RIGHT; 31.87 + else if(strcmp(confkey, "bc") == 0 || strcmp(confkey, "back-center") == 0) 31.88 + val = BACK_CENTER; 31.89 + else if(strcmp(confkey, "sl") == 0 || strcmp(confkey, "side-left") == 0) 31.90 + val = SIDE_LEFT; 31.91 + else if(strcmp(confkey, "sr") == 0 || strcmp(confkey, "side-right") == 0) 31.92 + val = SIDE_RIGHT; 31.93 + else 31.94 + { 31.95 + ERR("Unknown speaker for %s: \"%s\"\n", name, confkey); 31.96 + continue; 31.97 + } 31.98 + 31.99 + *(sep++) = 0; 31.100 + while(isspace(*sep)) 31.101 + sep++; 31.102 + 31.103 + for(i = 0;i < chans;i++) 31.104 + { 31.105 + if(Speaker2Chan[i] == val) 31.106 + { 31.107 + long angle = strtol(sep, NULL, 10); 31.108 + if(angle >= -180 && angle <= 180) 31.109 + SpeakerAngle[i] = angle * M_PI/180.0f; 31.110 + else 31.111 + ERR("Invalid angle for speaker \"%s\": %ld\n", confkey, angle); 31.112 + break; 31.113 + } 31.114 + } 31.115 + } 31.116 + 31.117 + for(i = 0;i < chans;i++) 31.118 + { 31.119 + int min = i; 31.120 + int i2; 31.121 + 31.122 + for(i2 = i+1;i2 < chans;i2++) 31.123 + { 31.124 + if(SpeakerAngle[i2] < SpeakerAngle[min]) 31.125 + min = i2; 31.126 + } 31.127 + 31.128 + if(min != i) 31.129 + { 31.130 + ALfloat tmpf; 31.131 + enum Channel tmpc; 31.132 + 31.133 + tmpf = SpeakerAngle[i]; 31.134 + SpeakerAngle[i] = SpeakerAngle[min]; 31.135 + SpeakerAngle[min] = tmpf; 31.136 + 31.137 + tmpc = Speaker2Chan[i]; 31.138 + Speaker2Chan[i] = Speaker2Chan[min]; 31.139 + Speaker2Chan[min] = tmpc; 31.140 + } 31.141 + } 31.142 +} 31.143 + 31.144 +static ALfloat aluLUTpos2Angle(ALint pos) 31.145 +{ 31.146 + if(pos < QUADRANT_NUM) 31.147 + return aluAtan((ALfloat)pos / (ALfloat)(QUADRANT_NUM - pos)); 31.148 + if(pos < 2 * QUADRANT_NUM) 31.149 + return M_PI_2 + aluAtan((ALfloat)(pos - QUADRANT_NUM) / (ALfloat)(2 * QUADRANT_NUM - pos)); 31.150 + if(pos < 3 * QUADRANT_NUM) 31.151 + return aluAtan((ALfloat)(pos - 2 * QUADRANT_NUM) / (ALfloat)(3 * QUADRANT_NUM - pos)) - M_PI; 31.152 + return aluAtan((ALfloat)(pos - 3 * QUADRANT_NUM) / (ALfloat)(4 * QUADRANT_NUM - pos)) - M_PI_2; 31.153 +} 31.154 + 31.155 +ALint aluCart2LUTpos(ALfloat re, ALfloat im) 31.156 +{ 31.157 + ALint pos = 0; 31.158 + ALfloat denom = aluFabs(re) + aluFabs(im); 31.159 + if(denom > 0.0f) 31.160 + pos = (ALint)(QUADRANT_NUM*aluFabs(im) / denom + 0.5); 31.161 + 31.162 + if(re < 0.0) 31.163 + pos = 2 * QUADRANT_NUM - pos; 31.164 + if(im < 0.0) 31.165 + pos = LUT_NUM - pos; 31.166 + return pos%LUT_NUM; 31.167 +} 31.168 + 31.169 +ALvoid aluInitPanning(ALCdevice *Device) 31.170 +{ 31.171 + ALfloat SpeakerAngle[MAXCHANNELS]; 31.172 + enum Channel *Speaker2Chan; 31.173 + ALfloat Alpha, Theta; 31.174 + ALint pos; 31.175 + ALuint s; 31.176 + 31.177 + Speaker2Chan = Device->Speaker2Chan; 31.178 + switch(Device->FmtChans) 31.179 + { 31.180 + case DevFmtMono: 31.181 + Device->NumChan = 1; 31.182 + Speaker2Chan[0] = FRONT_CENTER; 31.183 + SpeakerAngle[0] = 0.0f * M_PI/180.0f; 31.184 + break; 31.185 + 31.186 + case DevFmtStereo: 31.187 + Device->NumChan = 2; 31.188 + Speaker2Chan[0] = FRONT_LEFT; 31.189 + Speaker2Chan[1] = FRONT_RIGHT; 31.190 + SpeakerAngle[0] = -90.0f * M_PI/180.0f; 31.191 + SpeakerAngle[1] = 90.0f * M_PI/180.0f; 31.192 + SetSpeakerArrangement("layout_STEREO", SpeakerAngle, Speaker2Chan, Device->NumChan); 31.193 + break; 31.194 + 31.195 + case DevFmtQuad: 31.196 + Device->NumChan = 4; 31.197 + Speaker2Chan[0] = BACK_LEFT; 31.198 + Speaker2Chan[1] = FRONT_LEFT; 31.199 + Speaker2Chan[2] = FRONT_RIGHT; 31.200 + Speaker2Chan[3] = BACK_RIGHT; 31.201 + SpeakerAngle[0] = -135.0f * M_PI/180.0f; 31.202 + SpeakerAngle[1] = -45.0f * M_PI/180.0f; 31.203 + SpeakerAngle[2] = 45.0f * M_PI/180.0f; 31.204 + SpeakerAngle[3] = 135.0f * M_PI/180.0f; 31.205 + SetSpeakerArrangement("layout_QUAD", SpeakerAngle, Speaker2Chan, Device->NumChan); 31.206 + break; 31.207 + 31.208 + case DevFmtX51: 31.209 + Device->NumChan = 5; 31.210 + Speaker2Chan[0] = BACK_LEFT; 31.211 + Speaker2Chan[1] = FRONT_LEFT; 31.212 + Speaker2Chan[2] = FRONT_CENTER; 31.213 + Speaker2Chan[3] = FRONT_RIGHT; 31.214 + Speaker2Chan[4] = BACK_RIGHT; 31.215 + SpeakerAngle[0] = -110.0f * M_PI/180.0f; 31.216 + SpeakerAngle[1] = -30.0f * M_PI/180.0f; 31.217 + SpeakerAngle[2] = 0.0f * M_PI/180.0f; 31.218 + SpeakerAngle[3] = 30.0f * M_PI/180.0f; 31.219 + SpeakerAngle[4] = 110.0f * M_PI/180.0f; 31.220 + SetSpeakerArrangement("layout_51CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); 31.221 + break; 31.222 + 31.223 + case DevFmtX51Side: 31.224 + Device->NumChan = 5; 31.225 + Speaker2Chan[0] = SIDE_LEFT; 31.226 + Speaker2Chan[1] = FRONT_LEFT; 31.227 + Speaker2Chan[2] = FRONT_CENTER; 31.228 + Speaker2Chan[3] = FRONT_RIGHT; 31.229 + Speaker2Chan[4] = SIDE_RIGHT; 31.230 + SpeakerAngle[0] = -90.0f * M_PI/180.0f; 31.231 + SpeakerAngle[1] = -30.0f * M_PI/180.0f; 31.232 + SpeakerAngle[2] = 0.0f * M_PI/180.0f; 31.233 + SpeakerAngle[3] = 30.0f * M_PI/180.0f; 31.234 + SpeakerAngle[4] = 90.0f * M_PI/180.0f; 31.235 + SetSpeakerArrangement("layout_51SIDECHN", SpeakerAngle, Speaker2Chan, Device->NumChan); 31.236 + break; 31.237 + 31.238 + case DevFmtX61: 31.239 + Device->NumChan = 6; 31.240 + Speaker2Chan[0] = SIDE_LEFT; 31.241 + Speaker2Chan[1] = FRONT_LEFT; 31.242 + Speaker2Chan[2] = FRONT_CENTER; 31.243 + Speaker2Chan[3] = FRONT_RIGHT; 31.244 + Speaker2Chan[4] = SIDE_RIGHT; 31.245 + Speaker2Chan[5] = BACK_CENTER; 31.246 + SpeakerAngle[0] = -90.0f * M_PI/180.0f; 31.247 + SpeakerAngle[1] = -30.0f * M_PI/180.0f; 31.248 + SpeakerAngle[2] = 0.0f * M_PI/180.0f; 31.249 + SpeakerAngle[3] = 30.0f * M_PI/180.0f; 31.250 + SpeakerAngle[4] = 90.0f * M_PI/180.0f; 31.251 + SpeakerAngle[5] = 180.0f * M_PI/180.0f; 31.252 + SetSpeakerArrangement("layout_61CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); 31.253 + break; 31.254 + 31.255 + case DevFmtX71: 31.256 + Device->NumChan = 7; 31.257 + Speaker2Chan[0] = BACK_LEFT; 31.258 + Speaker2Chan[1] = SIDE_LEFT; 31.259 + Speaker2Chan[2] = FRONT_LEFT; 31.260 + Speaker2Chan[3] = FRONT_CENTER; 31.261 + Speaker2Chan[4] = FRONT_RIGHT; 31.262 + Speaker2Chan[5] = SIDE_RIGHT; 31.263 + Speaker2Chan[6] = BACK_RIGHT; 31.264 + SpeakerAngle[0] = -150.0f * M_PI/180.0f; 31.265 + SpeakerAngle[1] = -90.0f * M_PI/180.0f; 31.266 + SpeakerAngle[2] = -30.0f * M_PI/180.0f; 31.267 + SpeakerAngle[3] = 0.0f * M_PI/180.0f; 31.268 + SpeakerAngle[4] = 30.0f * M_PI/180.0f; 31.269 + SpeakerAngle[5] = 90.0f * M_PI/180.0f; 31.270 + SpeakerAngle[6] = 150.0f * M_PI/180.0f; 31.271 + SetSpeakerArrangement("layout_71CHN", SpeakerAngle, Speaker2Chan, Device->NumChan); 31.272 + break; 31.273 + } 31.274 + 31.275 + for(pos = 0; pos < LUT_NUM; pos++) 31.276 + { 31.277 + ALfloat *PanningLUT = Device->PanningLUT[pos]; 31.278 + 31.279 + /* clear all values */ 31.280 + for(s = 0; s < MAXCHANNELS; s++) 31.281 + PanningLUT[s] = 0.0f; 31.282 + 31.283 + if(Device->NumChan == 1) 31.284 + { 31.285 + PanningLUT[Speaker2Chan[0]] = 1.0f; 31.286 + continue; 31.287 + } 31.288 + 31.289 + /* source angle */ 31.290 + Theta = aluLUTpos2Angle(pos); 31.291 + 31.292 + /* set panning values */ 31.293 + for(s = 0; s < Device->NumChan - 1; s++) 31.294 + { 31.295 + if(Theta >= SpeakerAngle[s] && Theta < SpeakerAngle[s+1]) 31.296 + { 31.297 + /* source between speaker s and speaker s+1 */ 31.298 + Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / 31.299 + (SpeakerAngle[s+1]-SpeakerAngle[s]); 31.300 + PanningLUT[Speaker2Chan[s]] = cos(Alpha); 31.301 + PanningLUT[Speaker2Chan[s+1]] = sin(Alpha); 31.302 + break; 31.303 + } 31.304 + } 31.305 + if(s == Device->NumChan - 1) 31.306 + { 31.307 + /* source between last and first speaker */ 31.308 + if(Theta < SpeakerAngle[0]) 31.309 + Theta += 2.0f * M_PI; 31.310 + Alpha = M_PI_2 * (Theta-SpeakerAngle[s]) / 31.311 + (2.0f * M_PI + SpeakerAngle[0]-SpeakerAngle[s]); 31.312 + PanningLUT[Speaker2Chan[s]] = cos(Alpha); 31.313 + PanningLUT[Speaker2Chan[0]] = sin(Alpha); 31.314 + } 31.315 + } 31.316 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 32.2 +++ b/Alc/utils.c Tue Oct 25 13:02:31 2011 -0700 32.3 @@ -0,0 +1,123 @@ 32.4 +void pauseAllSources(ALCcontext *ctx){ 32.5 + ALCcontext *current = alcGetCurrentContext(); 32.6 + alcMakeContextCurrent(ctx); 32.7 + ALsource **src, **src_end; 32.8 + src = ctx->ActiveSources; 32.9 + src_end = src + ctx->ActiveSourceCount; 32.10 + while(src != src_end){ 32.11 + if (AL_PLAYING == (*src)->state){ 32.12 + //if (AL_TRUE){ 32.13 + ALuint source_id = (*src)->source; 32.14 + //printf("pausing ONE source\n"); 32.15 + alSourcePause(source_id); 32.16 + } 32.17 + src++; 32.18 + } 32.19 + alcMakeContextCurrent(current); 32.20 +} 32.21 + 32.22 + 32.23 +#define RUNONLY(n) \ 32.24 + {static int __runonce = n; \ 32.25 + if (__runonce-- <= 0){__runonce = 0;return;}} 32.26 + 32.27 +#define RUNAT(n) \ 32.28 + {static int __runat = n; \ 32.29 + if (0 != __runat--){return;}} 32.30 + 32.31 + 32.32 +#define DsyncSourcei(sourceID1, sourceID2, ctx1, ctx2, param) \ 32.33 + {/*printf("synci : " #param "\n");*/ \ 32.34 + syncSourcei(sourceID1, sourceID2, ctx1, ctx2, param);} 32.35 + 32.36 +#define DsyncSourcef(sourceID1, sourceID2, ctx1, ctx2, param) \ 32.37 + {/*printf("syncf : " #param "\n");*/ \ 32.38 + syncSourcef(sourceID1, sourceID2, ctx1, ctx2, param);} 32.39 + 32.40 +#define DsyncSource3i(sourceID1, sourceID2, ctx1, ctx2, param) \ 32.41 + {/*printf("sync3i : " #param "\n");*/ \ 32.42 + syncSource3i(sourceID1, sourceID2, ctx1, ctx2, param);} 32.43 + 32.44 +#define DsyncSource3f(sourceID1, sourceID2, ctx1, ctx2, param) \ 32.45 + {/*printf("sync3f : " #param "\n");*/ \ 32.46 + syncSource3f(sourceID1, sourceID2, ctx1, ctx2, param);} 32.47 + 32.48 +void printError(void){ 32.49 + ALenum error = alGetError(); 32.50 + printf("%s\n", GetALCErrorString(error)); 32.51 + printf("%s\n", GetALErrorString(error)); 32.52 +} 32.53 + 32.54 + 32.55 + 32.56 +char* GetALCErrorString(ALenum err) 32.57 +{ 32.58 + switch(err) 32.59 + { 32.60 + case ALC_NO_ERROR: 32.61 + return "AL_NO_ERROR"; 32.62 + break; 32.63 + 32.64 + case ALC_INVALID_DEVICE: 32.65 + return "ALC_INVALID_DEVICE"; 32.66 + break; 32.67 + 32.68 + case ALC_INVALID_CONTEXT: 32.69 + return "ALC_INVALID_CONTEXT"; 32.70 + break; 32.71 + 32.72 + case ALC_INVALID_ENUM: 32.73 + return "ALC_INVALID_ENUM"; 32.74 + break; 32.75 + 32.76 + case ALC_INVALID_VALUE: 32.77 + return "ALC_INVALID_VALUE"; 32.78 + break; 32.79 + 32.80 + case ALC_OUT_OF_MEMORY: 32.81 + return "ALC_OUT_OF_MEMORY"; 32.82 + break; 32.83 + }; 32.84 + return "UNknown error."; 32.85 +} 32.86 + 32.87 + 32.88 + 32.89 + 32.90 + 32.91 + 32.92 + 32.93 +char* GetALErrorString(ALenum err) 32.94 +{ 32.95 + switch(err) 32.96 + { 32.97 + case AL_NO_ERROR: 32.98 + return "AL_NO_ERROR"; 32.99 + break; 32.100 + 32.101 + case AL_INVALID_NAME: 32.102 + return "AL_INVALID_NAME"; 32.103 + break; 32.104 + 32.105 + case AL_INVALID_ENUM: 32.106 + return "AL_INVALID_ENUM"; 32.107 + break; 32.108 + 32.109 + case AL_INVALID_VALUE: 32.110 + return "AL_INVALID_VALUE"; 32.111 + break; 32.112 + 32.113 + case AL_INVALID_OPERATION: 32.114 + return "AL_INVALID_OPERATION"; 32.115 + break; 32.116 + 32.117 + case AL_OUT_OF_MEMORY: 32.118 + return "AL_OUT_OF_MEMORY"; 32.119 + break; 32.120 + }; 32.121 + return "UNknown error."; 32.122 +} 32.123 + 32.124 + 32.125 + 32.126 +
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 33.2 +++ b/CMakeLists-works.txt Tue Oct 25 13:02:31 2011 -0700 33.3 @@ -0,0 +1,431 @@ 33.4 +# CMake build file list for OpenAL 33.5 + 33.6 +CMAKE_MINIMUM_REQUIRED(VERSION 2.4) 33.7 + 33.8 +IF(COMMAND CMAKE_POLICY) 33.9 + CMAKE_POLICY(SET CMP0003 NEW) 33.10 +ENDIF(COMMAND CMAKE_POLICY) 33.11 + 33.12 +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 33.13 + 33.14 +INCLUDE(CheckFunctionExists) 33.15 +INCLUDE(CheckLibraryExists) 33.16 +INCLUDE(CheckSharedFunctionExists) 33.17 +INCLUDE(CheckIncludeFile) 33.18 +INCLUDE(CheckIncludeFiles) 33.19 +INCLUDE(CheckSymbolExists) 33.20 +INCLUDE(CheckCCompilerFlag) 33.21 +INCLUDE(CheckCSourceCompiles) 33.22 +INCLUDE(CheckTypeSize) 33.23 + 33.24 + 33.25 +PROJECT(OpenAL C) 33.26 + 33.27 + 33.28 +SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) 33.29 + 33.30 + 33.31 +OPTION(ALSA "Check for ALSA backend" ON) 33.32 +OPTION(OSS "Check for OSS backend" ON) 33.33 +OPTION(SOLARIS "Check for Solaris backend" ON) 33.34 +OPTION(SNDIO "Check for SndIO backend" ON) 33.35 +OPTION(MMDEVAPI "Check for MMDevApi" ON) 33.36 +OPTION(DSOUND "Check for DirectSound backend" ON) 33.37 +OPTION(WINMM "Check for Windows Multimedia backend" ON) 33.38 +OPTION(PORTAUDIO "Check for PortAudio backend" ON) 33.39 +OPTION(PULSEAUDIO "Check for PulseAudio backend" ON) 33.40 +OPTION(COREAUDIO "Check for CoreAudio backend" ON) 33.41 +OPTION(OPENSL "Check for OpenSL backend" ON) 33.42 +OPTION(WAVE "Enable Wave Writer backend" ON) 33.43 +OPTION(RECORD "Enable Recorder Backend" ON) 33.44 + 33.45 +OPTION(REQUIRE_ALSA "Require ALSA backend" OFF) 33.46 +OPTION(REQUIRE_OSS "Require OSS backend" OFF) 33.47 +OPTION(REQUIRE_SOLARIS "Require Solaris backend" OFF) 33.48 +OPTION(REQUIRE_SNDIO "Require SndIO backend" OFF) 33.49 +OPTION(REQUIRE_MMDEVAPI "Require MMDevApi" OFF) 33.50 +OPTION(REQUIRE_DSOUND "Require DirectSound backend" OFF) 33.51 +OPTION(REQUIRE_WINMM "Require Windows Multimedia backend" OFF) 33.52 +OPTION(REQUIRE_PORTAUDIO "Require PortAudio backend" OFF) 33.53 +OPTION(REQUIRE_PULSEAUDIO "Require PulseAudio backend" OFF) 33.54 +OPTION(REQUIRE_COREAUDIO "Require CoreAudio backend" OFF) 33.55 +OPTION(REQUIRE_OPENSL "Require OpenSL backend" OFF) 33.56 + 33.57 +OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON) 33.58 + 33.59 +OPTION(WERROR "Treat compile warnings as errors" OFF) 33.60 + 33.61 +OPTION(UTILS "Build and install utility programs" ON) 33.62 + 33.63 +OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF) 33.64 + 33.65 + 33.66 +SET(LIBNAME openal) 33.67 + 33.68 +SET(LIBTYPE SHARED) 33.69 + 33.70 +SET(LIB_MAJOR_VERSION "1") 33.71 +SET(LIB_MINOR_VERSION "13") 33.72 +SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}") 33.73 + 33.74 +SET(EXPORT_DECL "") 33.75 + 33.76 + 33.77 +# Add definitions, compiler switches, etc. 33.78 +INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}") 33.79 + 33.80 +ADD_DEFINITIONS(-Winline -Wall) 33.81 +CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA) 33.82 +IF(HAVE_W_EXTRA) 33.83 + ADD_DEFINITIONS(-Wextra) 33.84 +ENDIF() 33.85 + 33.86 +IF(WERROR) 33.87 + ADD_DEFINITIONS(-Werror) 33.88 +ENDIF() 33.89 + 33.90 +SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -D_DEBUG" CACHE STRING 33.91 + "Flags used by the compiler during Release with Debug Info builds." 33.92 + FORCE) 33.93 +SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING 33.94 + "Flags used by the compiler during release minsize builds." 33.95 + FORCE) 33.96 +SET(CMAKE_C_FLAGS_RELEASE "-O2 -fomit-frame-pointer -DNDEBUG" CACHE STRING 33.97 + "Flags used by the compiler during release builds" 33.98 + FORCE) 33.99 +SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING 33.100 + "Flags used by the compiler during debug builds." 33.101 + FORCE) 33.102 + 33.103 +CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H) 33.104 +CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H) 33.105 +CHECK_INCLUDE_FILE(ieeefp.h HAVE_IEEEFP_H) 33.106 +CHECK_INCLUDE_FILE(guiddef.h HAVE_GUIDDEF_H) 33.107 +IF(NOT HAVE_GUIDDEF_H) 33.108 + CHECK_INCLUDE_FILE(initguid.h HAVE_INITGUID_H) 33.109 +ENDIF() 33.110 +CHECK_INCLUDE_FILE(arm_neon.h HAVE_ARM_NEON_H) 33.111 + 33.112 +CHECK_LIBRARY_EXISTS(m powf "" HAVE_POWF) 33.113 +CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF) 33.114 +CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF) 33.115 +CHECK_LIBRARY_EXISTS(m atanf "" HAVE_ATANF) 33.116 +CHECK_LIBRARY_EXISTS(m fabsf "" HAVE_FABSF) 33.117 +IF(HAVE_FENV_H) 33.118 + CHECK_LIBRARY_EXISTS(m fesetround "" HAVE_FESETROUND) 33.119 +ENDIF() 33.120 +IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND) 33.121 + SET(EXTRA_LIBS m ${EXTRA_LIBS}) 33.122 +ENDIF() 33.123 +CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) 33.124 +CHECK_FUNCTION_EXISTS(_controlfp HAVE__CONTROLFP) 33.125 + 33.126 +CHECK_FUNCTION_EXISTS(stat HAVE_STAT) 33.127 +CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP) 33.128 +IF(NOT HAVE_STRCASECMP) 33.129 + CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP) 33.130 + IF(NOT HAVE__STRICMP) 33.131 + MESSAGE(FATAL_ERROR "No case-insensitive compare function found, please report!") 33.132 + ENDIF() 33.133 + 33.134 + ADD_DEFINITIONS(-Dstrcasecmp=_stricmp) 33.135 +ENDIF() 33.136 + 33.137 +CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP) 33.138 +IF(NOT HAVE_STRNCASECMP) 33.139 + CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP) 33.140 + IF(NOT HAVE__STRNICMP) 33.141 + MESSAGE(FATAL_ERROR "No case-insensitive size-limitted compare function found, please report!") 33.142 + ENDIF() 33.143 + 33.144 + ADD_DEFINITIONS(-Dstrncasecmp=_strnicmp) 33.145 +ENDIF() 33.146 + 33.147 +CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF) 33.148 +IF(NOT HAVE_SNPRINTF) 33.149 + CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF) 33.150 + IF(NOT HAVE__SNPRINTF) 33.151 + MESSAGE(FATAL_ERROR "No snprintf function found, please report!") 33.152 + ENDIF() 33.153 + 33.154 + ADD_DEFINITIONS(-Dsnprintf=_snprintf) 33.155 +ENDIF() 33.156 + 33.157 +CHECK_FUNCTION_EXISTS(vsnprintf HAVE_VSNPRINTF) 33.158 +IF(NOT HAVE_VSNPRINTF) 33.159 + CHECK_FUNCTION_EXISTS(_vsnprintf HAVE__VSNPRINTF) 33.160 + IF(NOT HAVE__VSNPRINTF) 33.161 + MESSAGE(FATAL_ERROR "No vsnprintf function found, please report!") 33.162 + ENDIF() 33.163 + 33.164 + ADD_DEFINITIONS(-Dvsnprintf=_vsnprintf) 33.165 +ENDIF() 33.166 + 33.167 +CHECK_SYMBOL_EXISTS(isfinite math.h HAVE_ISFINITE) 33.168 +IF(NOT HAVE_ISFINITE) 33.169 + CHECK_FUNCTION_EXISTS(finite HAVE_FINITE) 33.170 + IF(NOT HAVE_FINITE) 33.171 + CHECK_FUNCTION_EXISTS(_finite HAVE__FINITE) 33.172 + IF(NOT HAVE__FINITE) 33.173 + MESSAGE(FATAL_ERROR "No isfinite function found, please report!") 33.174 + ENDIF() 33.175 + ADD_DEFINITIONS(-Disfinite=_finite) 33.176 + ELSE() 33.177 + ADD_DEFINITIONS(-Disfinite=finite) 33.178 + ENDIF() 33.179 +ENDIF() 33.180 + 33.181 +CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN) 33.182 +IF(NOT HAVE_ISNAN) 33.183 + CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN) 33.184 + IF(NOT HAVE__ISNAN) 33.185 + MESSAGE(FATAL_ERROR "No isnan function found, please report!") 33.186 + ENDIF() 33.187 + 33.188 + ADD_DEFINITIONS(-Disnan=_isnan) 33.189 +ENDIF() 33.190 + 33.191 + 33.192 +# Check for the dlopen API (for dynamicly loading backend libs) 33.193 +IF(DLOPEN) 33.194 + CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H) 33.195 + IF(HAVE_DLFCN_H) 33.196 + CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL) 33.197 + IF(HAVE_LIBDL) 33.198 + SET(EXTRA_LIBS dl ${EXTRA_LIBS}) 33.199 + ENDIF() 33.200 + ENDIF() 33.201 +ENDIF() 33.202 + 33.203 +# Check if we have Windows headers 33.204 +CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500) 33.205 +IF(NOT HAVE_WINDOWS_H) 33.206 + CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) 33.207 + IF(NOT HAVE_GETTIMEOFDAY) 33.208 + MESSAGE(FATAL_ERROR "No timing function found!") 33.209 + ENDIF() 33.210 + 33.211 + CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP) 33.212 + IF(NOT HAVE_NANOSLEEP) 33.213 + MESSAGE(FATAL_ERROR "No sleep function found!") 33.214 + ENDIF() 33.215 + 33.216 + CHECK_C_COMPILER_FLAG(-pthread HAVE_PTHREAD) 33.217 + IF(HAVE_PTHREAD) 33.218 + ADD_DEFINITIONS(-pthread) 33.219 + SET(EXTRA_LIBS ${EXTRA_LIBS} -pthread) 33.220 + ENDIF() 33.221 + 33.222 + # We need pthreads outside of Windows 33.223 + CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H) 33.224 + IF(NOT HAVE_PTHREAD_H) 33.225 + MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!") 33.226 + ENDIF() 33.227 + # Some systems need pthread_np.h to get recursive mutexes 33.228 + CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H) 33.229 + 33.230 + # _GNU_SOURCE is needed on some systems for extra attributes, and 33.231 + # _REENTRANT is needed for libc thread-safety 33.232 + ADD_DEFINITIONS(-D_GNU_SOURCE=1) 33.233 + CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD) 33.234 + IF(HAVE_LIBPTHREAD) 33.235 + SET(EXTRA_LIBS pthread ${EXTRA_LIBS}) 33.236 + ENDIF() 33.237 + 33.238 + CHECK_LIBRARY_EXISTS(pthread pthread_setschedparam "" HAVE_PTHREAD_SETSCHEDPARAM) 33.239 + 33.240 + CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_LIBRT) 33.241 + IF(HAVE_LIBRT) 33.242 + SET(EXTRA_LIBS rt ${EXTRA_LIBS}) 33.243 + ENDIF() 33.244 +ENDIF() 33.245 + 33.246 +# Check for a 64-bit type 33.247 +CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H) 33.248 +IF(NOT HAVE_STDINT_H) 33.249 + IF(HAVE_WINDOWS_H) 33.250 + CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0500 33.251 + \#include <windows.h> 33.252 + __int64 foo; 33.253 + int main() {return 0;}" HAVE___INT64) 33.254 + ENDIF() 33.255 + IF(NOT HAVE___INT64) 33.256 + IF(NOT SIZEOF_LONG MATCHES "8") 33.257 + IF(NOT SIZEOF_LONG_LONG MATCHES "8") 33.258 + MESSAGE(FATAL_ERROR "No 64-bit types found, please report!") 33.259 + ENDIF() 33.260 + ENDIF() 33.261 + ENDIF() 33.262 +ENDIF() 33.263 + 33.264 +# Windows needs winmm for timeGetTime, even if the backend is disabled 33.265 +CHECK_SHARED_FUNCTION_EXISTS(timeGetTime "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM) 33.266 +IF(HAVE_LIBWINMM) 33.267 + SET(EXTRA_LIBS winmm ${EXTRA_LIBS}) 33.268 + SET(PKG_CONFIG_LIBS ${PKG_CONFIG_LIBS} -lwinmm) 33.269 +ENDIF() 33.270 + 33.271 + 33.272 +SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c 33.273 + OpenAL32/alBuffer.c 33.274 + OpenAL32/alEffect.c 33.275 + OpenAL32/alError.c 33.276 + OpenAL32/alExtension.c 33.277 + OpenAL32/alFilter.c 33.278 + OpenAL32/alListener.c 33.279 + OpenAL32/alSource.c 33.280 + OpenAL32/alState.c 33.281 + OpenAL32/alThunk.c 33.282 +) 33.283 +SET(ALC_OBJS Alc/ALc.c 33.284 + Alc/ALu.c 33.285 + Alc/alcConfig.c 33.286 + Alc/alcDedicated.c 33.287 + Alc/alcEcho.c 33.288 + Alc/alcModulator.c 33.289 + Alc/alcReverb.c 33.290 + Alc/alcRing.c 33.291 + Alc/alcThread.c 33.292 + Alc/bs2b.c 33.293 + Alc/helpers.c 33.294 + Alc/hrtf.c 33.295 + Alc/mixer.c 33.296 + Alc/panning.c 33.297 + # Default backends, always available 33.298 + Alc/backends/loopback.c 33.299 + Alc/backends/null.c 33.300 + # RLM: add record device 33.301 + Alc/backends/record.c 33.302 +) 33.303 + 33.304 +SET(BACKENDS "") 33.305 +SET(HAVE_ALSA 0) 33.306 +SET(HAVE_OSS 0) 33.307 +SET(HAVE_SOLARIS 0) 33.308 +SET(HAVE_SNDIO 0) 33.309 +SET(HAVE_DSOUND 0) 33.310 +SET(HAVE_WINMM 0) 33.311 +SET(HAVE_PORTAUDIO 0) 33.312 +SET(HAVE_PULSEAUDIO 0) 33.313 +SET(HAVE_COREAUDIO 0) 33.314 +SET(HAVE_OPENSL 0) 33.315 +SET(HAVE_WAVE 0) 33.316 + 33.317 + 33.318 +# Check for MMDevApi backend 33.319 +IF(HAVE_WINDOWS_H) 33.320 + IF(MMDEVAPI) 33.321 + CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H) 33.322 + IF(HAVE_MMDEVICEAPI_H) 33.323 + SET(HAVE_MMDEVAPI 1) 33.324 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c) 33.325 + 33.326 + SET(BACKENDS "${BACKENDS} MMDevApi,") 33.327 + ENDIF() 33.328 + ENDIF() 33.329 +ENDIF() 33.330 +IF(REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI) 33.331 + MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend") 33.332 +ENDIF() 33.333 + 33.334 + 33.335 +IF(HAVE_WINDOWS_H) 33.336 + IF(WINMM) 33.337 + CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500) 33.338 + IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM) 33.339 + SET(HAVE_WINMM 1) 33.340 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c) 33.341 + SET(BACKENDS "${BACKENDS} WinMM,") 33.342 + ENDIF() 33.343 + ENDIF() 33.344 +ENDIF() 33.345 +IF(REQUIRE_WINMM AND NOT HAVE_WINMM) 33.346 + MESSAGE(FATAL_ERROR "Failed to enable required WinMM backend") 33.347 +ENDIF() 33.348 + 33.349 +# Optionally enable the Wave Writer backend 33.350 +IF(WAVE) 33.351 + SET(HAVE_WAVE 1) 33.352 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wave.c) 33.353 + SET(BACKENDS "${BACKENDS} WaveFile,") 33.354 +ENDIF() 33.355 + 33.356 + 33.357 +# RLM: enable the record backend 33.358 +SET(ALC_OBJS ${ALC_OBJS} Alc/backends/record.c) 33.359 +SET(BACKENDS "${BACKENDS} Record,") 33.360 + 33.361 + 33.362 +# This is always available 33.363 +SET(BACKENDS "${BACKENDS} Null") 33.364 + 33.365 +# Needed for openal.pc.in 33.366 +SET(prefix ${CMAKE_INSTALL_PREFIX}) 33.367 +SET(exec_prefix "\${prefix}") 33.368 +SET(libdir "\${exec_prefix}/lib${LIB_SUFFIX}") 33.369 +SET(bindir "\${exec_prefix}/bin") 33.370 +SET(includedir "\${prefix}/include") 33.371 +SET(PACKAGE_VERSION "${LIB_VERSION}") 33.372 + 33.373 +# End configuration 33.374 +CONFIGURE_FILE( 33.375 + "${OpenAL_SOURCE_DIR}/config.h.in" 33.376 + "${OpenAL_BINARY_DIR}/config.h") 33.377 +CONFIGURE_FILE( 33.378 + "${OpenAL_SOURCE_DIR}/openal.pc.in" 33.379 + "${OpenAL_BINARY_DIR}/openal.pc" 33.380 + @ONLY) 33.381 + 33.382 + 33.383 +# RLM link jni the dumb way for now: 33.384 +INCLUDE_DIRECTORIES("/usr/lib/jvm/java-6-sun-1.6.0.20/include/") 33.385 +INCLUDE_DIRECTORIES("/usr/lib/jvm/java-6-sun-1.6.0.20/include/linux") 33.386 + 33.387 + 33.388 +# Build a library 33.389 +ADD_LIBRARY(${LIBNAME} SHARED ${OPENAL_OBJS} ${ALC_OBJS}) 33.390 +SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES DEFINE_SYMBOL AL_BUILD_LIBRARY 33.391 + COMPILE_FLAGS -DAL_ALEXT_PROTOTYPES 33.392 + VERSION ${LIB_VERSION}.0 33.393 + SOVERSION ${LIB_MAJOR_VERSION}) 33.394 + 33.395 + 33.396 +TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS}) 33.397 + 33.398 +# Add an install target here 33.399 +INSTALL(TARGETS ${LIBNAME} 33.400 + RUNTIME DESTINATION bin 33.401 + LIBRARY DESTINATION "lib${LIB_SUFFIX}" 33.402 + ARCHIVE DESTINATION "lib${LIB_SUFFIX}" 33.403 +) 33.404 +INSTALL(FILES include/AL/al.h 33.405 + include/AL/alc.h 33.406 + include/AL/alext.h 33.407 + include/AL/efx.h 33.408 + include/AL/efx-creative.h 33.409 + DESTINATION include/AL 33.410 +) 33.411 +INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc" 33.412 + DESTINATION "lib${LIB_SUFFIX}/pkgconfig") 33.413 + 33.414 + 33.415 +MESSAGE(STATUS "") 33.416 +MESSAGE(STATUS "Building OpenAL with support for the following backends:") 33.417 +MESSAGE(STATUS " ${BACKENDS}") 33.418 +MESSAGE(STATUS "") 33.419 + 33.420 +# Install alsoft.conf configuration file 33.421 + 33.422 +IF(UTILS) 33.423 + ADD_EXECUTABLE(openal-info utils/openal-info.c) 33.424 + TARGET_LINK_LIBRARIES(openal-info ${LIBNAME}) 33.425 + INSTALL(TARGETS openal-info 33.426 + RUNTIME DESTINATION bin 33.427 + LIBRARY DESTINATION "lib${LIB_SUFFIX}" 33.428 + ARCHIVE DESTINATION "lib${LIB_SUFFIX}" 33.429 + ) 33.430 + MESSAGE(STATUS "Building utility programs") 33.431 + MESSAGE(STATUS "") 33.432 +ENDIF() 33.433 + 33.434 +
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 34.2 +++ b/CMakeLists.txt Tue Oct 25 13:02:31 2011 -0700 34.3 @@ -0,0 +1,715 @@ 34.4 +# CMake build file list for OpenAL 34.5 + 34.6 +CMAKE_MINIMUM_REQUIRED(VERSION 2.4) 34.7 + 34.8 +IF(COMMAND CMAKE_POLICY) 34.9 + CMAKE_POLICY(SET CMP0003 NEW) 34.10 +ENDIF(COMMAND CMAKE_POLICY) 34.11 + 34.12 +SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 34.13 + 34.14 +INCLUDE(CheckFunctionExists) 34.15 +INCLUDE(CheckLibraryExists) 34.16 +INCLUDE(CheckSharedFunctionExists) 34.17 +INCLUDE(CheckIncludeFile) 34.18 +INCLUDE(CheckIncludeFiles) 34.19 +INCLUDE(CheckSymbolExists) 34.20 +INCLUDE(CheckCCompilerFlag) 34.21 +INCLUDE(CheckCSourceCompiles) 34.22 +INCLUDE(CheckTypeSize) 34.23 + 34.24 + 34.25 +PROJECT(OpenAL C) 34.26 + 34.27 + 34.28 +SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS TRUE) 34.29 + 34.30 + 34.31 +OPTION(ALSA "Check for ALSA backend" ON) 34.32 +OPTION(OSS "Check for OSS backend" ON) 34.33 +OPTION(SOLARIS "Check for Solaris backend" ON) 34.34 +OPTION(SNDIO "Check for SndIO backend" ON) 34.35 +OPTION(MMDEVAPI "Check for MMDevApi" ON) 34.36 +OPTION(DSOUND "Check for DirectSound backend" ON) 34.37 +OPTION(WINMM "Check for Windows Multimedia backend" ON) 34.38 +OPTION(PORTAUDIO "Check for PortAudio backend" ON) 34.39 +OPTION(PULSEAUDIO "Check for PulseAudio backend" ON) 34.40 +OPTION(COREAUDIO "Check for CoreAudio backend" ON) 34.41 +OPTION(OPENSL "Check for OpenSL backend" ON) 34.42 +OPTION(WAVE "Enable Wave Writer backend" ON) 34.43 +OPTION(SEND "Enable Send Backend" ON) 34.44 + 34.45 +OPTION(REQUIRE_ALSA "Require ALSA backend" OFF) 34.46 +OPTION(REQUIRE_OSS "Require OSS backend" OFF) 34.47 +OPTION(REQUIRE_SOLARIS "Require Solaris backend" OFF) 34.48 +OPTION(REQUIRE_SNDIO "Require SndIO backend" OFF) 34.49 +OPTION(REQUIRE_MMDEVAPI "Require MMDevApi" OFF) 34.50 +OPTION(REQUIRE_DSOUND "Require DirectSound backend" OFF) 34.51 +OPTION(REQUIRE_WINMM "Require Windows Multimedia backend" OFF) 34.52 +OPTION(REQUIRE_PORTAUDIO "Require PortAudio backend" OFF) 34.53 +OPTION(REQUIRE_PULSEAUDIO "Require PulseAudio backend" OFF) 34.54 +OPTION(REQUIRE_COREAUDIO "Require CoreAudio backend" OFF) 34.55 +OPTION(REQUIRE_OPENSL "Require OpenSL backend" OFF) 34.56 + 34.57 +OPTION(DLOPEN "Check for the dlopen API for loading optional libs" ON) 34.58 + 34.59 +OPTION(WERROR "Treat compile warnings as errors" OFF) 34.60 + 34.61 +OPTION(UTILS "Build and install utility programs" ON) 34.62 + 34.63 +OPTION(ALSOFT_CONFIG "Install alsoft.conf configuration file" OFF) 34.64 + 34.65 + 34.66 +IF(WIN32) 34.67 + SET(LIBNAME OpenAL32) 34.68 + ADD_DEFINITIONS("-D_WIN32") 34.69 +ELSE() 34.70 + SET(LIBNAME openal) 34.71 +ENDIF() 34.72 + 34.73 +IF(NOT LIBTYPE) 34.74 + SET(LIBTYPE SHARED) 34.75 +ENDIF() 34.76 + 34.77 +SET(LIB_MAJOR_VERSION "1") 34.78 +SET(LIB_MINOR_VERSION "13") 34.79 +SET(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}") 34.80 + 34.81 +SET(EXPORT_DECL "") 34.82 + 34.83 + 34.84 +CHECK_TYPE_SIZE("long" SIZEOF_LONG) 34.85 +CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG) 34.86 +CHECK_TYPE_SIZE("unsigned int" SIZEOF_UINT) 34.87 +CHECK_TYPE_SIZE("void*" SIZEOF_VOIDP) 34.88 + 34.89 + 34.90 +CHECK_C_SOURCE_COMPILES("int *restrict foo; 34.91 + int main() {return 0;}" HAVE_RESTRICT) 34.92 +CHECK_C_SOURCE_COMPILES("int *__restrict foo; 34.93 + int main() {return 0;}" HAVE___RESTRICT) 34.94 + 34.95 + 34.96 +# Add definitions, compiler switches, etc. 34.97 +INCLUDE_DIRECTORIES(OpenAL32/Include include "${OpenAL_BINARY_DIR}") 34.98 + 34.99 +IF(NOT CMAKE_BUILD_TYPE) 34.100 + SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING 34.101 + "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." 34.102 + FORCE) 34.103 +ENDIF() 34.104 +IF(NOT CMAKE_DEBUG_POSTFIX) 34.105 + SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING 34.106 + "Library postfix for debug builds. Normally left blank." 34.107 + FORCE) 34.108 +ENDIF() 34.109 + 34.110 + 34.111 + 34.112 +IF(MSVC) 34.113 + # ??? 34.114 + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -D_DEBUG") 34.115 + SET(CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -DNDEBUG") 34.116 + SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -DNDEBUG") 34.117 + SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -D_DEBUG") 34.118 + ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) 34.119 + ADD_DEFINITIONS(-D_CRT_NONSTDC_NO_DEPRECATE) 34.120 + 34.121 + IF(NOT DXSDK_DIR) 34.122 + STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}") 34.123 + ELSE() 34.124 + STRING(REGEX REPLACE "\\\\" "/" DXSDK_DIR "${DXSDK_DIR}") 34.125 + ENDIF() 34.126 + IF(DXSDK_DIR) 34.127 + MESSAGE(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}") 34.128 + SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "${DXSDK_DIR}/Include") 34.129 + INCLUDE_DIRECTORIES("${DXSDK_DIR}/Include") 34.130 + LINK_DIRECTORIES("${DXSDK_DIR}/Lib") 34.131 + ENDIF() 34.132 + 34.133 + OPTION(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF) 34.134 + IF(FORCE_STATIC_VCRT) 34.135 + FOREACH(flag_var 34.136 + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE 34.137 + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO) 34.138 + IF(${flag_var} MATCHES "/MD") 34.139 + STRING(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") 34.140 + ENDIF() 34.141 + ENDFOREACH(flag_var) 34.142 + ENDIF() 34.143 +ELSE() 34.144 + ADD_DEFINITIONS(-Winline -Wall) 34.145 + CHECK_C_COMPILER_FLAG(-Wextra HAVE_W_EXTRA) 34.146 + IF(HAVE_W_EXTRA) 34.147 + ADD_DEFINITIONS(-Wextra) 34.148 + ENDIF() 34.149 + 34.150 + IF(WERROR) 34.151 + ADD_DEFINITIONS(-Werror) 34.152 + ENDIF() 34.153 + 34.154 + SET(CMAKE_C_FLAGS_RELWITHDEBINFO "-g -O2 -D_DEBUG" CACHE STRING 34.155 + "Flags used by the compiler during Release with Debug Info builds." 34.156 + FORCE) 34.157 + SET(CMAKE_C_FLAGS_MINSIZEREL "-Os -DNDEBUG" CACHE STRING 34.158 + "Flags used by the compiler during release minsize builds." 34.159 + FORCE) 34.160 + SET(CMAKE_C_FLAGS_RELEASE "-O2 -fomit-frame-pointer -DNDEBUG" CACHE STRING 34.161 + "Flags used by the compiler during release builds" 34.162 + FORCE) 34.163 + SET(CMAKE_C_FLAGS_DEBUG "-g3 -D_DEBUG" CACHE STRING 34.164 + "Flags used by the compiler during debug builds." 34.165 + FORCE) 34.166 + 34.167 + CHECK_C_SOURCE_COMPILES("int foo() __attribute__((destructor)); 34.168 + int main() {return 0;}" HAVE_GCC_DESTRUCTOR) 34.169 +ENDIF() 34.170 + 34.171 +# Set visibility/export options if available 34.172 +IF(WIN32) 34.173 + SET(EXPORT_DECL "__declspec(dllexport)") 34.174 + 34.175 + OPTION(WINE "Enable use of Wine headers when compiling" OFF) 34.176 + IF(WINE) 34.177 + FIND_PATH(WINE_INCLUDE_DIR library.h 34.178 + PATHS 34.179 + /usr/include/wine 34.180 + /usr/local/include/wine 34.181 + CMAKE_FIND_ROOT_PATH_BOTH) 34.182 + IF(WINE_INCLUDE_DIR) 34.183 + MESSAGE(STATUS "Found Wine header files - ${WINE_INCLUDE_DIR}" ) 34.184 + INCLUDE_DIRECTORIES("${WINE_INCLUDE_DIR}/windows") 34.185 + SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} "${WINE_INCLUDE_DIR}/windows") 34.186 + ELSE() 34.187 + MESSAGE(STATUS "Could not find Wine header files" ) 34.188 + ENDIF() 34.189 + ENDIF() 34.190 +ELSE() 34.191 + CHECK_C_COMPILER_FLAG(-fvisibility=internal HAVE_VISIBILITY_SWITCH) 34.192 + CHECK_C_SOURCE_COMPILES("int foo() __attribute__((visibility(\"protected\"))); 34.193 + int main() {return 0;}" HAVE_GCC_VISIBILITY) 34.194 + IF(HAVE_VISIBILITY_SWITCH AND HAVE_GCC_VISIBILITY) 34.195 + #ADD_DEFINITIONS(-fvisibility=internal) 34.196 + #SET(EXPORT_DECL "__attribute__((visibility(\"protected\")))") 34.197 + ENDIF() 34.198 +ENDIF() 34.199 + 34.200 +CHECK_C_SOURCE_COMPILES("int foo(const char *str, ...) __attribute__((format(printf, 1, 2))); 34.201 + int main() {return 0;}" HAVE_GCC_FORMAT) 34.202 + 34.203 +CHECK_INCLUDE_FILE(fenv.h HAVE_FENV_H) 34.204 +CHECK_INCLUDE_FILE(float.h HAVE_FLOAT_H) 34.205 +CHECK_INCLUDE_FILE(ieeefp.h HAVE_IEEEFP_H) 34.206 +CHECK_INCLUDE_FILE(guiddef.h HAVE_GUIDDEF_H) 34.207 +IF(NOT HAVE_GUIDDEF_H) 34.208 + CHECK_INCLUDE_FILE(initguid.h HAVE_INITGUID_H) 34.209 +ENDIF() 34.210 +CHECK_INCLUDE_FILE(arm_neon.h HAVE_ARM_NEON_H) 34.211 + 34.212 +CHECK_LIBRARY_EXISTS(m powf "" HAVE_POWF) 34.213 +CHECK_LIBRARY_EXISTS(m sqrtf "" HAVE_SQRTF) 34.214 +CHECK_LIBRARY_EXISTS(m acosf "" HAVE_ACOSF) 34.215 +CHECK_LIBRARY_EXISTS(m atanf "" HAVE_ATANF) 34.216 +CHECK_LIBRARY_EXISTS(m fabsf "" HAVE_FABSF) 34.217 +IF(HAVE_FENV_H) 34.218 + CHECK_LIBRARY_EXISTS(m fesetround "" HAVE_FESETROUND) 34.219 +ENDIF() 34.220 +IF(HAVE_SQRTF OR HAVE_ACOSF OR HAVE_ATANF OR HAVE_FABSF OR HAVE_FESETROUND) 34.221 + SET(EXTRA_LIBS m ${EXTRA_LIBS}) 34.222 +ENDIF() 34.223 +CHECK_FUNCTION_EXISTS(strtof HAVE_STRTOF) 34.224 +CHECK_FUNCTION_EXISTS(_controlfp HAVE__CONTROLFP) 34.225 + 34.226 +CHECK_FUNCTION_EXISTS(stat HAVE_STAT) 34.227 +CHECK_FUNCTION_EXISTS(strcasecmp HAVE_STRCASECMP) 34.228 +IF(NOT HAVE_STRCASECMP) 34.229 + CHECK_FUNCTION_EXISTS(_stricmp HAVE__STRICMP) 34.230 + IF(NOT HAVE__STRICMP) 34.231 + MESSAGE(FATAL_ERROR "No case-insensitive compare function found, please report!") 34.232 + ENDIF() 34.233 + 34.234 + ADD_DEFINITIONS(-Dstrcasecmp=_stricmp) 34.235 +ENDIF() 34.236 + 34.237 +CHECK_FUNCTION_EXISTS(strncasecmp HAVE_STRNCASECMP) 34.238 +IF(NOT HAVE_STRNCASECMP) 34.239 + CHECK_FUNCTION_EXISTS(_strnicmp HAVE__STRNICMP) 34.240 + IF(NOT HAVE__STRNICMP) 34.241 + MESSAGE(FATAL_ERROR "No case-insensitive size-limitted compare function found, please report!") 34.242 + ENDIF() 34.243 + 34.244 + ADD_DEFINITIONS(-Dstrncasecmp=_strnicmp) 34.245 +ENDIF() 34.246 + 34.247 +CHECK_FUNCTION_EXISTS(snprintf HAVE_SNPRINTF) 34.248 +IF(NOT HAVE_SNPRINTF) 34.249 + CHECK_FUNCTION_EXISTS(_snprintf HAVE__SNPRINTF) 34.250 + IF(NOT HAVE__SNPRINTF) 34.251 + MESSAGE(FATAL_ERROR "No snprintf function found, please report!") 34.252 + ENDIF() 34.253 + 34.254 + ADD_DEFINITIONS(-Dsnprintf=_snprintf) 34.255 +ENDIF() 34.256 + 34.257 +CHECK_FUNCTION_EXISTS(vsnprintf HAVE_VSNPRINTF) 34.258 +IF(NOT HAVE_VSNPRINTF) 34.259 + CHECK_FUNCTION_EXISTS(_vsnprintf HAVE__VSNPRINTF) 34.260 + IF(NOT HAVE__VSNPRINTF) 34.261 + MESSAGE(FATAL_ERROR "No vsnprintf function found, please report!") 34.262 + ENDIF() 34.263 + 34.264 + ADD_DEFINITIONS(-Dvsnprintf=_vsnprintf) 34.265 +ENDIF() 34.266 + 34.267 +CHECK_SYMBOL_EXISTS(isfinite math.h HAVE_ISFINITE) 34.268 +IF(NOT HAVE_ISFINITE) 34.269 + CHECK_FUNCTION_EXISTS(finite HAVE_FINITE) 34.270 + IF(NOT HAVE_FINITE) 34.271 + CHECK_FUNCTION_EXISTS(_finite HAVE__FINITE) 34.272 + IF(NOT HAVE__FINITE) 34.273 + MESSAGE(FATAL_ERROR "No isfinite function found, please report!") 34.274 + ENDIF() 34.275 + ADD_DEFINITIONS(-Disfinite=_finite) 34.276 + ELSE() 34.277 + ADD_DEFINITIONS(-Disfinite=finite) 34.278 + ENDIF() 34.279 +ENDIF() 34.280 + 34.281 +CHECK_SYMBOL_EXISTS(isnan math.h HAVE_ISNAN) 34.282 +IF(NOT HAVE_ISNAN) 34.283 + CHECK_FUNCTION_EXISTS(_isnan HAVE__ISNAN) 34.284 + IF(NOT HAVE__ISNAN) 34.285 + MESSAGE(FATAL_ERROR "No isnan function found, please report!") 34.286 + ENDIF() 34.287 + 34.288 + ADD_DEFINITIONS(-Disnan=_isnan) 34.289 +ENDIF() 34.290 + 34.291 + 34.292 +# Check for the dlopen API (for dynamicly loading backend libs) 34.293 +IF(DLOPEN) 34.294 + CHECK_INCLUDE_FILE(dlfcn.h HAVE_DLFCN_H) 34.295 + IF(HAVE_DLFCN_H) 34.296 + CHECK_LIBRARY_EXISTS(dl dlopen "" HAVE_LIBDL) 34.297 + IF(HAVE_LIBDL) 34.298 + SET(EXTRA_LIBS dl ${EXTRA_LIBS}) 34.299 + ENDIF() 34.300 + ENDIF() 34.301 +ENDIF() 34.302 + 34.303 +# Check if we have Windows headers 34.304 +CHECK_INCLUDE_FILE(windows.h HAVE_WINDOWS_H -D_WIN32_WINNT=0x0500) 34.305 +IF(NOT HAVE_WINDOWS_H) 34.306 + CHECK_FUNCTION_EXISTS(gettimeofday HAVE_GETTIMEOFDAY) 34.307 + IF(NOT HAVE_GETTIMEOFDAY) 34.308 + MESSAGE(FATAL_ERROR "No timing function found!") 34.309 + ENDIF() 34.310 + 34.311 + CHECK_FUNCTION_EXISTS(nanosleep HAVE_NANOSLEEP) 34.312 + IF(NOT HAVE_NANOSLEEP) 34.313 + MESSAGE(FATAL_ERROR "No sleep function found!") 34.314 + ENDIF() 34.315 + 34.316 + CHECK_C_COMPILER_FLAG(-pthread HAVE_PTHREAD) 34.317 + IF(HAVE_PTHREAD) 34.318 + ADD_DEFINITIONS(-pthread) 34.319 + SET(EXTRA_LIBS ${EXTRA_LIBS} -pthread) 34.320 + ENDIF() 34.321 + 34.322 + # We need pthreads outside of Windows 34.323 + CHECK_INCLUDE_FILE(pthread.h HAVE_PTHREAD_H) 34.324 + IF(NOT HAVE_PTHREAD_H) 34.325 + MESSAGE(FATAL_ERROR "PThreads is required for non-Windows builds!") 34.326 + ENDIF() 34.327 + # Some systems need pthread_np.h to get recursive mutexes 34.328 + CHECK_INCLUDE_FILES("pthread.h;pthread_np.h" HAVE_PTHREAD_NP_H) 34.329 + 34.330 + # _GNU_SOURCE is needed on some systems for extra attributes, and 34.331 + # _REENTRANT is needed for libc thread-safety 34.332 + ADD_DEFINITIONS(-D_GNU_SOURCE=1) 34.333 + CHECK_LIBRARY_EXISTS(pthread pthread_create "" HAVE_LIBPTHREAD) 34.334 + IF(HAVE_LIBPTHREAD) 34.335 + SET(EXTRA_LIBS pthread ${EXTRA_LIBS}) 34.336 + ENDIF() 34.337 + 34.338 + CHECK_LIBRARY_EXISTS(pthread pthread_setschedparam "" HAVE_PTHREAD_SETSCHEDPARAM) 34.339 + 34.340 + CHECK_LIBRARY_EXISTS(rt clock_gettime "" HAVE_LIBRT) 34.341 + IF(HAVE_LIBRT) 34.342 + SET(EXTRA_LIBS rt ${EXTRA_LIBS}) 34.343 + ENDIF() 34.344 +ENDIF() 34.345 + 34.346 +# Check for a 64-bit type 34.347 +CHECK_INCLUDE_FILE(stdint.h HAVE_STDINT_H) 34.348 +IF(NOT HAVE_STDINT_H) 34.349 + IF(HAVE_WINDOWS_H) 34.350 + CHECK_C_SOURCE_COMPILES("\#define _WIN32_WINNT 0x0500 34.351 + \#include <windows.h> 34.352 + __int64 foo; 34.353 + int main() {return 0;}" HAVE___INT64) 34.354 + ENDIF() 34.355 + IF(NOT HAVE___INT64) 34.356 + IF(NOT SIZEOF_LONG MATCHES "8") 34.357 + IF(NOT SIZEOF_LONG_LONG MATCHES "8") 34.358 + MESSAGE(FATAL_ERROR "No 64-bit types found, please report!") 34.359 + ENDIF() 34.360 + ENDIF() 34.361 + ENDIF() 34.362 +ENDIF() 34.363 + 34.364 +# Windows needs winmm for timeGetTime, even if the backend is disabled 34.365 +CHECK_SHARED_FUNCTION_EXISTS(timeGetTime "windows.h;mmsystem.h" winmm "" HAVE_LIBWINMM) 34.366 +IF(HAVE_LIBWINMM) 34.367 + SET(EXTRA_LIBS winmm ${EXTRA_LIBS}) 34.368 + SET(PKG_CONFIG_LIBS ${PKG_CONFIG_LIBS} -lwinmm) 34.369 +ENDIF() 34.370 + 34.371 + 34.372 +SET(OPENAL_OBJS OpenAL32/alAuxEffectSlot.c 34.373 + OpenAL32/alBuffer.c 34.374 + OpenAL32/alEffect.c 34.375 + OpenAL32/alError.c 34.376 + OpenAL32/alExtension.c 34.377 + OpenAL32/alFilter.c 34.378 + OpenAL32/alListener.c 34.379 + OpenAL32/alSource.c 34.380 + OpenAL32/alState.c 34.381 + OpenAL32/alThunk.c 34.382 +) 34.383 +SET(ALC_OBJS Alc/ALc.c 34.384 + Alc/ALu.c 34.385 + Alc/alcConfig.c 34.386 + Alc/alcDedicated.c 34.387 + Alc/alcEcho.c 34.388 + Alc/alcModulator.c 34.389 + Alc/alcReverb.c 34.390 + Alc/alcRing.c 34.391 + Alc/alcThread.c 34.392 + Alc/bs2b.c 34.393 + Alc/helpers.c 34.394 + Alc/hrtf.c 34.395 + Alc/mixer.c 34.396 + Alc/panning.c 34.397 + # Default backends, always available 34.398 + Alc/backends/loopback.c 34.399 + Alc/backends/null.c 34.400 + # RLM: add send device 34.401 + Alc/backends/send.c 34.402 +) 34.403 + 34.404 +SET(BACKENDS "") 34.405 +SET(HAVE_ALSA 0) 34.406 +SET(HAVE_OSS 0) 34.407 +SET(HAVE_SOLARIS 0) 34.408 +SET(HAVE_SNDIO 0) 34.409 +SET(HAVE_DSOUND 0) 34.410 +SET(HAVE_WINMM 0) 34.411 +SET(HAVE_PORTAUDIO 0) 34.412 +SET(HAVE_PULSEAUDIO 0) 34.413 +SET(HAVE_COREAUDIO 0) 34.414 +SET(HAVE_OPENSL 0) 34.415 +SET(HAVE_WAVE 0) 34.416 + 34.417 + 34.418 +# Check ALSA backend 34.419 +IF(ALSA) 34.420 + CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ALSA_ASOUNDLIB_H) 34.421 + IF(HAVE_ALSA_ASOUNDLIB_H) 34.422 + CHECK_SHARED_FUNCTION_EXISTS(snd_pcm_open "alsa/asoundlib.h" asound "" HAVE_LIBASOUND) 34.423 + IF(HAVE_LIBASOUND OR HAVE_DLFCN_H OR WIN32) 34.424 + SET(HAVE_ALSA 1) 34.425 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/alsa.c) 34.426 + IF(HAVE_DLFCN_H OR WIN32) 34.427 + SET(BACKENDS "${BACKENDS} ALSA,") 34.428 + ELSE() 34.429 + SET(BACKENDS "${BACKENDS} ALSA \(linked\),") 34.430 + SET(EXTRA_LIBS asound ${EXTRA_LIBS}) 34.431 + ENDIF() 34.432 + ENDIF() 34.433 + ENDIF() 34.434 +ENDIF() 34.435 +IF(REQUIRE_ALSA AND NOT HAVE_ALSA) 34.436 + MESSAGE(FATAL_ERROR "Failed to enabled required ALSA backend") 34.437 +ENDIF() 34.438 + 34.439 +# Check OSS backend 34.440 +IF(OSS) 34.441 + CHECK_INCLUDE_FILE(sys/soundcard.h HAVE_SYS_SOUNDCARD_H) 34.442 + IF(HAVE_SYS_SOUNDCARD_H) 34.443 + SET(HAVE_OSS 1) 34.444 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/oss.c) 34.445 + SET(BACKENDS "${BACKENDS} OSS,") 34.446 + ENDIF() 34.447 +ENDIF() 34.448 +IF(REQUIRE_OSS AND NOT HAVE_OSS) 34.449 + MESSAGE(FATAL_ERROR "Failed to enabled required OSS backend") 34.450 +ENDIF() 34.451 + 34.452 +# Check Solaris backend 34.453 +IF(SOLARIS) 34.454 + CHECK_INCLUDE_FILE(sys/audioio.h HAVE_SYS_AUDIOIO_H) 34.455 + IF(HAVE_SYS_AUDIOIO_H) 34.456 + SET(HAVE_SOLARIS 1) 34.457 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/solaris.c) 34.458 + SET(BACKENDS "${BACKENDS} Solaris,") 34.459 + ENDIF() 34.460 +ENDIF() 34.461 +IF(REQUIRE_SOLARIS AND NOT HAVE_SOLARIS) 34.462 + MESSAGE(FATAL_ERROR "Failed to enabled required Solaris backend") 34.463 +ENDIF() 34.464 + 34.465 +# Check SndIO backend 34.466 +IF(SNDIO) 34.467 + CHECK_INCLUDE_FILE(sndio.h HAVE_SNDIO_H) 34.468 + IF(HAVE_SNDIO_H) 34.469 + CHECK_SHARED_FUNCTION_EXISTS(sio_open "sndio.h" sndio "" HAVE_LIBSNDIO) 34.470 + IF(HAVE_LIBSNDIO OR HAVE_DLFCN_H OR WIN32) 34.471 + SET(HAVE_SNDIO 1) 34.472 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/sndio.c) 34.473 + IF(HAVE_DLFCN_H OR WIN32) 34.474 + SET(BACKENDS "${BACKENDS} SndIO,") 34.475 + ELSE() 34.476 + SET(BACKENDS "${BACKENDS} SndIO \(linked\),") 34.477 + SET(EXTRA_LIBS sndio ${EXTRA_LIBS}) 34.478 + ENDIF() 34.479 + ENDIF() 34.480 + ENDIF() 34.481 +ENDIF() 34.482 +IF(REQUIRE_SNDIO AND NOT HAVE_SNDIO) 34.483 + MESSAGE(FATAL_ERROR "Failed to enabled required SndIO backend") 34.484 +ENDIF() 34.485 + 34.486 +# Check for MMDevApi backend 34.487 +IF(HAVE_WINDOWS_H) 34.488 + IF(MMDEVAPI) 34.489 + CHECK_INCLUDE_FILE(mmdeviceapi.h HAVE_MMDEVICEAPI_H) 34.490 + IF(HAVE_MMDEVICEAPI_H) 34.491 + SET(HAVE_MMDEVAPI 1) 34.492 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/mmdevapi.c) 34.493 + 34.494 + SET(BACKENDS "${BACKENDS} MMDevApi,") 34.495 + ENDIF() 34.496 + ENDIF() 34.497 +ENDIF() 34.498 +IF(REQUIRE_MMDEVAPI AND NOT HAVE_MMDEVAPI) 34.499 + MESSAGE(FATAL_ERROR "Failed to enabled required MMDevApi backend") 34.500 +ENDIF() 34.501 + 34.502 +# Check DSound/MMSystem backend 34.503 +IF(DSOUND) 34.504 + CHECK_INCLUDE_FILE(dsound.h HAVE_DSOUND_H) 34.505 + IF(HAVE_DSOUND_H) 34.506 + CHECK_SHARED_FUNCTION_EXISTS(DirectSoundCreate "dsound.h" dsound "" HAVE_LIBDSOUND) 34.507 + IF(HAVE_LIBDSOUND OR HAVE_DLFCN_H OR WIN32) 34.508 + SET(HAVE_DSOUND 1) 34.509 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/dsound.c) 34.510 + 34.511 + IF(HAVE_DLFCN_H OR WIN32) 34.512 + SET(BACKENDS "${BACKENDS} DirectSound,") 34.513 + ELSE() 34.514 + SET(BACKENDS "${BACKENDS} DirectSound \(linked\),") 34.515 + SET(EXTRA_LIBS dsound ${EXTRA_LIBS}) 34.516 + ENDIF() 34.517 + ENDIF() 34.518 + ENDIF() 34.519 +ENDIF() 34.520 +IF(REQUIRE_DSOUND AND NOT HAVE_DSOUND) 34.521 + MESSAGE(FATAL_ERROR "Failed to enabled required DSound backend") 34.522 +ENDIF() 34.523 + 34.524 +IF(HAVE_WINDOWS_H) 34.525 + IF(WINMM) 34.526 + CHECK_INCLUDE_FILES("windows.h;mmsystem.h" HAVE_MMSYSTEM_H -D_WIN32_WINNT=0x0500) 34.527 + IF(HAVE_MMSYSTEM_H AND HAVE_LIBWINMM) 34.528 + SET(HAVE_WINMM 1) 34.529 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/winmm.c) 34.530 + SET(BACKENDS "${BACKENDS} WinMM,") 34.531 + ENDIF() 34.532 + ENDIF() 34.533 +ENDIF() 34.534 +IF(REQUIRE_WINMM AND NOT HAVE_WINMM) 34.535 + MESSAGE(FATAL_ERROR "Failed to enable required WinMM backend") 34.536 +ENDIF() 34.537 + 34.538 +# Check PortAudio backend 34.539 +IF(PORTAUDIO) 34.540 + CHECK_INCLUDE_FILE(portaudio.h HAVE_PORTAUDIO_H) 34.541 + IF(HAVE_PORTAUDIO_H) 34.542 + CHECK_SHARED_FUNCTION_EXISTS(Pa_Initialize "portaudio.h" portaudio "" HAVE_LIBPORTAUDIO) 34.543 + IF(HAVE_LIBPORTAUDIO OR HAVE_DLFCN_H OR WIN32) 34.544 + SET(HAVE_PORTAUDIO 1) 34.545 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/portaudio.c) 34.546 + IF(HAVE_DLFCN_H OR WIN32) 34.547 + SET(BACKENDS "${BACKENDS} PortAudio,") 34.548 + ELSE() 34.549 + SET(BACKENDS "${BACKENDS} PortAudio \(linked\),") 34.550 + SET(EXTRA_LIBS portaudio ${EXTRA_LIBS}) 34.551 + ENDIF() 34.552 + ENDIF() 34.553 + ENDIF() 34.554 +ENDIF() 34.555 +IF(REQUIRE_PORTAUDIO AND NOT HAVE_PORTAUDIO) 34.556 + MESSAGE(FATAL_ERROR "Failed to enabled required PortAudio backend") 34.557 +ENDIF() 34.558 + 34.559 +# Check PulseAudio backend 34.560 +IF(PULSEAUDIO) 34.561 + CHECK_INCLUDE_FILE(pulse/pulseaudio.h HAVE_PULSE_PULSEAUDIO_H) 34.562 + IF(HAVE_PULSE_PULSEAUDIO_H) 34.563 + CHECK_SHARED_FUNCTION_EXISTS(pa_context_new "pulse/pulseaudio.h" pulse "" HAVE_LIBPULSE) 34.564 + IF(HAVE_LIBPULSE OR HAVE_DLFCN_H OR WIN32) 34.565 + SET(HAVE_PULSEAUDIO 1) 34.566 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/pulseaudio.c) 34.567 + IF(HAVE_DLFCN_H OR WIN32) 34.568 + SET(BACKENDS "${BACKENDS} PulseAudio,") 34.569 + ELSE() 34.570 + SET(BACKENDS "${BACKENDS} PulseAudio \(linked\),") 34.571 + SET(EXTRA_LIBS pulse ${EXTRA_LIBS}) 34.572 + ENDIF() 34.573 + ENDIF() 34.574 + ENDIF() 34.575 +ENDIF() 34.576 +IF(REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO) 34.577 + MESSAGE(FATAL_ERROR "Failed to enabled required PulseAudio backend") 34.578 +ENDIF() 34.579 + 34.580 +# Check CoreAudio backend 34.581 +IF(COREAUDIO) 34.582 + CHECK_INCLUDE_FILE(/System/Library/Frameworks/CoreAudio.framework/Headers/CoreAudio.h HAVE_COREAUDIO_FRAMEWORK) 34.583 + IF(HAVE_COREAUDIO_FRAMEWORK) 34.584 + SET(HAVE_COREAUDIO 1) 34.585 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/coreaudio.c) 34.586 + SET(BACKENDS "${BACKENDS} CoreAudio,") 34.587 + SET(EXTRA_LIBS /System/Library/Frameworks/CoreAudio.framework ${EXTRA_LIBS}) 34.588 + SET(EXTRA_LIBS /System/Library/Frameworks/AudioUnit.framework ${EXTRA_LIBS}) 34.589 + SET(EXTRA_LIBS /System/Library/Frameworks/ApplicationServices.framework ${EXTRA_LIBS}) 34.590 + ENDIF() 34.591 +ENDIF() 34.592 +IF(REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO) 34.593 + MESSAGE(FATAL_ERROR "Failed to enabled required CoreAudio backend") 34.594 +ENDIF() 34.595 + 34.596 +# Check for OpenSL (Android) backend 34.597 +IF(OPENSL) 34.598 + CHECK_INCLUDE_FILE(SLES/OpenSLES_Android.h HAVE_SLES_OPENSLES_ANDROID_H) 34.599 + IF(HAVE_SLES_OPENSLES_ANDROID_H) 34.600 + CHECK_SHARED_FUNCTION_EXISTS(slCreateEngine "SLES/OpenSLES.h" OpenSLES "" HAVE_LIBOPENSLES) 34.601 + IF(HAVE_LIBOPENSLES) 34.602 + SET(HAVE_OPENSL 1) 34.603 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/opensl.c) 34.604 + SET(BACKENDS "${BACKENDS} OpenSL,") 34.605 + SET(EXTRA_LIBS OpenSLES ${EXTRA_LIBS}) 34.606 + ENDIF() 34.607 + ENDIF() 34.608 +ENDIF() 34.609 +IF(REQUIRE_OPENSL AND NOT HAVE_OPENSL) 34.610 + MESSAGE(FATAL_ERROR "Failed to enable required OpenSL backend") 34.611 +ENDIF() 34.612 + 34.613 +# Optionally enable the Wave Writer backend 34.614 +IF(WAVE) 34.615 + SET(HAVE_WAVE 1) 34.616 + SET(ALC_OBJS ${ALC_OBJS} Alc/backends/wave.c) 34.617 + SET(BACKENDS "${BACKENDS} WaveFile,") 34.618 +ENDIF() 34.619 + 34.620 + 34.621 +SET(ALC_OBJS ${ALC_OBJS} Alc/backends/send.c) 34.622 +SET(BACKENDS "${BACKENDS} Send,") 34.623 + 34.624 + 34.625 +# This is always available 34.626 +SET(BACKENDS "${BACKENDS} Null") 34.627 + 34.628 +IF(LIBTYPE STREQUAL "STATIC") 34.629 + ADD_DEFINITIONS(-DAL_LIBTYPE_STATIC) 34.630 + SET(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC ${PKG_CONFIG_CFLAGS}) 34.631 +ENDIF() 34.632 + 34.633 +# Needed for openal.pc.in 34.634 +SET(prefix ${CMAKE_INSTALL_PREFIX}) 34.635 +SET(exec_prefix "\${prefix}") 34.636 +SET(libdir "\${exec_prefix}/lib${LIB_SUFFIX}") 34.637 +SET(bindir "\${exec_prefix}/bin") 34.638 +SET(includedir "\${prefix}/include") 34.639 +SET(PACKAGE_VERSION "${LIB_VERSION}") 34.640 + 34.641 +# End configuration 34.642 +CONFIGURE_FILE( 34.643 + "${OpenAL_SOURCE_DIR}/config.h.in" 34.644 + "${OpenAL_BINARY_DIR}/config.h") 34.645 +CONFIGURE_FILE( 34.646 + "${OpenAL_SOURCE_DIR}/openal.pc.in" 34.647 + "${OpenAL_BINARY_DIR}/openal.pc" 34.648 + @ONLY) 34.649 + 34.650 +# Build a library 34.651 +ADD_LIBRARY(${LIBNAME} ${LIBTYPE} ${OPENAL_OBJS} ${ALC_OBJS}) 34.652 +SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES DEFINE_SYMBOL AL_BUILD_LIBRARY 34.653 + COMPILE_FLAGS -DAL_ALEXT_PROTOTYPES 34.654 + VERSION ${LIB_VERSION}.0 34.655 + SOVERSION ${LIB_MAJOR_VERSION}) 34.656 +IF(WIN32 AND NOT LIBTYPE STREQUAL "STATIC") 34.657 + SET_TARGET_PROPERTIES(${LIBNAME} PROPERTIES PREFIX "") 34.658 +ENDIF() 34.659 + 34.660 +# RLM link jni the dumb way for now: 34.661 + 34.662 +INCLUDE_DIRECTORIES("/opt/jdk/include/") 34.663 +INCLUDE_DIRECTORIES("/opt/jdk/include/linux") 34.664 +TARGET_LINK_LIBRARIES(${LIBNAME} ${EXTRA_LIBS}) 34.665 + 34.666 +# Add an install target here 34.667 +INSTALL(TARGETS ${LIBNAME} 34.668 + RUNTIME DESTINATION bin 34.669 + LIBRARY DESTINATION "lib${LIB_SUFFIX}" 34.670 + ARCHIVE DESTINATION "lib${LIB_SUFFIX}" 34.671 +) 34.672 +INSTALL(FILES include/AL/al.h 34.673 + include/AL/alc.h 34.674 + include/AL/alext.h 34.675 + include/AL/efx.h 34.676 + include/AL/efx-creative.h 34.677 + DESTINATION include/AL 34.678 +) 34.679 +INSTALL(FILES "${OpenAL_BINARY_DIR}/openal.pc" 34.680 + DESTINATION "lib${LIB_SUFFIX}/pkgconfig") 34.681 + 34.682 + 34.683 +MESSAGE(STATUS "") 34.684 +MESSAGE(STATUS "Building OpenAL with support for the following backends:") 34.685 +MESSAGE(STATUS " ${BACKENDS}") 34.686 +MESSAGE(STATUS "") 34.687 + 34.688 +IF(WIN32) 34.689 + IF(NOT HAVE_DSOUND) 34.690 + MESSAGE(STATUS "WARNING: Building the Windows version without DirectSound output") 34.691 + MESSAGE(STATUS " This is probably NOT what you want!") 34.692 + MESSAGE(STATUS "") 34.693 + ENDIF() 34.694 +ENDIF() 34.695 + 34.696 +# Install alsoft.conf configuration file 34.697 +IF(ALSOFT_CONFIG) 34.698 + INSTALL(FILES alsoftrc.sample 34.699 + DESTINATION /etc/openal 34.700 + RENAME alsoft.conf 34.701 + ) 34.702 + MESSAGE(STATUS "Installing sample alsoft.conf") 34.703 + MESSAGE(STATUS "") 34.704 +ENDIF() 34.705 + 34.706 +IF(UTILS) 34.707 + ADD_EXECUTABLE(openal-info utils/openal-info.c) 34.708 + TARGET_LINK_LIBRARIES(openal-info ${LIBNAME}) 34.709 + INSTALL(TARGETS openal-info 34.710 + RUNTIME DESTINATION bin 34.711 + LIBRARY DESTINATION "lib${LIB_SUFFIX}" 34.712 + ARCHIVE DESTINATION "lib${LIB_SUFFIX}" 34.713 + ) 34.714 + MESSAGE(STATUS "Building utility programs") 34.715 + MESSAGE(STATUS "") 34.716 +ENDIF() 34.717 + 34.718 +
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 35.2 +++ b/COPYING Tue Oct 25 13:02:31 2011 -0700 35.3 @@ -0,0 +1,484 @@ 35.4 + 35.5 + GNU LIBRARY GENERAL PUBLIC LICENSE 35.6 + Version 2, June 1991 35.7 + 35.8 + 35.9 + Copyright (C) 1991 Free Software Foundation, Inc. 35.10 + 675 Mass Ave, Cambridge, MA 02139, USA 35.11 + Everyone is permitted to copy and distribute verbatim copies 35.12 + of this license document, but changing it is not allowed. 35.13 + 35.14 +[This is the first released version of the library GPL. It is 35.15 + numbered 2 because it goes with version 2 of the ordinary GPL.] 35.16 + 35.17 + Preamble 35.18 + 35.19 + The licenses for most software are designed to take away your 35.20 +freedom to share and change it. By contrast, the GNU General Public 35.21 +Licenses are intended to guarantee your freedom to share and change 35.22 +free software--to make sure the software is free for all its users. 35.23 + 35.24 + This license, the Library General Public License, applies to some 35.25 +specially designated Free Software Foundation software, and to any 35.26 +other libraries whose authors decide to use it. You can use it for 35.27 +your libraries, too. 35.28 + 35.29 + When we speak of free software, we are referring to freedom, not 35.30 +price. Our General Public Licenses are designed to make sure that you 35.31 +have the freedom to distribute copies of free software (and charge for 35.32 +this service if you wish), that you receive source code or can get it 35.33 +if you want it, that you can change the software or use pieces of it 35.34 +in new free programs; and that you know you can do these things. 35.35 + 35.36 + To protect your rights, we need to make restrictions that forbid 35.37 +anyone to deny you these rights or to ask you to surrender the rights. 35.38 +These restrictions translate to certain responsibilities for you if 35.39 +you distribute copies of the library, or if you modify it. 35.40 + 35.41 + For example, if you distribute copies of the library, whether gratis 35.42 +or for a fee, you must give the recipients all the rights that we gave 35.43 +you. You must make sure that they, too, receive or can get the source 35.44 +code. If you link a program with the library, you must provide 35.45 +complete object files to the recipients so that they can relink them 35.46 +with the library, after making changes to the library and recompiling 35.47 +it. And you must show them these terms so they know their rights. 35.48 + 35.49 + Our method of protecting your rights has two steps: (1) copyright 35.50 +the library, and (2) offer you this license which gives you legal 35.51 +permission to copy, distribute and/or modify the library. 35.52 + 35.53 + Also, for each distributor's protection, we want to make certain 35.54 +that everyone understands that there is no warranty for this free 35.55 +library. If the library is modified by someone else and passed on, we 35.56 +want its recipients to know that what they have is not the original 35.57 +version, so that any problems introduced by others will not reflect on 35.58 +the original authors' reputations. 35.59 + 35.60 + Finally, any free program is threatened constantly by software 35.61 +patents. We wish to avoid the danger that companies distributing free 35.62 +software will individually obtain patent licenses, thus in effect 35.63 +transforming the program into proprietary software. To prevent this, 35.64 +we have made it clear that any patent must be licensed for everyone's 35.65 +free use or not licensed at all. 35.66 + 35.67 + Most GNU software, including some libraries, is covered by the ordinary 35.68 +GNU General Public License, which was designed for utility programs. This 35.69 +license, the GNU Library General Public License, applies to certain 35.70 +designated libraries. This license is quite different from the ordinary 35.71 +one; be sure to read it in full, and don't assume that anything in it is 35.72 +the same as in the ordinary license. 35.73 + 35.74 + The reason we have a separate public license for some libraries is that 35.75 +they blur the distinction we usually make between modifying or adding to a 35.76 +program and simply using it. Linking a program with a library, without 35.77 +changing the library, is in some sense simply using the library, and is 35.78 +analogous to running a utility program or application program. However, in 35.79 +a textual and legal sense, the linked executable is a combined work, a 35.80 +derivative of the original library, and the ordinary General Public License 35.81 +treats it as such. 35.82 + 35.83 + Because of this blurred distinction, using the ordinary General 35.84 +Public License for libraries did not effectively promote software 35.85 +sharing, because most developers did not use the libraries. We 35.86 +concluded that weaker conditions might promote sharing better. 35.87 + 35.88 + However, unrestricted linking of non-free programs would deprive the 35.89 +users of those programs of all benefit from the free status of the 35.90 +libraries themselves. This Library General Public License is intended to 35.91 +permit developers of non-free programs to use free libraries, while 35.92 +preserving your freedom as a user of such programs to change the free 35.93 +libraries that are incorporated in them. (We have not seen how to achieve 35.94 +this as regards changes in header files, but we have achieved it as regards 35.95 +changes in the actual functions of the Library.) The hope is that this 35.96 +will lead to faster development of free libraries. 35.97 + 35.98 + The precise terms and conditions for copying, distribution and 35.99 +modification follow. Pay close attention to the difference between a 35.100 +"work based on the library" and a "work that uses the library". The 35.101 +former contains code derived from the library, while the latter only 35.102 +works together with the library. 35.103 + 35.104 + Note that it is possible for a library to be covered by the ordinary 35.105 +General Public License rather than by this special one. 35.106 + 35.107 + GNU LIBRARY GENERAL PUBLIC LICENSE 35.108 + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 35.109 + 35.110 + 0. This License Agreement applies to any software library which 35.111 +contains a notice placed by the copyright holder or other authorized 35.112 +party saying it may be distributed under the terms of this Library 35.113 +General Public License (also called "this License"). Each licensee is 35.114 +addressed as "you". 35.115 + 35.116 + A "library" means a collection of software functions and/or data 35.117 +prepared so as to be conveniently linked with application programs 35.118 +(which use some of those functions and data) to form executables. 35.119 + 35.120 + The "Library", below, refers to any such software library or work 35.121 +which has been distributed under these terms. A "work based on the 35.122 +Library" means either the Library or any derivative work under 35.123 +copyright law: that is to say, a work containing the Library or a 35.124 +portion of it, either verbatim or with modifications and/or translated 35.125 +straightforwardly into another language. (Hereinafter, translation is 35.126 +included without limitation in the term "modification".) 35.127 + 35.128 + "Source code" for a work means the preferred form of the work for 35.129 +making modifications to it. For a library, complete source code means 35.130 +all the source code for all modules it contains, plus any associated 35.131 +interface definition files, plus the scripts used to control compilation 35.132 +and installation of the library. 35.133 + 35.134 + Activities other than copying, distribution and modification are not 35.135 +covered by this License; they are outside its scope. The act of 35.136 +running a program using the Library is not restricted, and output from 35.137 +such a program is covered only if its contents constitute a work based 35.138 +on the Library (independent of the use of the Library in a tool for 35.139 +writing it). Whether that is true depends on what the Library does 35.140 +and what the program that uses the Library does. 35.141 + 35.142 + 1. You may copy and distribute verbatim copies of the Library's 35.143 +complete source code as you receive it, in any medium, provided that 35.144 +you conspicuously and appropriately publish on each copy an 35.145 +appropriate copyright notice and disclaimer of warranty; keep intact 35.146 +all the notices that refer to this License and to the absence of any 35.147 +warranty; and distribute a copy of this License along with the 35.148 +Library. 35.149 + 35.150 + You may charge a fee for the physical act of transferring a copy, 35.151 +and you may at your option offer warranty protection in exchange for a 35.152 +fee. 35.153 + 35.154 + 2. You may modify your copy or copies of the Library or any portion 35.155 +of it, thus forming a work based on the Library, and copy and 35.156 +distribute such modifications or work under the terms of Section 1 35.157 +above, provided that you also meet all of these conditions: 35.158 + 35.159 + a) The modified work must itself be a software library. 35.160 + 35.161 + b) You must cause the files modified to carry prominent notices 35.162 + stating that you changed the files and the date of any change. 35.163 + 35.164 + c) You must cause the whole of the work to be licensed at no 35.165 + charge to all third parties under the terms of this License. 35.166 + 35.167 + d) If a facility in the modified Library refers to a function or a 35.168 + table of data to be supplied by an application program that uses 35.169 + the facility, other than as an argument passed when the facility 35.170 + is invoked, then you must make a good faith effort to ensure that, 35.171 + in the event an application does not supply such function or 35.172 + table, the facility still operates, and performs whatever part of 35.173 + its purpose remains meaningful. 35.174 + 35.175 + (For example, a function in a library to compute square roots has 35.176 + a purpose that is entirely well-defined independent of the 35.177 + application. Therefore, Subsection 2d requires that any 35.178 + application-supplied function or table used by this function must 35.179 + be optional: if the application does not supply it, the square 35.180 + root function must still compute square roots.) 35.181 + 35.182 +These requirements apply to the modified work as a whole. If 35.183 +identifiable sections of that work are not derived from the Library, 35.184 +and can be reasonably considered independent and separate works in 35.185 +themselves, then this License, and its terms, do not apply to those 35.186 +sections when you distribute them as separate works. But when you 35.187 +distribute the same sections as part of a whole which is a work based 35.188 +on the Library, the distribution of the whole must be on the terms of 35.189 +this License, whose permissions for other licensees extend to the 35.190 +entire whole, and thus to each and every part regardless of who wrote 35.191 +it. 35.192 + 35.193 +Thus, it is not the intent of this section to claim rights or contest 35.194 +your rights to work written entirely by you; rather, the intent is to 35.195 +exercise the right to control the distribution of derivative or 35.196 +collective works based on the Library. 35.197 + 35.198 +In addition, mere aggregation of another work not based on the Library 35.199 +with the Library (or with a work based on the Library) on a volume of 35.200 +a storage or distribution medium does not bring the other work under 35.201 +the scope of this License. 35.202 + 35.203 + 3. You may opt to apply the terms of the ordinary GNU General Public 35.204 +License instead of this License to a given copy of the Library. To do 35.205 +this, you must alter all the notices that refer to this License, so 35.206 +that they refer to the ordinary GNU General Public License, version 2, 35.207 +instead of to this License. (If a newer version than version 2 of the 35.208 +ordinary GNU General Public License has appeared, then you can specify 35.209 +that version instead if you wish.) Do not make any other change in 35.210 +these notices. 35.211 + 35.212 + Once this change is made in a given copy, it is irreversible for 35.213 +that copy, so the ordinary GNU General Public License applies to all 35.214 +subsequent copies and derivative works made from that copy. 35.215 + 35.216 + This option is useful when you wish to copy part of the code of 35.217 +the Library into a program that is not a library. 35.218 + 35.219 + 4. You may copy and distribute the Library (or a portion or 35.220 +derivative of it, under Section 2) in object code or executable form 35.221 +under the terms of Sections 1 and 2 above provided that you accompany 35.222 +it with the complete corresponding machine-readable source code, which 35.223 +must be distributed under the terms of Sections 1 and 2 above on a 35.224 +medium customarily used for software interchange. 35.225 + 35.226 + If distribution of object code is made by offering access to copy 35.227 +from a designated place, then offering equivalent access to copy the 35.228 +source code from the same place satisfies the requirement to 35.229 +distribute the source code, even though third parties are not 35.230 +compelled to copy the source along with the object code. 35.231 + 35.232 + 5. A program that contains no derivative of any portion of the 35.233 +Library, but is designed to work with the Library by being compiled or 35.234 +linked with it, is called a "work that uses the Library". Such a 35.235 +work, in isolation, is not a derivative work of the Library, and 35.236 +therefore falls outside the scope of this License. 35.237 + 35.238 + However, linking a "work that uses the Library" with the Library 35.239 +creates an executable that is a derivative of the Library (because it 35.240 +contains portions of the Library), rather than a "work that uses the 35.241 +library". The executable is therefore covered by this License. 35.242 +Section 6 states terms for distribution of such executables. 35.243 + 35.244 + When a "work that uses the Library" uses material from a header file 35.245 +that is part of the Library, the object code for the work may be a 35.246 +derivative work of the Library even though the source code is not. 35.247 +Whether this is true is especially significant if the work can be 35.248 +linked without the Library, or if the work is itself a library. The 35.249 +threshold for this to be true is not precisely defined by law. 35.250 + 35.251 + If such an object file uses only numerical parameters, data 35.252 +structure layouts and accessors, and small macros and small inline 35.253 +functions (ten lines or less in length), then the use of the object 35.254 +file is unrestricted, regardless of whether it is legally a derivative 35.255 +work. (Executables containing this object code plus portions of the 35.256 +Library will still fall under Section 6.) 35.257 + 35.258 + Otherwise, if the work is a derivative of the Library, you may 35.259 +distribute the object code for the work under the terms of Section 6. 35.260 +Any executables containing that work also fall under Section 6, 35.261 +whether or not they are linked directly with the Library itself. 35.262 + 35.263 + 6. As an exception to the Sections above, you may also compile or 35.264 +link a "work that uses the Library" with the Library to produce a 35.265 +work containing portions of the Library, and distribute that work 35.266 +under terms of your choice, provided that the terms permit 35.267 +modification of the work for the customer's own use and reverse 35.268 +engineering for debugging such modifications. 35.269 + 35.270 + You must give prominent notice with each copy of the work that the 35.271 +Library is used in it and that the Library and its use are covered by 35.272 +this License. You must supply a copy of this License. If the work 35.273 +during execution displays copyright notices, you must include the 35.274 +copyright notice for the Library among them, as well as a reference 35.275 +directing the user to the copy of this License. Also, you must do one 35.276 +of these things: 35.277 + 35.278 + a) Accompany the work with the complete corresponding 35.279 + machine-readable source code for the Library including whatever 35.280 + changes were used in the work (which must be distributed under 35.281 + Sections 1 and 2 above); and, if the work is an executable linked 35.282 + with the Library, with the complete machine-readable "work that 35.283 + uses the Library", as object code and/or source code, so that the 35.284 + user can modify the Library and then relink to produce a modified 35.285 + executable containing the modified Library. (It is understood 35.286 + that the user who changes the contents of definitions files in the 35.287 + Library will not necessarily be able to recompile the application 35.288 + to use the modified definitions.) 35.289 + 35.290 + b) Accompany the work with a written offer, valid for at 35.291 + least three years, to give the same user the materials 35.292 + specified in Subsection 6a, above, for a charge no more 35.293 + than the cost of performing this distribution. 35.294 + 35.295 + c) If distribution of the work is made by offering access to copy 35.296 + from a designated place, offer equivalent access to copy the above 35.297 + specified materials from the same place. 35.298 + 35.299 + d) Verify that the user has already received a copy of these 35.300 + materials or that you have already sent this user a copy. 35.301 + 35.302 + For an executable, the required form of the "work that uses the 35.303 +Library" must include any data and utility programs needed for 35.304 +reproducing the executable from it. However, as a special exception, 35.305 +the source code distributed need not include anything that is normally 35.306 +distributed (in either source or binary form) with the major 35.307 +components (compiler, kernel, and so on) of the operating system on 35.308 +which the executable runs, unless that component itself accompanies 35.309 +the executable. 35.310 + 35.311 + It may happen that this requirement contradicts the license 35.312 +restrictions of other proprietary libraries that do not normally 35.313 +accompany the operating system. Such a contradiction means you cannot 35.314 +use both them and the Library together in an executable that you 35.315 +distribute. 35.316 + 35.317 + 7. You may place library facilities that are a work based on the 35.318 +Library side-by-side in a single library together with other library 35.319 +facilities not covered by this License, and distribute such a combined 35.320 +library, provided that the separate distribution of the work based on 35.321 +the Library and of the other library facilities is otherwise 35.322 +permitted, and provided that you do these two things: 35.323 + 35.324 + a) Accompany the combined library with a copy of the same work 35.325 + based on the Library, uncombined with any other library 35.326 + facilities. This must be distributed under the terms of the 35.327 + Sections above. 35.328 + 35.329 + b) Give prominent notice with the combined library of the fact 35.330 + that part of it is a work based on the Library, and explaining 35.331 + where to find the accompanying uncombined form of the same work. 35.332 + 35.333 + 8. You may not copy, modify, sublicense, link with, or distribute 35.334 +the Library except as expressly provided under this License. Any 35.335 +attempt otherwise to copy, modify, sublicense, link with, or 35.336 +distribute the Library is void, and will automatically terminate your 35.337 +rights under this License. However, parties who have received copies, 35.338 +or rights, from you under this License will not have their licenses 35.339 +terminated so long as such parties remain in full compliance. 35.340 + 35.341 + 9. You are not required to accept this License, since you have not 35.342 +signed it. However, nothing else grants you permission to modify or 35.343 +distribute the Library or its derivative works. These actions are 35.344 +prohibited by law if you do not accept this License. Therefore, by 35.345 +modifying or distributing the Library (or any work based on the 35.346 +Library), you indicate your acceptance of this License to do so, and 35.347 +all its terms and conditions for copying, distributing or modifying 35.348 +the Library or works based on it. 35.349 + 35.350 + 10. Each time you redistribute the Library (or any work based on the 35.351 +Library), the recipient automatically receives a license from the 35.352 +original licensor to copy, distribute, link with or modify the Library 35.353 +subject to these terms and conditions. You may not impose any further 35.354 +restrictions on the recipients' exercise of the rights granted herein. 35.355 +You are not responsible for enforcing compliance by third parties to 35.356 +this License. 35.357 + 35.358 + 11. If, as a consequence of a court judgment or allegation of patent 35.359 +infringement or for any other reason (not limited to patent issues), 35.360 +conditions are imposed on you (whether by court order, agreement or 35.361 +otherwise) that contradict the conditions of this License, they do not 35.362 +excuse you from the conditions of this License. If you cannot 35.363 +distribute so as to satisfy simultaneously your obligations under this 35.364 +License and any other pertinent obligations, then as a consequence you 35.365 +may not distribute the Library at all. For example, if a patent 35.366 +license would not permit royalty-free redistribution of the Library by 35.367 +all those who receive copies directly or indirectly through you, then 35.368 +the only way you could satisfy both it and this License would be to 35.369 +refrain entirely from distribution of the Library. 35.370 + 35.371 +If any portion of this section is held invalid or unenforceable under any 35.372 +particular circumstance, the balance of the section is intended to apply, 35.373 +and the section as a whole is intended to apply in other circumstances. 35.374 + 35.375 +It is not the purpose of this section to induce you to infringe any 35.376 +patents or other property right claims or to contest validity of any 35.377 +such claims; this section has the sole purpose of protecting the 35.378 +integrity of the free software distribution system which is 35.379 +implemented by public license practices. Many people have made 35.380 +generous contributions to the wide range of software distributed 35.381 +through that system in reliance on consistent application of that 35.382 +system; it is up to the author/donor to decide if he or she is willing 35.383 +to distribute software through any other system and a licensee cannot 35.384 +impose that choice. 35.385 + 35.386 +This section is intended to make thoroughly clear what is believed to 35.387 +be a consequence of the rest of this License. 35.388 + 35.389 + 12. If the distribution and/or use of the Library is restricted in 35.390 +certain countries either by patents or by copyrighted interfaces, the 35.391 +original copyright holder who places the Library under this License may add 35.392 +an explicit geographical distribution limitation excluding those countries, 35.393 +so that distribution is permitted only in or among countries not thus 35.394 +excluded. In such case, this License incorporates the limitation as if 35.395 +written in the body of this License. 35.396 + 35.397 + 13. The Free Software Foundation may publish revised and/or new 35.398 +versions of the Library General Public License from time to time. 35.399 +Such new versions will be similar in spirit to the present version, 35.400 +but may differ in detail to address new problems or concerns. 35.401 + 35.402 +Each version is given a distinguishing version number. If the Library 35.403 +specifies a version number of this License which applies to it and 35.404 +"any later version", you have the option of following the terms and 35.405 +conditions either of that version or of any later version published by 35.406 +the Free Software Foundation. If the Library does not specify a 35.407 +license version number, you may choose any version ever published by 35.408 +the Free Software Foundation. 35.409 + 35.410 + 14. If you wish to incorporate parts of the Library into other free 35.411 +programs whose distribution conditions are incompatible with these, 35.412 +write to the author to ask for permission. For software which is 35.413 +copyrighted by the Free Software Foundation, write to the Free 35.414 +Software Foundation; we sometimes make exceptions for this. Our 35.415 +decision will be guided by the two goals of preserving the free status 35.416 +of all derivatives of our free software and of promoting the sharing 35.417 +and reuse of software generally. 35.418 + 35.419 + NO WARRANTY 35.420 + 35.421 + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 35.422 +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 35.423 +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 35.424 +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 35.425 +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 35.426 +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 35.427 +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 35.428 +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 35.429 +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 35.430 + 35.431 + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 35.432 +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 35.433 +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 35.434 +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 35.435 +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 35.436 +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 35.437 +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 35.438 +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 35.439 +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 35.440 +DAMAGES. 35.441 + 35.442 + END OF TERMS AND CONDITIONS 35.443 + 35.444 + Appendix: How to Apply These Terms to Your New Libraries 35.445 + 35.446 + If you develop a new library, and you want it to be of the greatest 35.447 +possible use to the public, we recommend making it free software that 35.448 +everyone can redistribute and change. You can do so by permitting 35.449 +redistribution under these terms (or, alternatively, under the terms of the 35.450 +ordinary General Public License). 35.451 + 35.452 + To apply these terms, attach the following notices to the library. It is 35.453 +safest to attach them to the start of each source file to most effectively 35.454 +convey the exclusion of warranty; and each file should have at least the 35.455 +"copyright" line and a pointer to where the full notice is found. 35.456 + 35.457 + <one line to give the library's name and a brief idea of what it does.> 35.458 + Copyright (C) <year> <name of author> 35.459 + 35.460 + This library is free software; you can redistribute it and/or 35.461 + modify it under the terms of the GNU Library General Public 35.462 + License as published by the Free Software Foundation; either 35.463 + version 2 of the License, or (at your option) any later version. 35.464 + 35.465 + This library is distributed in the hope that it will be useful, 35.466 + but WITHOUT ANY WARRANTY; without even the implied warranty of 35.467 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35.468 + Library General Public License for more details. 35.469 + 35.470 + You should have received a copy of the GNU Library General Public 35.471 + License along with this library; if not, write to the Free 35.472 + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 35.473 + 35.474 +Also add information on how to contact you by electronic and paper mail. 35.475 + 35.476 +You should also get your employer (if you work as a programmer) or your 35.477 +school, if any, to sign a "copyright disclaimer" for the library, if 35.478 +necessary. Here is a sample; alter the names: 35.479 + 35.480 + Yoyodyne, Inc., hereby disclaims all copyright interest in the 35.481 + library `Frob' (a library for tweaking knobs) written by James Random Hacker. 35.482 + 35.483 + <signature of Ty Coon>, 1 April 1990 35.484 + Ty Coon, President of Vice 35.485 + 35.486 +That's all there is to it! 35.487 +
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 36.2 +++ b/OpenAL32/Include/alAuxEffectSlot.h Tue Oct 25 13:02:31 2011 -0700 36.3 @@ -0,0 +1,66 @@ 36.4 +#ifndef _AL_AUXEFFECTSLOT_H_ 36.5 +#define _AL_AUXEFFECTSLOT_H_ 36.6 + 36.7 +#include "AL/al.h" 36.8 +#include "alEffect.h" 36.9 +#include "alFilter.h" 36.10 + 36.11 +#ifdef __cplusplus 36.12 +extern "C" { 36.13 +#endif 36.14 + 36.15 +typedef struct ALeffectState ALeffectState; 36.16 + 36.17 +typedef struct ALeffectslot 36.18 +{ 36.19 + ALeffect effect; 36.20 + 36.21 + ALfloat Gain; 36.22 + ALboolean AuxSendAuto; 36.23 + 36.24 + ALboolean NeedsUpdate; 36.25 + ALeffectState *EffectState; 36.26 + 36.27 + ALfloat WetBuffer[BUFFERSIZE]; 36.28 + 36.29 + ALfloat ClickRemoval[1]; 36.30 + ALfloat PendingClicks[1]; 36.31 + 36.32 + ALuint refcount; 36.33 + 36.34 + // Index to itself 36.35 + ALuint effectslot; 36.36 + 36.37 + struct ALeffectslot *next; 36.38 +} ALeffectslot; 36.39 + 36.40 + 36.41 +ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context); 36.42 + 36.43 + 36.44 +struct ALeffectState { 36.45 + ALvoid (*Destroy)(ALeffectState *State); 36.46 + ALboolean (*DeviceUpdate)(ALeffectState *State, ALCdevice *Device); 36.47 + ALvoid (*Update)(ALeffectState *State, ALCcontext *Context, const ALeffectslot *Slot); 36.48 + ALvoid (*Process)(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]); 36.49 +}; 36.50 + 36.51 +ALeffectState *NoneCreate(void); 36.52 +ALeffectState *EAXVerbCreate(void); 36.53 +ALeffectState *VerbCreate(void); 36.54 +ALeffectState *EchoCreate(void); 36.55 +ALeffectState *ModulatorCreate(void); 36.56 +ALeffectState *DedicatedDLGCreate(void); 36.57 +ALeffectState *DedicatedLFECreate(void); 36.58 + 36.59 +#define ALEffect_Destroy(a) ((a)->Destroy((a))) 36.60 +#define ALEffect_DeviceUpdate(a,b) ((a)->DeviceUpdate((a),(b))) 36.61 +#define ALEffect_Update(a,b,c) ((a)->Update((a),(b),(c))) 36.62 +#define ALEffect_Process(a,b,c,d,e) ((a)->Process((a),(b),(c),(d),(e))) 36.63 + 36.64 + 36.65 +#ifdef __cplusplus 36.66 +} 36.67 +#endif 36.68 + 36.69 +#endif
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 37.2 +++ b/OpenAL32/Include/alBuffer.h Tue Oct 25 13:02:31 2011 -0700 37.3 @@ -0,0 +1,100 @@ 37.4 +#ifndef _AL_BUFFER_H_ 37.5 +#define _AL_BUFFER_H_ 37.6 + 37.7 +#include "AL/al.h" 37.8 + 37.9 +#ifdef __cplusplus 37.10 +extern "C" { 37.11 +#endif 37.12 + 37.13 +/* User formats */ 37.14 +enum UserFmtType { 37.15 + UserFmtByte = AL_BYTE, 37.16 + UserFmtUByte = AL_UNSIGNED_BYTE, 37.17 + UserFmtShort = AL_SHORT, 37.18 + UserFmtUShort = AL_UNSIGNED_SHORT, 37.19 + UserFmtInt = AL_INT, 37.20 + UserFmtUInt = AL_UNSIGNED_INT, 37.21 + UserFmtFloat = AL_FLOAT, 37.22 + UserFmtDouble = AL_DOUBLE, 37.23 + UserFmtMulaw = AL_MULAW, 37.24 + UserFmtIMA4 = AL_IMA4, 37.25 + UserFmtByte3 = AL_BYTE3, 37.26 + UserFmtUByte3 = AL_UNSIGNED_BYTE3, 37.27 +}; 37.28 +enum UserFmtChannels { 37.29 + UserFmtMono = AL_MONO, 37.30 + UserFmtStereo = AL_STEREO, 37.31 + UserFmtRear = AL_REAR, 37.32 + UserFmtQuad = AL_QUAD, 37.33 + UserFmtX51 = AL_5POINT1, /* (WFX order) */ 37.34 + UserFmtX61 = AL_6POINT1, /* (WFX order) */ 37.35 + UserFmtX71 = AL_7POINT1 /* (WFX order) */ 37.36 +}; 37.37 + 37.38 +ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, 37.39 + enum UserFmtType *type); 37.40 +ALuint BytesFromUserFmt(enum UserFmtType type); 37.41 +ALuint ChannelsFromUserFmt(enum UserFmtChannels chans); 37.42 +static __inline ALuint FrameSizeFromUserFmt(enum UserFmtChannels chans, 37.43 + enum UserFmtType type) 37.44 +{ 37.45 + return ChannelsFromUserFmt(chans) * BytesFromUserFmt(type); 37.46 +} 37.47 + 37.48 + 37.49 +/* Storable formats */ 37.50 +enum FmtType { 37.51 + FmtByte = UserFmtByte, 37.52 + FmtShort = UserFmtShort, 37.53 + FmtFloat = UserFmtFloat, 37.54 +}; 37.55 +enum FmtChannels { 37.56 + FmtMono = UserFmtMono, 37.57 + FmtStereo = UserFmtStereo, 37.58 + FmtRear = UserFmtRear, 37.59 + FmtQuad = UserFmtQuad, 37.60 + FmtX51 = UserFmtX51, 37.61 + FmtX61 = UserFmtX61, 37.62 + FmtX71 = UserFmtX71, 37.63 +}; 37.64 + 37.65 +ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type); 37.66 +ALuint BytesFromFmt(enum FmtType type); 37.67 +ALuint ChannelsFromFmt(enum FmtChannels chans); 37.68 +static __inline ALuint FrameSizeFromFmt(enum FmtChannels chans, enum FmtType type) 37.69 +{ 37.70 + return ChannelsFromFmt(chans) * BytesFromFmt(type); 37.71 +} 37.72 + 37.73 + 37.74 +typedef struct ALbuffer 37.75 +{ 37.76 + ALvoid *data; 37.77 + ALsizei size; 37.78 + 37.79 + ALsizei Frequency; 37.80 + enum FmtChannels FmtChannels; 37.81 + enum FmtType FmtType; 37.82 + 37.83 + enum UserFmtChannels OriginalChannels; 37.84 + enum UserFmtType OriginalType; 37.85 + ALsizei OriginalSize; 37.86 + ALsizei OriginalAlign; 37.87 + 37.88 + ALsizei LoopStart; 37.89 + ALsizei LoopEnd; 37.90 + 37.91 + ALuint refcount; // Number of sources using this buffer (deletion can only occur when this is 0) 37.92 + 37.93 + // Index to itself 37.94 + ALuint buffer; 37.95 +} ALbuffer; 37.96 + 37.97 +ALvoid ReleaseALBuffers(ALCdevice *device); 37.98 + 37.99 +#ifdef __cplusplus 37.100 +} 37.101 +#endif 37.102 + 37.103 +#endif
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 38.2 +++ b/OpenAL32/Include/alEffect.h Tue Oct 25 13:02:31 2011 -0700 38.3 @@ -0,0 +1,93 @@ 38.4 +#ifndef _AL_EFFECT_H_ 38.5 +#define _AL_EFFECT_H_ 38.6 + 38.7 +#include "AL/al.h" 38.8 + 38.9 +#ifdef __cplusplus 38.10 +extern "C" { 38.11 +#endif 38.12 + 38.13 +enum { 38.14 + EAXREVERB = 0, 38.15 + REVERB, 38.16 + ECHO, 38.17 + MODULATOR, 38.18 + DEDICATED, 38.19 + 38.20 + MAX_EFFECTS 38.21 +}; 38.22 +extern ALboolean DisabledEffects[MAX_EFFECTS]; 38.23 + 38.24 +extern ALfloat ReverbBoost; 38.25 +extern ALboolean EmulateEAXReverb; 38.26 + 38.27 +typedef struct ALeffect 38.28 +{ 38.29 + // Effect type (AL_EFFECT_NULL, ...) 38.30 + ALenum type; 38.31 + 38.32 + union { 38.33 + struct { 38.34 + // Shared Reverb Properties 38.35 + ALfloat Density; 38.36 + ALfloat Diffusion; 38.37 + ALfloat Gain; 38.38 + ALfloat GainHF; 38.39 + ALfloat DecayTime; 38.40 + ALfloat DecayHFRatio; 38.41 + ALfloat ReflectionsGain; 38.42 + ALfloat ReflectionsDelay; 38.43 + ALfloat LateReverbGain; 38.44 + ALfloat LateReverbDelay; 38.45 + ALfloat AirAbsorptionGainHF; 38.46 + ALfloat RoomRolloffFactor; 38.47 + ALboolean DecayHFLimit; 38.48 + 38.49 + // Additional EAX Reverb Properties 38.50 + ALfloat GainLF; 38.51 + ALfloat DecayLFRatio; 38.52 + ALfloat ReflectionsPan[3]; 38.53 + ALfloat LateReverbPan[3]; 38.54 + ALfloat EchoTime; 38.55 + ALfloat EchoDepth; 38.56 + ALfloat ModulationTime; 38.57 + ALfloat ModulationDepth; 38.58 + ALfloat HFReference; 38.59 + ALfloat LFReference; 38.60 + } Reverb; 38.61 + 38.62 + struct { 38.63 + ALfloat Delay; 38.64 + ALfloat LRDelay; 38.65 + 38.66 + ALfloat Damping; 38.67 + ALfloat Feedback; 38.68 + 38.69 + ALfloat Spread; 38.70 + } Echo; 38.71 + 38.72 + struct { 38.73 + ALfloat Frequency; 38.74 + ALfloat HighPassCutoff; 38.75 + ALint Waveform; 38.76 + } Modulator; 38.77 + 38.78 + struct { 38.79 + ALfloat Gain; 38.80 + } Dedicated; 38.81 + } Params; 38.82 + 38.83 + // Index to itself 38.84 + ALuint effect; 38.85 +} ALeffect; 38.86 + 38.87 +static __inline ALboolean IsReverbEffect(ALenum type) 38.88 +{ return type == AL_EFFECT_REVERB || type == AL_EFFECT_EAXREVERB; } 38.89 + 38.90 +ALvoid ReleaseALEffects(ALCdevice *device); 38.91 + 38.92 +#ifdef __cplusplus 38.93 +} 38.94 +#endif 38.95 + 38.96 +#endif
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 39.2 +++ b/OpenAL32/Include/alError.h Tue Oct 25 13:02:31 2011 -0700 39.3 @@ -0,0 +1,17 @@ 39.4 +#ifndef _AL_ERROR_H_ 39.5 +#define _AL_ERROR_H_ 39.6 + 39.7 +#include "AL/al.h" 39.8 +#include "AL/alc.h" 39.9 + 39.10 +#ifdef __cplusplus 39.11 +extern "C" { 39.12 +#endif 39.13 + 39.14 +ALvoid alSetError(ALCcontext *Context, ALenum errorCode); 39.15 + 39.16 +#ifdef __cplusplus 39.17 +} 39.18 +#endif 39.19 + 39.20 +#endif
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 40.2 +++ b/OpenAL32/Include/alFilter.h Tue Oct 25 13:02:31 2011 -0700 40.3 @@ -0,0 +1,92 @@ 40.4 +#ifndef _AL_FILTER_H_ 40.5 +#define _AL_FILTER_H_ 40.6 + 40.7 +#include "AL/al.h" 40.8 +#include "alu.h" 40.9 + 40.10 +#ifdef __cplusplus 40.11 +extern "C" { 40.12 +#endif 40.13 + 40.14 +typedef struct { 40.15 + ALfloat coeff; 40.16 +#ifndef _MSC_VER 40.17 + ALfloat history[0]; 40.18 +#else 40.19 + ALfloat history[1]; 40.20 +#endif 40.21 +} FILTER; 40.22 + 40.23 +static __inline ALfloat lpFilter2P(FILTER *iir, ALuint offset, ALfloat input) 40.24 +{ 40.25 + ALfloat *history = &iir->history[offset*2]; 40.26 + ALfloat a = iir->coeff; 40.27 + ALfloat output = input; 40.28 + 40.29 + output = output + (history[0]-output)*a; 40.30 + history[0] = output; 40.31 + output = output + (history[1]-output)*a; 40.32 + history[1] = output; 40.33 + 40.34 + return output; 40.35 +} 40.36 +static __inline ALfloat lpFilter1P(FILTER *iir, ALuint offset, ALfloat input) 40.37 +{ 40.38 + ALfloat *history = &iir->history[offset]; 40.39 + ALfloat a = iir->coeff; 40.40 + ALfloat output = input; 40.41 + 40.42 + output = output + (history[0]-output)*a; 40.43 + history[0] = output; 40.44 + 40.45 + return output; 40.46 +} 40.47 + 40.48 +static __inline ALfloat lpFilter2PC(const FILTER *iir, ALuint offset, ALfloat input) 40.49 +{ 40.50 + const ALfloat *history = &iir->history[offset*2]; 40.51 + ALfloat a = iir->coeff; 40.52 + ALfloat output = input; 40.53 + 40.54 + output = output + (history[0]-output)*a; 40.55 + output = output + (history[1]-output)*a; 40.56 + 40.57 + return output; 40.58 +} 40.59 +static __inline ALfloat lpFilter1PC(FILTER *iir, ALuint offset, ALfloat input) 40.60 +{ 40.61 + const ALfloat *history = &iir->history[offset]; 40.62 + ALfloat a = iir->coeff; 40.63 + ALfloat output = input; 40.64 + 40.65 + output = output + (history[0]-output)*a; 40.66 + 40.67 + return output; 40.68 +} 40.69 + 40.70 +/* Calculates the low-pass filter coefficient given the pre-scaled gain and 40.71 + * cos(w) value. Note that g should be pre-scaled (sqr(gain) for one-pole, 40.72 + * sqrt(gain) for four-pole, etc) */ 40.73 +ALfloat lpCoeffCalc(ALfloat g, ALfloat cw); 40.74 + 40.75 + 40.76 +typedef struct ALfilter 40.77 +{ 40.78 + // Filter type (AL_FILTER_NULL, ...) 40.79 + ALenum type; 40.80 + 40.81 + ALfloat Gain; 40.82 + ALfloat GainHF; 40.83 + 40.84 + // Index to itself 40.85 + ALuint filter; 40.86 +} ALfilter; 40.87 + 40.88 + 40.89 +ALvoid ReleaseALFilters(ALCdevice *device); 40.90 + 40.91 +#ifdef __cplusplus 40.92 +} 40.93 +#endif 40.94 + 40.95 +#endif
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 41.2 +++ b/OpenAL32/Include/alListener.h Tue Oct 25 13:02:31 2011 -0700 41.3 @@ -0,0 +1,24 @@ 41.4 +#ifndef _AL_LISTENER_H_ 41.5 +#define _AL_LISTENER_H_ 41.6 + 41.7 +#include "AL/al.h" 41.8 + 41.9 +#ifdef __cplusplus 41.10 +extern "C" { 41.11 +#endif 41.12 + 41.13 +typedef struct ALlistener_struct 41.14 +{ 41.15 + ALfloat Position[3]; 41.16 + ALfloat Velocity[3]; 41.17 + ALfloat Forward[3]; 41.18 + ALfloat Up[3]; 41.19 + ALfloat Gain; 41.20 + ALfloat MetersPerUnit; 41.21 +} ALlistener; 41.22 + 41.23 +#ifdef __cplusplus 41.24 +} 41.25 +#endif 41.26 + 41.27 +#endif
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 42.2 +++ b/OpenAL32/Include/alMain.h Tue Oct 25 13:02:31 2011 -0700 42.3 @@ -0,0 +1,598 @@ 42.4 +#ifndef AL_MAIN_H 42.5 +#define AL_MAIN_H 42.6 + 42.7 +#include <string.h> 42.8 +#include <stdio.h> 42.9 +#include <stdarg.h> 42.10 + 42.11 +#ifdef HAVE_FENV_H 42.12 +#include <fenv.h> 42.13 +#endif 42.14 + 42.15 +#include "AL/al.h" 42.16 +#include "AL/alc.h" 42.17 +#include "AL/alext.h" 42.18 + 42.19 +#ifndef ALC_SOFT_device_loopback 42.20 +#define ALC_SOFT_device_loopback 1 42.21 +#define ALC_FORMAT_CHANNELS_SOFT 0x1990 42.22 +#define ALC_FORMAT_TYPE_SOFT 0x1991 42.23 + 42.24 +/* Sample types */ 42.25 +#define ALC_BYTE 0x1400 42.26 +#define ALC_UNSIGNED_BYTE 0x1401 42.27 +#define ALC_SHORT 0x1402 42.28 +#define ALC_UNSIGNED_SHORT 0x1403 42.29 +#define ALC_INT 0x1404 42.30 +#define ALC_UNSIGNED_INT 0x1405 42.31 +#define ALC_FLOAT 0x1406 42.32 + 42.33 +/* Channel configurations */ 42.34 +#define ALC_MONO 0x1500 42.35 +#define ALC_STEREO 0x1501 42.36 +#define ALC_QUAD 0x1503 42.37 +#define ALC_5POINT1 0x1504 /* (WFX order) */ 42.38 +#define ALC_6POINT1 0x1505 /* (WFX order) */ 42.39 +#define ALC_7POINT1 0x1506 /* (WFX order) */ 42.40 + 42.41 +typedef ALCdevice* (ALC_APIENTRY*LPALCLOOPBACKOPENDEVICESOFT)(void); 42.42 +typedef ALCboolean (ALC_APIENTRY*LPALCISRENDERFORMATSUPPORTEDSOFT)(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); 42.43 +typedef void (ALC_APIENTRY*LPALCRENDERSAMPLESSOFT)(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); 42.44 +#ifdef AL_ALEXT_PROTOTYPES 42.45 +ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(void); 42.46 +ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device, ALCsizei freq, ALCenum channels, ALCenum type); 42.47 +ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples); 42.48 +#endif 42.49 +#endif 42.50 + 42.51 +#ifndef AL_SOFT_buffer_samples 42.52 +#define AL_SOFT_buffer_samples 1 42.53 +/* Sample types */ 42.54 +#define AL_BYTE 0x1400 42.55 +#define AL_UNSIGNED_BYTE 0x1401 42.56 +#define AL_SHORT 0x1402 42.57 +#define AL_UNSIGNED_SHORT 0x1403 42.58 +#define AL_INT 0x1404 42.59 +#define AL_UNSIGNED_INT 0x1405 42.60 +#define AL_FLOAT 0x1406 42.61 +#define AL_DOUBLE 0x1407 42.62 +#define AL_BYTE3 0x1408 42.63 +#define AL_UNSIGNED_BYTE3 0x1409 42.64 +#define AL_MULAW 0x1410 42.65 +#define AL_IMA4 0x1411 42.66 + 42.67 +/* Channel configurations */ 42.68 +#define AL_MONO 0x1500 42.69 +#define AL_STEREO 0x1501 42.70 +#define AL_REAR 0x1502 42.71 +#define AL_QUAD 0x1503 42.72 +#define AL_5POINT1 0x1504 /* (WFX order) */ 42.73 +#define AL_6POINT1 0x1505 /* (WFX order) */ 42.74 +#define AL_7POINT1 0x1506 /* (WFX order) */ 42.75 + 42.76 +/* Storage formats */ 42.77 +#define AL_MONO8 0x1100 42.78 +#define AL_MONO16 0x1101 42.79 +#define AL_MONO32F 0x10010 42.80 +#define AL_STEREO8 0x1102 42.81 +#define AL_STEREO16 0x1103 42.82 +#define AL_STEREO32F 0x10011 42.83 +#define AL_QUAD8 0x1204 42.84 +#define AL_QUAD16 0x1205 42.85 +#define AL_QUAD32F 0x1206 42.86 +#define AL_REAR8 0x1207 42.87 +#define AL_REAR16 0x1208 42.88 +#define AL_REAR32F 0x1209 42.89 +#define AL_5POINT1_8 0x120A 42.90 +#define AL_5POINT1_16 0x120B 42.91 +#define AL_5POINT1_32F 0x120C 42.92 +#define AL_6POINT1_8 0x120D 42.93 +#define AL_6POINT1_16 0x120E 42.94 +#define AL_6POINT1_32F 0x120F 42.95 +#define AL_7POINT1_8 0x1210 42.96 +#define AL_7POINT1_16 0x1211 42.97 +#define AL_7POINT1_32F 0x1212 42.98 + 42.99 +typedef void (AL_APIENTRY*LPALBUFFERSAMPLESSOFT)(ALuint,ALuint,ALenum,ALsizei,ALenum,ALenum,const ALvoid*); 42.100 +typedef void (AL_APIENTRY*LPALBUFFERSUBSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,const ALvoid*); 42.101 +typedef void (AL_APIENTRY*LPALGETBUFFERSAMPLESSOFT)(ALuint,ALsizei,ALsizei,ALenum,ALenum,ALvoid*); 42.102 +typedef ALboolean (AL_APIENTRY*LPALISBUFFERFORMATSUPPORTEDSOFT)(ALenum); 42.103 +#ifdef AL_ALEXT_PROTOTYPES 42.104 +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, 42.105 + ALuint samplerate, ALenum internalformat, ALsizei frames, 42.106 + ALenum channels, ALenum type, const ALvoid *data); 42.107 +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, 42.108 + ALsizei offset, ALsizei frames, 42.109 + ALenum channels, ALenum type, const ALvoid *data); 42.110 +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, 42.111 + ALsizei offset, ALsizei frames, 42.112 + ALenum channels, ALenum type, ALvoid *data); 42.113 +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format); 42.114 +#endif 42.115 +#endif 42.116 + 42.117 +#ifndef AL_SOFT_non_virtual_channels 42.118 +#define AL_SOFT_non_virtual_channels 1 42.119 +#define AL_VIRTUAL_CHANNELS_SOFT 0x1033 42.120 +#endif 42.121 + 42.122 +#ifndef AL_SOFT_deferred_updates 42.123 +#define AL_SOFT_deferred_updates 1 42.124 +#define AL_DEFERRED_UPDATES_SOFT 0xC002 42.125 +typedef ALvoid (AL_APIENTRY*LPALDEFERUPDATESSOFT)(void); 42.126 +typedef ALvoid (AL_APIENTRY*LPALPROCESSUPDATESSOFT)(void); 42.127 +#ifdef AL_ALEXT_PROTOTYPES 42.128 +AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void); 42.129 +AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void); 42.130 +#endif 42.131 +#endif 42.132 + 42.133 + 42.134 +#if defined(HAVE_STDINT_H) 42.135 +#include <stdint.h> 42.136 +typedef int64_t ALint64; 42.137 +typedef uint64_t ALuint64; 42.138 +#elif defined(HAVE___INT64) 42.139 +typedef __int64 ALint64; 42.140 +typedef unsigned __int64 ALuint64; 42.141 +#elif (SIZEOF_LONG == 8) 42.142 +typedef long ALint64; 42.143 +typedef unsigned long ALuint64; 42.144 +#elif (SIZEOF_LONG_LONG == 8) 42.145 +typedef long long ALint64; 42.146 +typedef unsigned long long ALuint64; 42.147 +#endif 42.148 + 42.149 +typedef ptrdiff_t ALintptrEXT; 42.150 +typedef ptrdiff_t ALsizeiptrEXT; 42.151 + 42.152 +#ifdef HAVE_GCC_FORMAT 42.153 +#define PRINTF_STYLE(x, y) __attribute__((format(printf, (x), (y)))) 42.154 +#else 42.155 +#define PRINTF_STYLE(x, y) 42.156 +#endif 42.157 + 42.158 +#if defined(HAVE_RESTRICT) 42.159 +#define RESTRICT restrict 42.160 +#elif defined(HAVE___RESTRICT) 42.161 +#define RESTRICT __restrict 42.162 +#else 42.163 +#define RESTRICT 42.164 +#endif 42.165 + 42.166 +#ifdef _WIN32 42.167 + 42.168 +#ifndef _WIN32_WINNT 42.169 +#define _WIN32_WINNT 0x0500 42.170 +#endif 42.171 +#include <windows.h> 42.172 + 42.173 +typedef DWORD tls_type; 42.174 +#define tls_create(x) (*(x) = TlsAlloc()) 42.175 +#define tls_delete(x) TlsFree((x)) 42.176 +#define tls_get(x) TlsGetValue((x)) 42.177 +#define tls_set(x, a) TlsSetValue((x), (a)) 42.178 + 42.179 +#define HAVE_DYNLOAD 1 42.180 +void *LoadLib(const char *name); 42.181 +void CloseLib(void *handle); 42.182 +void *GetSymbol(void *handle, const char *name); 42.183 + 42.184 +typedef LONG pthread_once_t; 42.185 +#define PTHREAD_ONCE_INIT 0 42.186 +void pthread_once(pthread_once_t *once, void (*callback)(void)); 42.187 + 42.188 +#else 42.189 + 42.190 +#include <unistd.h> 42.191 +#include <assert.h> 42.192 +#include <pthread.h> 42.193 +#ifdef HAVE_PTHREAD_NP_H 42.194 +#include <pthread_np.h> 42.195 +#endif 42.196 +#include <sys/time.h> 42.197 +#include <time.h> 42.198 +#include <errno.h> 42.199 + 42.200 +#define IsBadWritePtr(a,b) ((a) == NULL && (b) != 0) 42.201 + 42.202 +typedef pthread_key_t tls_type; 42.203 +#define tls_create(x) pthread_key_create((x), NULL) 42.204 +#define tls_delete(x) pthread_key_delete((x)) 42.205 +#define tls_get(x) pthread_getspecific((x)) 42.206 +#define tls_set(x, a) pthread_setspecific((x), (a)) 42.207 + 42.208 +typedef pthread_mutex_t CRITICAL_SECTION; 42.209 +void InitializeCriticalSection(CRITICAL_SECTION *cs); 42.210 +void DeleteCriticalSection(CRITICAL_SECTION *cs); 42.211 +void EnterCriticalSection(CRITICAL_SECTION *cs); 42.212 +void LeaveCriticalSection(CRITICAL_SECTION *cs); 42.213 + 42.214 +ALuint timeGetTime(void); 42.215 + 42.216 +static __inline void Sleep(ALuint t) 42.217 +{ 42.218 + struct timespec tv, rem; 42.219 + tv.tv_nsec = (t*1000000)%1000000000; 42.220 + tv.tv_sec = t/1000; 42.221 + 42.222 + while(nanosleep(&tv, &rem) == -1 && errno == EINTR) 42.223 + tv = rem; 42.224 +} 42.225 + 42.226 +#if defined(HAVE_DLFCN_H) 42.227 +#define HAVE_DYNLOAD 1 42.228 +void *LoadLib(const char *name); 42.229 +void CloseLib(void *handle); 42.230 +void *GetSymbol(void *handle, const char *name); 42.231 +#endif 42.232 + 42.233 +#endif 42.234 + 42.235 +#include "alListener.h" 42.236 +#include "alu.h" 42.237 + 42.238 +#ifdef __cplusplus 42.239 +extern "C" { 42.240 +#endif 42.241 + 42.242 + 42.243 +#define DEFAULT_OUTPUT_RATE (44100) 42.244 + 42.245 +#define SPEEDOFSOUNDMETRESPERSEC (343.3f) 42.246 +#define AIRABSORBGAINHF (0.99426) /* -0.05dB */ 42.247 + 42.248 +#define LOWPASSFREQCUTOFF (5000) 42.249 + 42.250 + 42.251 +// Find the next power-of-2 for non-power-of-2 numbers. 42.252 +static __inline ALuint NextPowerOf2(ALuint value) 42.253 +{ 42.254 + ALuint powerOf2 = 1; 42.255 + 42.256 + if(value) 42.257 + { 42.258 + value--; 42.259 + while(value) 42.260 + { 42.261 + value >>= 1; 42.262 + powerOf2 <<= 1; 42.263 + } 42.264 + } 42.265 + return powerOf2; 42.266 +} 42.267 + 42.268 + 42.269 +enum DevProbe { 42.270 + DEVICE_PROBE, 42.271 + ALL_DEVICE_PROBE, 42.272 + CAPTURE_DEVICE_PROBE 42.273 +}; 42.274 + 42.275 +typedef struct { 42.276 + ALCboolean (*OpenPlayback)(ALCdevice*, const ALCchar*); 42.277 + void (*ClosePlayback)(ALCdevice*); 42.278 + ALCboolean (*ResetPlayback)(ALCdevice*); 42.279 + void (*StopPlayback)(ALCdevice*); 42.280 + 42.281 + ALCboolean (*OpenCapture)(ALCdevice*, const ALCchar*); 42.282 + void (*CloseCapture)(ALCdevice*); 42.283 + void (*StartCapture)(ALCdevice*); 42.284 + void (*StopCapture)(ALCdevice*); 42.285 + void (*CaptureSamples)(ALCdevice*, void*, ALCuint); 42.286 + ALCuint (*AvailableSamples)(ALCdevice*); 42.287 +} BackendFuncs; 42.288 + 42.289 +struct BackendInfo { 42.290 + const char *name; 42.291 + ALCboolean (*Init)(BackendFuncs*); 42.292 + void (*Deinit)(void); 42.293 + void (*Probe)(enum DevProbe); 42.294 + BackendFuncs Funcs; 42.295 +}; 42.296 + 42.297 +ALCboolean alc_alsa_init(BackendFuncs *func_list); 42.298 +void alc_alsa_deinit(void); 42.299 +void alc_alsa_probe(enum DevProbe type); 42.300 +ALCboolean alc_oss_init(BackendFuncs *func_list); 42.301 +void alc_oss_deinit(void); 42.302 +void alc_oss_probe(enum DevProbe type); 42.303 +ALCboolean alc_solaris_init(BackendFuncs *func_list); 42.304 +void alc_solaris_deinit(void); 42.305 +void alc_solaris_probe(enum DevProbe type); 42.306 +ALCboolean alc_sndio_init(BackendFuncs *func_list); 42.307 +void alc_sndio_deinit(void); 42.308 +void alc_sndio_probe(enum DevProbe type); 42.309 +ALCboolean alcMMDevApiInit(BackendFuncs *func_list); 42.310 +void alcMMDevApiDeinit(void); 42.311 +void alcMMDevApiProbe(enum DevProbe type); 42.312 +ALCboolean alcDSoundInit(BackendFuncs *func_list); 42.313 +void alcDSoundDeinit(void); 42.314 +void alcDSoundProbe(enum DevProbe type); 42.315 +ALCboolean alcWinMMInit(BackendFuncs *FuncList); 42.316 +void alcWinMMDeinit(void); 42.317 +void alcWinMMProbe(enum DevProbe type); 42.318 +ALCboolean alc_pa_init(BackendFuncs *func_list); 42.319 +void alc_pa_deinit(void); 42.320 +void alc_pa_probe(enum DevProbe type); 42.321 +ALCboolean alc_wave_init(BackendFuncs *func_list); 42.322 +void alc_wave_deinit(void); 42.323 +void alc_wave_probe(enum DevProbe type); 42.324 +ALCboolean alc_pulse_init(BackendFuncs *func_list); 42.325 +void alc_pulse_deinit(void); 42.326 +void alc_pulse_probe(enum DevProbe type); 42.327 +ALCboolean alc_ca_init(BackendFuncs *func_list); 42.328 +void alc_ca_deinit(void); 42.329 +void alc_ca_probe(enum DevProbe type); 42.330 +ALCboolean alc_opensl_init(BackendFuncs *func_list); 42.331 +void alc_opensl_deinit(void); 42.332 +void alc_opensl_probe(enum DevProbe type); 42.333 +ALCboolean alc_null_init(BackendFuncs *func_list); 42.334 +void alc_null_deinit(void); 42.335 +void alc_null_probe(enum DevProbe type); 42.336 +ALCboolean alc_loopback_init(BackendFuncs *func_list); 42.337 +void alc_loopback_deinit(void); 42.338 +void alc_loopback_probe(enum DevProbe type); 42.339 + 42.340 +//RLM: aurellem send device insertion 42.341 +ALCboolean alc_send_init(BackendFuncs *func_list); 42.342 +void alc_send_deinit(void); 42.343 +void alc_send_probe(enum DevProbe type); 42.344 + 42.345 + 42.346 +typedef struct UIntMap { 42.347 + struct { 42.348 + ALuint key; 42.349 + ALvoid *value; 42.350 + } *array; 42.351 + ALsizei size; 42.352 + ALsizei maxsize; 42.353 +} UIntMap; 42.354 + 42.355 +void InitUIntMap(UIntMap *map); 42.356 +void ResetUIntMap(UIntMap *map); 42.357 +ALenum InsertUIntMapEntry(UIntMap *map, ALuint key, ALvoid *value); 42.358 +void RemoveUIntMapKey(UIntMap *map, ALuint key); 42.359 +ALvoid *LookupUIntMapKey(UIntMap *map, ALuint key); 42.360 + 42.361 +/* Device formats */ 42.362 +enum DevFmtType { 42.363 + DevFmtByte = AL_BYTE, 42.364 + DevFmtUByte = AL_UNSIGNED_BYTE, 42.365 + DevFmtShort = AL_SHORT, 42.366 + DevFmtUShort = AL_UNSIGNED_SHORT, 42.367 + DevFmtFloat = AL_FLOAT 42.368 +}; 42.369 +enum DevFmtChannels { 42.370 + DevFmtMono = AL_MONO, 42.371 + DevFmtStereo = AL_STEREO, 42.372 + DevFmtQuad = AL_QUAD, 42.373 + DevFmtX51 = AL_5POINT1, 42.374 + DevFmtX61 = AL_6POINT1, 42.375 + DevFmtX71 = AL_7POINT1, 42.376 + 42.377 + /* Similar to 5.1, except using the side channels instead of back */ 42.378 + DevFmtX51Side = 0x80000000 | AL_5POINT1 42.379 +}; 42.380 + 42.381 +ALuint BytesFromDevFmt(enum DevFmtType type); 42.382 +ALuint ChannelsFromDevFmt(enum DevFmtChannels chans); 42.383 +static __inline ALuint FrameSizeFromDevFmt(enum DevFmtChannels chans, 42.384 + enum DevFmtType type) 42.385 +{ 42.386 + return ChannelsFromDevFmt(chans) * BytesFromDevFmt(type); 42.387 +} 42.388 + 42.389 + 42.390 +extern const struct EffectList { 42.391 + const char *name; 42.392 + int type; 42.393 + const char *ename; 42.394 + ALenum val; 42.395 +} EffectList[]; 42.396 + 42.397 + 42.398 +struct ALCdevice_struct 42.399 +{ 42.400 + ALCboolean Connected; 42.401 + ALboolean IsCaptureDevice; 42.402 + ALboolean IsLoopbackDevice; 42.403 + 42.404 + CRITICAL_SECTION Mutex; 42.405 + 42.406 + ALuint Frequency; 42.407 + ALuint UpdateSize; 42.408 + ALuint NumUpdates; 42.409 + enum DevFmtChannels FmtChans; 42.410 + enum DevFmtType FmtType; 42.411 + 42.412 + ALCchar *szDeviceName; 42.413 + 42.414 + ALCenum LastError; 42.415 + 42.416 + // Maximum number of sources that can be created 42.417 + ALuint MaxNoOfSources; 42.418 + // Maximum number of slots that can be created 42.419 + ALuint AuxiliaryEffectSlotMax; 42.420 + 42.421 + ALCuint NumMonoSources; 42.422 + ALCuint NumStereoSources; 42.423 + ALuint NumAuxSends; 42.424 + 42.425 + // Map of Buffers for this device 42.426 + UIntMap BufferMap; 42.427 + 42.428 + // Map of Effects for this device 42.429 + UIntMap EffectMap; 42.430 + 42.431 + // Map of Filters for this device 42.432 + UIntMap FilterMap; 42.433 + 42.434 + // Stereo-to-binaural filter 42.435 + struct bs2b *Bs2b; 42.436 + ALCint Bs2bLevel; 42.437 + 42.438 + // Device flags 42.439 + ALuint Flags; 42.440 + 42.441 + // Dry path buffer mix 42.442 + ALfloat DryBuffer[BUFFERSIZE][MAXCHANNELS]; 42.443 + 42.444 + enum Channel DevChannels[MAXCHANNELS]; 42.445 + 42.446 + enum Channel Speaker2Chan[MAXCHANNELS]; 42.447 + ALfloat PanningLUT[LUT_NUM][MAXCHANNELS]; 42.448 + ALuint NumChan; 42.449 + 42.450 + ALfloat ClickRemoval[MAXCHANNELS]; 42.451 + ALfloat PendingClicks[MAXCHANNELS]; 42.452 + 42.453 + // Contexts created on this device 42.454 + ALCcontext **Contexts; 42.455 + ALuint NumContexts; 42.456 + 42.457 + BackendFuncs *Funcs; 42.458 + void *ExtraData; // For the backend's use 42.459 + 42.460 + ALCdevice *next; 42.461 +}; 42.462 + 42.463 +#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b))) 42.464 +#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a))) 42.465 +#define ALCdevice_ResetPlayback(a) ((a)->Funcs->ResetPlayback((a))) 42.466 +#define ALCdevice_StopPlayback(a) ((a)->Funcs->StopPlayback((a))) 42.467 +#define ALCdevice_OpenCapture(a,b) ((a)->Funcs->OpenCapture((a), (b))) 42.468 +#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a))) 42.469 +#define ALCdevice_StartCapture(a) ((a)->Funcs->StartCapture((a))) 42.470 +#define ALCdevice_StopCapture(a) ((a)->Funcs->StopCapture((a))) 42.471 +#define ALCdevice_CaptureSamples(a,b,c) ((a)->Funcs->CaptureSamples((a), (b), (c))) 42.472 +#define ALCdevice_AvailableSamples(a) ((a)->Funcs->AvailableSamples((a))) 42.473 + 42.474 +// Duplicate stereo sources on the side/rear channels 42.475 +#define DEVICE_DUPLICATE_STEREO (1<<0) 42.476 +// Use HRTF filters for mixing sounds 42.477 +#define DEVICE_USE_HRTF (1<<1) 42.478 +// Frequency was requested by the app or config file 42.479 +#define DEVICE_FREQUENCY_REQUEST (1<<2) 42.480 +// Channel configuration was requested by the config file 42.481 +#define DEVICE_CHANNELS_REQUEST (1<<3) 42.482 + 42.483 +// Specifies if the device is currently running 42.484 +#define DEVICE_RUNNING (1<<31) 42.485 + 42.486 +struct ALCcontext_struct 42.487 +{ 42.488 + ALlistener Listener; 42.489 + 42.490 + UIntMap SourceMap; 42.491 + UIntMap EffectSlotMap; 42.492 + 42.493 + ALenum LastError; 42.494 + 42.495 + ALboolean UpdateSources; 42.496 + 42.497 + enum DistanceModel DistanceModel; 42.498 + ALboolean SourceDistanceModel; 42.499 + 42.500 + ALfloat DopplerFactor; 42.501 + ALfloat DopplerVelocity; 42.502 + ALfloat flSpeedOfSound; 42.503 + ALboolean DeferUpdates; 42.504 + 42.505 + struct ALsource **ActiveSources; 42.506 + ALsizei ActiveSourceCount; 42.507 + ALsizei MaxActiveSources; 42.508 + 42.509 + ALCdevice *Device; 42.510 + const ALCchar *ExtensionList; 42.511 + 42.512 + ALCcontext *next; 42.513 +}; 42.514 + 42.515 +void AppendDeviceList(const ALCchar *name); 42.516 +void AppendAllDeviceList(const ALCchar *name); 42.517 +void AppendCaptureDeviceList(const ALCchar *name); 42.518 + 42.519 +ALCvoid alcSetError(ALCdevice *device, ALenum errorCode); 42.520 + 42.521 +ALCvoid LockDevice(ALCdevice *device); 42.522 +ALCvoid UnlockDevice(ALCdevice *device); 42.523 +ALCvoid LockContext(ALCcontext *context); 42.524 +ALCvoid UnlockContext(ALCcontext *context); 42.525 + 42.526 +ALvoid *StartThread(ALuint (*func)(ALvoid*), ALvoid *ptr); 42.527 +ALuint StopThread(ALvoid *thread); 42.528 + 42.529 +ALCcontext *GetLockedContext(void); 42.530 + 42.531 +typedef struct RingBuffer RingBuffer; 42.532 +RingBuffer *CreateRingBuffer(ALsizei frame_size, ALsizei length); 42.533 +void DestroyRingBuffer(RingBuffer *ring); 42.534 +ALsizei RingBufferSize(RingBuffer *ring); 42.535 +void WriteRingBuffer(RingBuffer *ring, const ALubyte *data, ALsizei len); 42.536 +void ReadRingBuffer(RingBuffer *ring, ALubyte *data, ALsizei len); 42.537 + 42.538 +void ReadALConfig(void); 42.539 +void FreeALConfig(void); 42.540 +int ConfigValueExists(const char *blockName, const char *keyName); 42.541 +const char *GetConfigValue(const char *blockName, const char *keyName, const char *def); 42.542 +int GetConfigValueInt(const char *blockName, const char *keyName, int def); 42.543 +float GetConfigValueFloat(const char *blockName, const char *keyName, float def); 42.544 +int GetConfigValueBool(const char *blockName, const char *keyName, int def); 42.545 + 42.546 +void SetRTPriority(void); 42.547 + 42.548 +void SetDefaultChannelOrder(ALCdevice *device); 42.549 +void SetDefaultWFXChannelOrder(ALCdevice *device); 42.550 + 42.551 +const ALCchar *DevFmtTypeString(enum DevFmtType type); 42.552 +const ALCchar *DevFmtChannelsString(enum DevFmtChannels chans); 42.553 + 42.554 +#define HRIR_BITS (5) 42.555 +#define HRIR_LENGTH (1<<HRIR_BITS) 42.556 +#define HRIR_MASK (HRIR_LENGTH-1) 42.557 +void InitHrtf(void); 42.558 +ALCboolean IsHrtfCompatible(ALCdevice *device); 42.559 +ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]); 42.560 +void GetLerpedHrtfCoeffs(ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays); 42.561 +ALuint GetMovingHrtfCoeffs(ALfloat elevation, ALfloat azimuth, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep); 42.562 + 42.563 +void al_print(const char *fname, unsigned int line, const char *fmt, ...) 42.564 + PRINTF_STYLE(3,4); 42.565 +#define AL_PRINT(...) al_print(__FILE__, __LINE__, __VA_ARGS__) 42.566 + 42.567 +extern FILE *LogFile; 42.568 +enum LogLevel { 42.569 + NoLog, 42.570 + LogError, 42.571 + LogWarning, 42.572 + LogTrace 42.573 +}; 42.574 +extern enum LogLevel LogLevel; 42.575 + 42.576 +#define TRACE(...) do { \ 42.577 + if(LogLevel >= LogTrace) \ 42.578 + AL_PRINT(__VA_ARGS__); \ 42.579 +} while(0) 42.580 + 42.581 +#define WARN(...) do { \ 42.582 + if(LogLevel >= LogWarning) \ 42.583 + AL_PRINT(__VA_ARGS__); \ 42.584 +} while(0) 42.585 + 42.586 +#define ERR(...) do { \ 42.587 + if(LogLevel >= LogError) \ 42.588 + AL_PRINT(__VA_ARGS__); \ 42.589 +} while(0) 42.590 + 42.591 + 42.592 +extern ALdouble ConeScale; 42.593 +extern ALdouble ZScale; 42.594 + 42.595 +extern ALint RTPrioLevel; 42.596 + 42.597 +#ifdef __cplusplus 42.598 +} 42.599 +#endif 42.600 + 42.601 +#endif
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 43.2 +++ b/OpenAL32/Include/alSource.h Tue Oct 25 13:02:31 2011 -0700 43.3 @@ -0,0 +1,142 @@ 43.4 +#ifndef _AL_SOURCE_H_ 43.5 +#define _AL_SOURCE_H_ 43.6 + 43.7 +#define MAX_SENDS 4 43.8 + 43.9 +#include "alFilter.h" 43.10 +#include "alu.h" 43.11 +#include "AL/al.h" 43.12 + 43.13 +#ifdef __cplusplus 43.14 +extern "C" { 43.15 +#endif 43.16 + 43.17 +#define SRC_HISTORY_BITS (6) 43.18 +#define SRC_HISTORY_LENGTH (1<<SRC_HISTORY_BITS) 43.19 +#define SRC_HISTORY_MASK (SRC_HISTORY_LENGTH-1) 43.20 + 43.21 +extern enum Resampler DefaultResampler; 43.22 + 43.23 +extern const ALsizei ResamplerPadding[RESAMPLER_MAX]; 43.24 +extern const ALsizei ResamplerPrePadding[RESAMPLER_MAX]; 43.25 + 43.26 + 43.27 +typedef struct ALbufferlistitem 43.28 +{ 43.29 + struct ALbuffer *buffer; 43.30 + struct ALbufferlistitem *next; 43.31 + struct ALbufferlistitem *prev; 43.32 +} ALbufferlistitem; 43.33 + 43.34 +typedef struct ALsource 43.35 +{ 43.36 + ALfloat flPitch; 43.37 + ALfloat flGain; 43.38 + ALfloat flOuterGain; 43.39 + ALfloat flMinGain; 43.40 + ALfloat flMaxGain; 43.41 + ALfloat flInnerAngle; 43.42 + ALfloat flOuterAngle; 43.43 + ALfloat flRefDistance; 43.44 + ALfloat flMaxDistance; 43.45 + ALfloat flRollOffFactor; 43.46 + ALfloat vPosition[3]; 43.47 + ALfloat vVelocity[3]; 43.48 + ALfloat vOrientation[3]; 43.49 + ALboolean bHeadRelative; 43.50 + ALboolean bLooping; 43.51 + enum DistanceModel DistanceModel; 43.52 + ALboolean VirtualChannels; 43.53 + 43.54 + enum Resampler Resampler; 43.55 + 43.56 + ALenum state; 43.57 + ALenum new_state; 43.58 + ALuint position; 43.59 + ALuint position_fraction; 43.60 + 43.61 + struct ALbuffer *Buffer; 43.62 + 43.63 + ALbufferlistitem *queue; // Linked list of buffers in queue 43.64 + ALuint BuffersInQueue; // Number of buffers in queue 43.65 + ALuint BuffersPlayed; // Number of buffers played on this loop 43.66 + 43.67 + ALfilter DirectFilter; 43.68 + 43.69 + struct { 43.70 + struct ALeffectslot *Slot; 43.71 + ALfilter WetFilter; 43.72 + } Send[MAX_SENDS]; 43.73 + 43.74 + ALboolean DryGainHFAuto; 43.75 + ALboolean WetGainAuto; 43.76 + ALboolean WetGainHFAuto; 43.77 + ALfloat OuterGainHF; 43.78 + 43.79 + ALfloat AirAbsorptionFactor; 43.80 + ALfloat RoomRolloffFactor; 43.81 + ALfloat DopplerFactor; 43.82 + 43.83 + ALint lOffset; 43.84 + ALint lOffsetType; 43.85 + 43.86 + // Source Type (Static, Streaming, or Undetermined) 43.87 + ALint lSourceType; 43.88 + 43.89 + ALuint NumChannels; 43.90 + ALuint SampleSize; 43.91 + 43.92 + /* HRTF info */ 43.93 + ALboolean HrtfMoving; 43.94 + ALuint HrtfCounter; 43.95 + ALfloat HrtfHistory[MAXCHANNELS][SRC_HISTORY_LENGTH]; 43.96 + ALfloat HrtfValues[MAXCHANNELS][HRIR_LENGTH][2]; 43.97 + ALuint HrtfOffset; 43.98 + 43.99 + /* Current target parameters used for mixing */ 43.100 + struct { 43.101 + MixerFunc DoMix; 43.102 + 43.103 + ALint Step; 43.104 + 43.105 + ALfloat HrtfGain; 43.106 + ALfloat HrtfDir[3]; 43.107 + ALfloat HrtfCoeffs[MAXCHANNELS][HRIR_LENGTH][2]; 43.108 + ALuint HrtfDelay[MAXCHANNELS][2]; 43.109 + ALfloat HrtfCoeffStep[HRIR_LENGTH][2]; 43.110 + ALint HrtfDelayStep[2]; 43.111 + 43.112 + /* A mixing matrix. First subscript is the channel number of the input 43.113 + * data (regardless of channel configuration) and the second is the 43.114 + * channel target (eg. FRONT_LEFT) */ 43.115 + ALfloat DryGains[MAXCHANNELS][MAXCHANNELS]; 43.116 + 43.117 + FILTER iirFilter; 43.118 + ALfloat history[MAXCHANNELS*2]; 43.119 + 43.120 + struct { 43.121 + struct ALeffectslot *Slot; 43.122 + ALfloat WetGain; 43.123 + FILTER iirFilter; 43.124 + ALfloat history[MAXCHANNELS]; 43.125 + } Send[MAX_SENDS]; 43.126 + } Params; 43.127 + ALboolean NeedsUpdate; 43.128 + 43.129 + ALvoid (*Update)(struct ALsource *self, const ALCcontext *context); 43.130 + 43.131 + // Index to itself 43.132 + ALuint source; 43.133 +} ALsource; 43.134 +#define ALsource_Update(s,a) ((s)->Update(s,a)) 43.135 + 43.136 +ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state); 43.137 +ALboolean ApplyOffset(ALsource *Source); 43.138 + 43.139 +ALvoid ReleaseALSources(ALCcontext *Context); 43.140 + 43.141 +#ifdef __cplusplus 43.142 +} 43.143 +#endif 43.144 + 43.145 +#endif
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 44.2 +++ b/OpenAL32/Include/alState.h Tue Oct 25 13:02:31 2011 -0700 44.3 @@ -0,0 +1,14 @@ 44.4 +#ifndef _AL_STATE_H_ 44.5 +#define _AL_STATE_H_ 44.6 + 44.7 +#include "AL/al.h" 44.8 + 44.9 +#ifdef __cplusplus 44.10 +extern "C" { 44.11 +#endif 44.12 + 44.13 +#ifdef __cplusplus 44.14 +} 44.15 +#endif 44.16 + 44.17 +#endif
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 45.2 +++ b/OpenAL32/Include/alThunk.h Tue Oct 25 13:02:31 2011 -0700 45.3 @@ -0,0 +1,20 @@ 45.4 +#ifndef ALTHUNK_H 45.5 +#define ALTHUNK_H 45.6 + 45.7 +#include "alMain.h" 45.8 + 45.9 +#ifdef __cplusplus 45.10 +extern "C" { 45.11 +#endif 45.12 + 45.13 +void ThunkInit(void); 45.14 +void ThunkExit(void); 45.15 +ALenum NewThunkEntry(ALuint *index); 45.16 +void FreeThunkEntry(ALuint index); 45.17 + 45.18 +#ifdef __cplusplus 45.19 +} 45.20 +#endif 45.21 + 45.22 +#endif //ALTHUNK_H 45.23 +
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 46.2 +++ b/OpenAL32/Include/alu.h Tue Oct 25 13:02:31 2011 -0700 46.3 @@ -0,0 +1,178 @@ 46.4 +#ifndef _ALU_H_ 46.5 +#define _ALU_H_ 46.6 + 46.7 +#include "AL/al.h" 46.8 +#include "AL/alc.h" 46.9 +#include "AL/alext.h" 46.10 + 46.11 +#include <limits.h> 46.12 +#include <math.h> 46.13 +#ifdef HAVE_FLOAT_H 46.14 +#include <float.h> 46.15 +#endif 46.16 +#ifdef HAVE_IEEEFP_H 46.17 +#include <ieeefp.h> 46.18 +#endif 46.19 + 46.20 +#ifndef M_PI 46.21 +#define M_PI 3.14159265358979323846 /* pi */ 46.22 +#define M_PI_2 1.57079632679489661923 /* pi/2 */ 46.23 +#endif 46.24 + 46.25 +#ifdef HAVE_POWF 46.26 +#define aluPow(x,y) (powf((x),(y))) 46.27 +#else 46.28 +#define aluPow(x,y) ((ALfloat)pow((double)(x),(double)(y))) 46.29 +#endif 46.30 + 46.31 +#ifdef HAVE_SQRTF 46.32 +#define aluSqrt(x) (sqrtf((x))) 46.33 +#else 46.34 +#define aluSqrt(x) ((ALfloat)sqrt((double)(x))) 46.35 +#endif 46.36 + 46.37 +#ifdef HAVE_ACOSF 46.38 +#define aluAcos(x) (acosf((x))) 46.39 +#else 46.40 +#define aluAcos(x) ((ALfloat)acos((double)(x))) 46.41 +#endif 46.42 + 46.43 +#ifdef HAVE_ATANF 46.44 +#define aluAtan(x) (atanf((x))) 46.45 +#else 46.46 +#define aluAtan(x) ((ALfloat)atan((double)(x))) 46.47 +#endif 46.48 + 46.49 +#ifdef HAVE_FABSF 46.50 +#define aluFabs(x) (fabsf((x))) 46.51 +#else 46.52 +#define aluFabs(x) ((ALfloat)fabs((double)(x))) 46.53 +#endif 46.54 + 46.55 +#define QUADRANT_NUM 128 46.56 +#define LUT_NUM (4 * QUADRANT_NUM) 46.57 + 46.58 +#ifdef __cplusplus 46.59 +extern "C" { 46.60 +#endif 46.61 + 46.62 +struct ALsource; 46.63 +struct ALbuffer; 46.64 + 46.65 +typedef ALvoid (*MixerFunc)(struct ALsource *self, ALCdevice *Device, 46.66 + const ALvoid *RESTRICT data, 46.67 + ALuint *DataPosInt, ALuint *DataPosFrac, 46.68 + ALuint OutPos, ALuint SamplesToDo, 46.69 + ALuint BufferSize); 46.70 + 46.71 +enum Resampler { 46.72 + POINT_RESAMPLER = 0, 46.73 + LINEAR_RESAMPLER, 46.74 + CUBIC_RESAMPLER, 46.75 + 46.76 + RESAMPLER_MAX, 46.77 + RESAMPLER_MIN = -1, 46.78 + RESAMPLER_DEFAULT = LINEAR_RESAMPLER 46.79 +}; 46.80 + 46.81 +enum Channel { 46.82 + FRONT_LEFT = 0, 46.83 + FRONT_RIGHT, 46.84 + FRONT_CENTER, 46.85 + LFE, 46.86 + BACK_LEFT, 46.87 + BACK_RIGHT, 46.88 + BACK_CENTER, 46.89 + SIDE_LEFT, 46.90 + SIDE_RIGHT, 46.91 + 46.92 + MAXCHANNELS 46.93 +}; 46.94 + 46.95 +enum DistanceModel { 46.96 + InverseDistanceClamped = AL_INVERSE_DISTANCE_CLAMPED, 46.97 + LinearDistanceClamped = AL_LINEAR_DISTANCE_CLAMPED, 46.98 + ExponentDistanceClamped = AL_EXPONENT_DISTANCE_CLAMPED, 46.99 + InverseDistance = AL_INVERSE_DISTANCE, 46.100 + LinearDistance = AL_LINEAR_DISTANCE, 46.101 + ExponentDistance = AL_EXPONENT_DISTANCE, 46.102 + DisableDistance = AL_NONE 46.103 +}; 46.104 + 46.105 +#define BUFFERSIZE 4096 46.106 + 46.107 +#define FRACTIONBITS (14) 46.108 +#define FRACTIONONE (1<<FRACTIONBITS) 46.109 +#define FRACTIONMASK (FRACTIONONE-1) 46.110 + 46.111 +/* Size for temporary stack storage of buffer data. Larger values need more 46.112 + * stack, while smaller values may need more iterations. The value needs to be 46.113 + * a sensible size, however, as it constrains the max stepping value used for 46.114 + * mixing. 46.115 + * The mixer requires being able to do two samplings per mixing loop. A 16KB 46.116 + * buffer can hold 512 sample frames for a 7.1 float buffer. With the cubic 46.117 + * resampler (which requires 3 padding sample frames), this limits the maximum 46.118 + * step to about 508. This means that buffer_freq*source_pitch cannot exceed 46.119 + * device_freq*508 for an 8-channel 32-bit buffer. */ 46.120 +#ifndef STACK_DATA_SIZE 46.121 +#define STACK_DATA_SIZE 16384 46.122 +#endif 46.123 + 46.124 + 46.125 +static __inline ALfloat minf(ALfloat a, ALfloat b) 46.126 +{ return ((a > b) ? b : a); } 46.127 +static __inline ALfloat maxf(ALfloat a, ALfloat b) 46.128 +{ return ((a > b) ? a : b); } 46.129 +static __inline ALfloat clampf(ALfloat val, ALfloat min, ALfloat max) 46.130 +{ return minf(max, maxf(min, val)); } 46.131 + 46.132 +static __inline ALuint minu(ALuint a, ALuint b) 46.133 +{ return ((a > b) ? b : a); } 46.134 +static __inline ALuint maxu(ALuint a, ALuint b) 46.135 +{ return ((a > b) ? a : b); } 46.136 +static __inline ALuint clampu(ALuint val, ALuint min, ALuint max) 46.137 +{ return minu(max, maxu(min, val)); } 46.138 + 46.139 +static __inline ALint mini(ALint a, ALint b) 46.140 +{ return ((a > b) ? b : a); } 46.141 +static __inline ALint maxi(ALint a, ALint b) 46.142 +{ return ((a > b) ? a : b); } 46.143 +static __inline ALint clampi(ALint val, ALint min, ALint max) 46.144 +{ return mini(max, maxi(min, val)); } 46.145 + 46.146 + 46.147 +static __inline ALdouble lerp(ALdouble val1, ALdouble val2, ALdouble mu) 46.148 +{ 46.149 + return val1 + (val2-val1)*mu; 46.150 +} 46.151 +static __inline ALdouble cubic(ALdouble val0, ALdouble val1, ALdouble val2, ALdouble val3, ALdouble mu) 46.152 +{ 46.153 + ALdouble mu2 = mu*mu; 46.154 + ALdouble a0 = -0.5*val0 + 1.5*val1 + -1.5*val2 + 0.5*val3; 46.155 + ALdouble a1 = val0 + -2.5*val1 + 2.0*val2 + -0.5*val3; 46.156 + ALdouble a2 = -0.5*val0 + 0.5*val2; 46.157 + ALdouble a3 = val1; 46.158 + 46.159 + return a0*mu*mu2 + a1*mu2 + a2*mu + a3; 46.160 +} 46.161 + 46.162 +ALvoid aluInitPanning(ALCdevice *Device); 46.163 +ALint aluCart2LUTpos(ALfloat re, ALfloat im); 46.164 + 46.165 +ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext); 46.166 +ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext); 46.167 + 46.168 +MixerFunc SelectMixer(struct ALbuffer *Buffer, enum Resampler Resampler); 46.169 +MixerFunc SelectHrtfMixer(struct ALbuffer *Buffer, enum Resampler Resampler); 46.170 + 46.171 +ALvoid MixSource(struct ALsource *Source, ALCdevice *Device, ALuint SamplesToDo); 46.172 + 46.173 +ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size); 46.174 +ALvoid aluHandleDisconnect(ALCdevice *device); 46.175 + 46.176 +#ifdef __cplusplus 46.177 +} 46.178 +#endif 46.179 + 46.180 +#endif 46.181 +
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 47.2 +++ b/OpenAL32/Include/bs2b.h Tue Oct 25 13:02:31 2011 -0700 47.3 @@ -0,0 +1,109 @@ 47.4 +/*- 47.5 + * Copyright (c) 2005 Boris Mikhaylov 47.6 + * 47.7 + * Permission is hereby granted, free of charge, to any person obtaining 47.8 + * a copy of this software and associated documentation files (the 47.9 + * "Software"), to deal in the Software without restriction, including 47.10 + * without limitation the rights to use, copy, modify, merge, publish, 47.11 + * distribute, sublicense, and/or sell copies of the Software, and to 47.12 + * permit persons to whom the Software is furnished to do so, subject to 47.13 + * the following conditions: 47.14 + * 47.15 + * The above copyright notice and this permission notice shall be 47.16 + * included in all copies or substantial portions of the Software. 47.17 + * 47.18 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 47.19 + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 47.20 + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 47.21 + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 47.22 + * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 47.23 + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 47.24 + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 47.25 + */ 47.26 + 47.27 +#ifndef BS2B_H 47.28 +#define BS2B_H 47.29 + 47.30 +/* Number of crossfeed levels */ 47.31 +#define BS2B_CLEVELS 3 47.32 + 47.33 +/* Normal crossfeed levels */ 47.34 +#define BS2B_HIGH_CLEVEL 3 47.35 +#define BS2B_MIDDLE_CLEVEL 2 47.36 +#define BS2B_LOW_CLEVEL 1 47.37 + 47.38 +/* Easy crossfeed levels */ 47.39 +#define BS2B_HIGH_ECLEVEL BS2B_HIGH_CLEVEL + BS2B_CLEVELS 47.40 +#define BS2B_MIDDLE_ECLEVEL BS2B_MIDDLE_CLEVEL + BS2B_CLEVELS 47.41 +#define BS2B_LOW_ECLEVEL BS2B_LOW_CLEVEL + BS2B_CLEVELS 47.42 + 47.43 +/* Default crossfeed levels */ 47.44 +#define BS2B_DEFAULT_CLEVEL BS2B_HIGH_ECLEVEL 47.45 +/* Default sample rate (Hz) */ 47.46 +#define BS2B_DEFAULT_SRATE 44100 47.47 + 47.48 +#ifdef __cplusplus 47.49 +extern "C" { 47.50 +#endif /* __cplusplus */ 47.51 + 47.52 +struct bs2b { 47.53 + int level; /* Crossfeed level */ 47.54 + int srate; /* Sample rate (Hz) */ 47.55 + 47.56 + /* Lowpass IIR filter coefficients */ 47.57 + double a0_lo; 47.58 + double b1_lo; 47.59 + 47.60 + /* Highboost IIR filter coefficients */ 47.61 + double a0_hi; 47.62 + double a1_hi; 47.63 + double b1_hi; 47.64 + 47.65 + /* Global gain against overloading */ 47.66 + double gain; 47.67 + 47.68 + /* Buffer of last filtered sample. 47.69 + * [0] - first channel, [1] - second channel 47.70 + */ 47.71 + struct t_last_sample { 47.72 + double asis[2]; 47.73 + double lo[2]; 47.74 + double hi[2]; 47.75 + } last_sample; 47.76 +}; 47.77 + 47.78 +/* Clear buffers and set new coefficients with new crossfeed level value. 47.79 + * level - crossfeed level of *LEVEL values. 47.80 + */ 47.81 +void bs2b_set_level(struct bs2b *bs2b, int level); 47.82 + 47.83 +/* Return current crossfeed level value */ 47.84 +int bs2b_get_level(struct bs2b *bs2b); 47.85 + 47.86 +/* Clear buffers and set new coefficients with new sample rate value. 47.87 + * srate - sample rate by Hz. 47.88 + */ 47.89 +void bs2b_set_srate(struct bs2b *bs2b, int srate); 47.90 + 47.91 +/* Return current sample rate value */ 47.92 +int bs2b_get_srate(struct bs2b *bs2b); 47.93 + 47.94 +/* Clear buffer */ 47.95 +void bs2b_clear(struct bs2b *bs2b); 47.96 + 47.97 +/* Return 1 if buffer is clear */ 47.98 +int bs2b_is_clear(struct bs2b *bs2b); 47.99 + 47.100 +/* Crossfeeds one stereo sample that are pointed by sample. 47.101 + * [0] - first channel, [1] - second channel. 47.102 + * Returns crossfided samle by sample pointer. 47.103 + */ 47.104 + 47.105 +/* sample poits to floats */ 47.106 +void bs2b_cross_feed(struct bs2b *bs2b, float *sample); 47.107 + 47.108 +#ifdef __cplusplus 47.109 +} /* extern "C" */ 47.110 +#endif /* __cplusplus */ 47.111 + 47.112 +#endif /* BS2B_H */
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 48.2 +++ b/OpenAL32/Include/com_aurellem_capture_AudioSend.h Tue Oct 25 13:02:31 2011 -0700 48.3 @@ -0,0 +1,63 @@ 48.4 +/* DO NOT EDIT THIS FILE - it is machine generated */ 48.5 +#include <jni.h> 48.6 +/* Header for class com_aurellem_capture_AudioSend */ 48.7 + 48.8 +#ifndef _Included_com_aurellem_capture_AudioSend 48.9 +#define _Included_com_aurellem_capture_AudioSend 48.10 +#ifdef __cplusplus 48.11 +extern "C" { 48.12 +#endif 48.13 +#undef com_aurellem_capture_AudioSend_BYTES_PER_SAMPLE 48.14 +#define com_aurellem_capture_AudioSend_BYTES_PER_SAMPLE 4L 48.15 +/* 48.16 + * Class: com_aurellem_capture_AudioSend 48.17 + * Method: ninitDevice 48.18 + * Signature: (J)V 48.19 + */ 48.20 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_ninitDevice 48.21 + (JNIEnv *, jclass, jlong); 48.22 + 48.23 +/* 48.24 + * Class: com_aurellem_capture_AudioSend 48.25 + * Method: nstep 48.26 + * Signature: (JI)V 48.27 + */ 48.28 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_nstep 48.29 + (JNIEnv *, jclass, jlong, jint); 48.30 + 48.31 +/* 48.32 + * Class: com_aurellem_capture_AudioSend 48.33 + * Method: ngetSamples 48.34 + * Signature: (JLjava/nio/ByteBuffer;III)V 48.35 + */ 48.36 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_ngetSamples 48.37 + (JNIEnv *, jclass, jlong, jobject, jint, jint, jint); 48.38 + 48.39 +/* 48.40 + * Class: com_aurellem_capture_AudioSend 48.41 + * Method: naddListener 48.42 + * Signature: (J)V 48.43 + */ 48.44 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_naddListener 48.45 + (JNIEnv *, jclass, jlong); 48.46 + 48.47 +/* 48.48 + * Class: com_aurellem_capture_AudioSend 48.49 + * Method: nsetNthListener3f 48.50 + * Signature: (IFFFJI)V 48.51 + */ 48.52 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_nsetNthListener3f 48.53 + (JNIEnv *, jclass, jint, jfloat, jfloat, jfloat, jlong, jint); 48.54 + 48.55 +/* 48.56 + * Class: com_aurellem_capture_AudioSend 48.57 + * Method: nsetNthListenerf 48.58 + * Signature: (IFJI)V 48.59 + */ 48.60 +JNIEXPORT void JNICALL Java_com_aurellem_capture_AudioSend_nsetNthListenerf 48.61 + (JNIEnv *, jclass, jint, jfloat, jlong, jint); 48.62 + 48.63 +#ifdef __cplusplus 48.64 +} 48.65 +#endif 48.66 +#endif
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 49.2 +++ b/OpenAL32/alAuxEffectSlot.c Tue Oct 25 13:02:31 2011 -0700 49.3 @@ -0,0 +1,540 @@ 49.4 +/** 49.5 + * OpenAL cross platform audio library 49.6 + * Copyright (C) 1999-2007 by authors. 49.7 + * This library is free software; you can redistribute it and/or 49.8 + * modify it under the terms of the GNU Library General Public 49.9 + * License as published by the Free Software Foundation; either 49.10 + * version 2 of the License, or (at your option) any later version. 49.11 + * 49.12 + * This library is distributed in the hope that it will be useful, 49.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 49.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 49.15 + * Library General Public License for more details. 49.16 + * 49.17 + * You should have received a copy of the GNU Library General Public 49.18 + * License along with this library; if not, write to the 49.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 49.20 + * Boston, MA 02111-1307, USA. 49.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 49.22 + */ 49.23 + 49.24 +#include "config.h" 49.25 + 49.26 +#include <stdlib.h> 49.27 +#include <math.h> 49.28 + 49.29 +#include "AL/al.h" 49.30 +#include "AL/alc.h" 49.31 +#include "alMain.h" 49.32 +#include "alAuxEffectSlot.h" 49.33 +#include "alThunk.h" 49.34 +#include "alError.h" 49.35 +#include "alSource.h" 49.36 + 49.37 + 49.38 +static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect); 49.39 + 49.40 +#define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k))) 49.41 +#define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k))) 49.42 + 49.43 +AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) 49.44 +{ 49.45 + ALCcontext *Context; 49.46 + ALCdevice *Device; 49.47 + 49.48 + Context = GetLockedContext(); 49.49 + if(!Context) return; 49.50 + 49.51 + Device = Context->Device; 49.52 + if(n < 0 || IsBadWritePtr((void*)effectslots, n * sizeof(ALuint))) 49.53 + alSetError(Context, AL_INVALID_VALUE); 49.54 + else if((ALuint)n > Device->AuxiliaryEffectSlotMax - Context->EffectSlotMap.size) 49.55 + alSetError(Context, AL_INVALID_VALUE); 49.56 + else 49.57 + { 49.58 + ALenum err; 49.59 + ALsizei i, j; 49.60 + 49.61 + i = 0; 49.62 + while(i < n) 49.63 + { 49.64 + ALeffectslot *slot = calloc(1, sizeof(ALeffectslot)); 49.65 + if(!slot || !(slot->EffectState=NoneCreate())) 49.66 + { 49.67 + free(slot); 49.68 + // We must have run out or memory 49.69 + alSetError(Context, AL_OUT_OF_MEMORY); 49.70 + alDeleteAuxiliaryEffectSlots(i, effectslots); 49.71 + break; 49.72 + } 49.73 + 49.74 + err = NewThunkEntry(&slot->effectslot); 49.75 + if(err == AL_NO_ERROR) 49.76 + err = InsertUIntMapEntry(&Context->EffectSlotMap, slot->effectslot, slot); 49.77 + if(err != AL_NO_ERROR) 49.78 + { 49.79 + FreeThunkEntry(slot->effectslot); 49.80 + ALEffect_Destroy(slot->EffectState); 49.81 + free(slot); 49.82 + 49.83 + alSetError(Context, err); 49.84 + alDeleteAuxiliaryEffectSlots(i, effectslots); 49.85 + break; 49.86 + } 49.87 + 49.88 + effectslots[i++] = slot->effectslot; 49.89 + 49.90 + slot->Gain = 1.0; 49.91 + slot->AuxSendAuto = AL_TRUE; 49.92 + slot->NeedsUpdate = AL_FALSE; 49.93 + for(j = 0;j < BUFFERSIZE;j++) 49.94 + slot->WetBuffer[j] = 0.0f; 49.95 + for(j = 0;j < 1;j++) 49.96 + { 49.97 + slot->ClickRemoval[j] = 0.0f; 49.98 + slot->PendingClicks[j] = 0.0f; 49.99 + } 49.100 + slot->refcount = 0; 49.101 + } 49.102 + } 49.103 + 49.104 + UnlockContext(Context); 49.105 +} 49.106 + 49.107 +AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots) 49.108 +{ 49.109 + ALCcontext *Context; 49.110 + ALeffectslot *EffectSlot; 49.111 + ALboolean SlotsValid = AL_FALSE; 49.112 + ALsizei i; 49.113 + 49.114 + Context = GetLockedContext(); 49.115 + if(!Context) return; 49.116 + 49.117 + if(n < 0) 49.118 + alSetError(Context, AL_INVALID_VALUE); 49.119 + else 49.120 + { 49.121 + SlotsValid = AL_TRUE; 49.122 + // Check that all effectslots are valid 49.123 + for(i = 0;i < n;i++) 49.124 + { 49.125 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL) 49.126 + { 49.127 + alSetError(Context, AL_INVALID_NAME); 49.128 + SlotsValid = AL_FALSE; 49.129 + break; 49.130 + } 49.131 + else if(EffectSlot->refcount > 0) 49.132 + { 49.133 + alSetError(Context, AL_INVALID_NAME); 49.134 + SlotsValid = AL_FALSE; 49.135 + break; 49.136 + } 49.137 + } 49.138 + } 49.139 + 49.140 + if(SlotsValid) 49.141 + { 49.142 + // All effectslots are valid 49.143 + for(i = 0;i < n;i++) 49.144 + { 49.145 + // Recheck that the effectslot is valid, because there could be duplicated names 49.146 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslots[i])) == NULL) 49.147 + continue; 49.148 + 49.149 + ALEffect_Destroy(EffectSlot->EffectState); 49.150 + 49.151 + RemoveUIntMapKey(&Context->EffectSlotMap, EffectSlot->effectslot); 49.152 + FreeThunkEntry(EffectSlot->effectslot); 49.153 + 49.154 + memset(EffectSlot, 0, sizeof(ALeffectslot)); 49.155 + free(EffectSlot); 49.156 + } 49.157 + } 49.158 + 49.159 + UnlockContext(Context); 49.160 +} 49.161 + 49.162 +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot) 49.163 +{ 49.164 + ALCcontext *Context; 49.165 + ALboolean result; 49.166 + 49.167 + Context = GetLockedContext(); 49.168 + if(!Context) return AL_FALSE; 49.169 + 49.170 + result = (LookupEffectSlot(Context->EffectSlotMap, effectslot) ? 49.171 + AL_TRUE : AL_FALSE); 49.172 + 49.173 + UnlockContext(Context); 49.174 + 49.175 + return result; 49.176 +} 49.177 + 49.178 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue) 49.179 +{ 49.180 + ALCdevice *Device; 49.181 + ALCcontext *Context; 49.182 + ALeffectslot *EffectSlot; 49.183 + 49.184 + Context = GetLockedContext(); 49.185 + if(!Context) return; 49.186 + 49.187 + Device = Context->Device; 49.188 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 49.189 + { 49.190 + switch(param) 49.191 + { 49.192 + case AL_EFFECTSLOT_EFFECT: { 49.193 + ALeffect *effect = NULL; 49.194 + 49.195 + if(iValue == 0 || 49.196 + (effect=LookupEffect(Device->EffectMap, iValue)) != NULL) 49.197 + { 49.198 + InitializeEffect(Context, EffectSlot, effect); 49.199 + Context->UpdateSources = AL_TRUE; 49.200 + } 49.201 + else 49.202 + alSetError(Context, AL_INVALID_VALUE); 49.203 + } break; 49.204 + 49.205 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 49.206 + if(iValue == AL_TRUE || iValue == AL_FALSE) 49.207 + { 49.208 + EffectSlot->AuxSendAuto = iValue; 49.209 + Context->UpdateSources = AL_TRUE; 49.210 + } 49.211 + else 49.212 + alSetError(Context, AL_INVALID_VALUE); 49.213 + break; 49.214 + 49.215 + default: 49.216 + alSetError(Context, AL_INVALID_ENUM); 49.217 + break; 49.218 + } 49.219 + } 49.220 + else 49.221 + alSetError(Context, AL_INVALID_NAME); 49.222 + 49.223 + UnlockContext(Context); 49.224 +} 49.225 + 49.226 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) 49.227 +{ 49.228 + ALCcontext *Context; 49.229 + 49.230 + switch(param) 49.231 + { 49.232 + case AL_EFFECTSLOT_EFFECT: 49.233 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 49.234 + alAuxiliaryEffectSloti(effectslot, param, piValues[0]); 49.235 + return; 49.236 + } 49.237 + 49.238 + Context = GetLockedContext(); 49.239 + if(!Context) return; 49.240 + 49.241 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 49.242 + { 49.243 + switch(param) 49.244 + { 49.245 + default: 49.246 + alSetError(Context, AL_INVALID_ENUM); 49.247 + break; 49.248 + } 49.249 + } 49.250 + else 49.251 + alSetError(Context, AL_INVALID_NAME); 49.252 + 49.253 + UnlockContext(Context); 49.254 +} 49.255 + 49.256 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue) 49.257 +{ 49.258 + ALCcontext *Context; 49.259 + ALeffectslot *EffectSlot; 49.260 + 49.261 + Context = GetLockedContext(); 49.262 + if(!Context) return; 49.263 + 49.264 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 49.265 + { 49.266 + switch(param) 49.267 + { 49.268 + case AL_EFFECTSLOT_GAIN: 49.269 + if(flValue >= 0.0f && flValue <= 1.0f) 49.270 + { 49.271 + EffectSlot->Gain = flValue; 49.272 + EffectSlot->NeedsUpdate = AL_TRUE; 49.273 + } 49.274 + else 49.275 + alSetError(Context, AL_INVALID_VALUE); 49.276 + break; 49.277 + 49.278 + default: 49.279 + alSetError(Context, AL_INVALID_ENUM); 49.280 + break; 49.281 + } 49.282 + } 49.283 + else 49.284 + alSetError(Context, AL_INVALID_NAME); 49.285 + 49.286 + UnlockContext(Context); 49.287 +} 49.288 + 49.289 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) 49.290 +{ 49.291 + ALCcontext *Context; 49.292 + 49.293 + switch(param) 49.294 + { 49.295 + case AL_EFFECTSLOT_GAIN: 49.296 + alAuxiliaryEffectSlotf(effectslot, param, pflValues[0]); 49.297 + return; 49.298 + } 49.299 + 49.300 + Context = GetLockedContext(); 49.301 + if(!Context) return; 49.302 + 49.303 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 49.304 + { 49.305 + switch(param) 49.306 + { 49.307 + default: 49.308 + alSetError(Context, AL_INVALID_ENUM); 49.309 + break; 49.310 + } 49.311 + } 49.312 + else 49.313 + alSetError(Context, AL_INVALID_NAME); 49.314 + 49.315 + UnlockContext(Context); 49.316 +} 49.317 + 49.318 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue) 49.319 +{ 49.320 + ALCcontext *Context; 49.321 + ALeffectslot *EffectSlot; 49.322 + 49.323 + Context = GetLockedContext(); 49.324 + if(!Context) return; 49.325 + 49.326 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 49.327 + { 49.328 + switch(param) 49.329 + { 49.330 + case AL_EFFECTSLOT_EFFECT: 49.331 + *piValue = EffectSlot->effect.effect; 49.332 + break; 49.333 + 49.334 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 49.335 + *piValue = EffectSlot->AuxSendAuto; 49.336 + break; 49.337 + 49.338 + default: 49.339 + alSetError(Context, AL_INVALID_ENUM); 49.340 + break; 49.341 + } 49.342 + } 49.343 + else 49.344 + alSetError(Context, AL_INVALID_NAME); 49.345 + 49.346 + UnlockContext(Context); 49.347 +} 49.348 + 49.349 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues) 49.350 +{ 49.351 + ALCcontext *Context; 49.352 + 49.353 + switch(param) 49.354 + { 49.355 + case AL_EFFECTSLOT_EFFECT: 49.356 + case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: 49.357 + alGetAuxiliaryEffectSloti(effectslot, param, piValues); 49.358 + return; 49.359 + } 49.360 + 49.361 + Context = GetLockedContext(); 49.362 + if(!Context) return; 49.363 + 49.364 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 49.365 + { 49.366 + switch(param) 49.367 + { 49.368 + default: 49.369 + alSetError(Context, AL_INVALID_ENUM); 49.370 + break; 49.371 + } 49.372 + } 49.373 + else 49.374 + alSetError(Context, AL_INVALID_NAME); 49.375 + 49.376 + UnlockContext(Context); 49.377 +} 49.378 + 49.379 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue) 49.380 +{ 49.381 + ALCcontext *Context; 49.382 + ALeffectslot *EffectSlot; 49.383 + 49.384 + Context = GetLockedContext(); 49.385 + if(!Context) return; 49.386 + 49.387 + if((EffectSlot=LookupEffectSlot(Context->EffectSlotMap, effectslot)) != NULL) 49.388 + { 49.389 + switch(param) 49.390 + { 49.391 + case AL_EFFECTSLOT_GAIN: 49.392 + *pflValue = EffectSlot->Gain; 49.393 + break; 49.394 + 49.395 + default: 49.396 + alSetError(Context, AL_INVALID_ENUM); 49.397 + break; 49.398 + } 49.399 + } 49.400 + else 49.401 + alSetError(Context, AL_INVALID_NAME); 49.402 + 49.403 + UnlockContext(Context); 49.404 +} 49.405 + 49.406 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues) 49.407 +{ 49.408 + ALCcontext *Context; 49.409 + 49.410 + switch(param) 49.411 + { 49.412 + case AL_EFFECTSLOT_GAIN: 49.413 + alGetAuxiliaryEffectSlotf(effectslot, param, pflValues); 49.414 + return; 49.415 + } 49.416 + 49.417 + Context = GetLockedContext(); 49.418 + if(!Context) return; 49.419 + 49.420 + if(LookupEffectSlot(Context->EffectSlotMap, effectslot) != NULL) 49.421 + { 49.422 + switch(param) 49.423 + { 49.424 + default: 49.425 + alSetError(Context, AL_INVALID_ENUM); 49.426 + break; 49.427 + } 49.428 + } 49.429 + else 49.430 + alSetError(Context, AL_INVALID_NAME); 49.431 + 49.432 + UnlockContext(Context); 49.433 +} 49.434 + 49.435 + 49.436 +static ALvoid NoneDestroy(ALeffectState *State) 49.437 +{ free(State); } 49.438 +static ALboolean NoneDeviceUpdate(ALeffectState *State, ALCdevice *Device) 49.439 +{ 49.440 + return AL_TRUE; 49.441 + (void)State; 49.442 + (void)Device; 49.443 +} 49.444 +static ALvoid NoneUpdate(ALeffectState *State, ALCcontext *Context, const ALeffectslot *Slot) 49.445 +{ 49.446 + (void)State; 49.447 + (void)Context; 49.448 + (void)Slot; 49.449 +} 49.450 +static ALvoid NoneProcess(ALeffectState *State, const ALeffectslot *Slot, ALuint SamplesToDo, const ALfloat *SamplesIn, ALfloat (*SamplesOut)[MAXCHANNELS]) 49.451 +{ 49.452 + (void)State; 49.453 + (void)Slot; 49.454 + (void)SamplesToDo; 49.455 + (void)SamplesIn; 49.456 + (void)SamplesOut; 49.457 +} 49.458 +ALeffectState *NoneCreate(void) 49.459 +{ 49.460 + ALeffectState *state; 49.461 + 49.462 + state = calloc(1, sizeof(*state)); 49.463 + if(!state) 49.464 + return NULL; 49.465 + 49.466 + state->Destroy = NoneDestroy; 49.467 + state->DeviceUpdate = NoneDeviceUpdate; 49.468 + state->Update = NoneUpdate; 49.469 + state->Process = NoneProcess; 49.470 + 49.471 + return state; 49.472 +} 49.473 + 49.474 +static ALvoid InitializeEffect(ALCcontext *Context, ALeffectslot *EffectSlot, ALeffect *effect) 49.475 +{ 49.476 + if(EffectSlot->effect.type != (effect?effect->type:AL_EFFECT_NULL)) 49.477 + { 49.478 + ALeffectState *NewState = NULL; 49.479 + if(!effect || effect->type == AL_EFFECT_NULL) 49.480 + NewState = NoneCreate(); 49.481 + else if(effect->type == AL_EFFECT_EAXREVERB) 49.482 + NewState = EAXVerbCreate(); 49.483 + else if(effect->type == AL_EFFECT_REVERB) 49.484 + NewState = VerbCreate(); 49.485 + else if(effect->type == AL_EFFECT_ECHO) 49.486 + NewState = EchoCreate(); 49.487 + else if(effect->type == AL_EFFECT_RING_MODULATOR) 49.488 + NewState = ModulatorCreate(); 49.489 + else if(effect->type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT) 49.490 + NewState = DedicatedLFECreate(); 49.491 + else if(effect->type == AL_EFFECT_DEDICATED_DIALOGUE) 49.492 + NewState = DedicatedDLGCreate(); 49.493 + /* No new state? An error occured.. */ 49.494 + if(NewState == NULL || 49.495 + ALEffect_DeviceUpdate(NewState, Context->Device) == AL_FALSE) 49.496 + { 49.497 + if(NewState) 49.498 + ALEffect_Destroy(NewState); 49.499 + alSetError(Context, AL_OUT_OF_MEMORY); 49.500 + return; 49.501 + } 49.502 + if(EffectSlot->EffectState) 49.503 + ALEffect_Destroy(EffectSlot->EffectState); 49.504 + EffectSlot->EffectState = NewState; 49.505 + 49.506 + if(!effect) 49.507 + memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect)); 49.508 + else 49.509 + memcpy(&EffectSlot->effect, effect, sizeof(*effect)); 49.510 + /* FIXME: This should be done asychronously, but since the EfefctState 49.511 + * object was changed, it needs an update before its Process method can 49.512 + * be called (coming changes may not guarantee an update when the 49.513 + * NeedsUpdate flag is set). */ 49.514 + EffectSlot->NeedsUpdate = AL_FALSE; 49.515 + ALEffect_Update(EffectSlot->EffectState, Context, EffectSlot); 49.516 + } 49.517 + else 49.518 + { 49.519 + if(!effect) 49.520 + memset(&EffectSlot->effect, 0, sizeof(EffectSlot->effect)); 49.521 + else 49.522 + memcpy(&EffectSlot->effect, effect, sizeof(*effect)); 49.523 + EffectSlot->NeedsUpdate = AL_TRUE; 49.524 + } 49.525 +} 49.526 + 49.527 + 49.528 +ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context) 49.529 +{ 49.530 + ALsizei pos; 49.531 + for(pos = 0;pos < Context->EffectSlotMap.size;pos++) 49.532 + { 49.533 + ALeffectslot *temp = Context->EffectSlotMap.array[pos].value; 49.534 + Context->EffectSlotMap.array[pos].value = NULL; 49.535 + 49.536 + // Release effectslot structure 49.537 + ALEffect_Destroy(temp->EffectState); 49.538 + 49.539 + FreeThunkEntry(temp->effectslot); 49.540 + memset(temp, 0, sizeof(ALeffectslot)); 49.541 + free(temp); 49.542 + } 49.543 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 50.2 +++ b/OpenAL32/alBuffer.c Tue Oct 25 13:02:31 2011 -0700 50.3 @@ -0,0 +1,2211 @@ 50.4 +/** 50.5 + * OpenAL cross platform audio library 50.6 + * Copyright (C) 1999-2007 by authors. 50.7 + * This library is free software; you can redistribute it and/or 50.8 + * modify it under the terms of the GNU Library General Public 50.9 + * License as published by the Free Software Foundation; either 50.10 + * version 2 of the License, or (at your option) any later version. 50.11 + * 50.12 + * This library is distributed in the hope that it will be useful, 50.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 50.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 50.15 + * Library General Public License for more details. 50.16 + * 50.17 + * You should have received a copy of the GNU Library General Public 50.18 + * License along with this library; if not, write to the 50.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 50.20 + * Boston, MA 02111-1307, USA. 50.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 50.22 + */ 50.23 + 50.24 +#include "config.h" 50.25 + 50.26 +#include <stdlib.h> 50.27 +#include <stdio.h> 50.28 +#include <assert.h> 50.29 +#include <limits.h> 50.30 + 50.31 +#include "alMain.h" 50.32 +#include "AL/al.h" 50.33 +#include "AL/alc.h" 50.34 +#include "alError.h" 50.35 +#include "alBuffer.h" 50.36 +#include "alThunk.h" 50.37 + 50.38 + 50.39 +static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels chans, enum UserFmtType type, const ALvoid *data, ALboolean storesrc); 50.40 +static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len); 50.41 +static ALboolean IsValidType(ALenum type); 50.42 +static ALboolean IsValidChannels(ALenum channels); 50.43 + 50.44 +#define LookupBuffer(m, k) ((ALbuffer*)LookupUIntMapKey(&(m), (k))) 50.45 + 50.46 + 50.47 +/* 50.48 + * Global Variables 50.49 + */ 50.50 + 50.51 +/* IMA ADPCM Stepsize table */ 50.52 +static const long IMAStep_size[89] = { 50.53 + 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 50.54 + 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 50.55 + 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 50.56 + 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 50.57 + 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 50.58 + 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 50.59 + 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442, 50.60 + 11487,12635,13899,15289,16818,18500,20350,22358,24633,27086,29794, 50.61 + 32767 50.62 +}; 50.63 + 50.64 +/* IMA4 ADPCM Codeword decode table */ 50.65 +static const long IMA4Codeword[16] = { 50.66 + 1, 3, 5, 7, 9, 11, 13, 15, 50.67 + -1,-3,-5,-7,-9,-11,-13,-15, 50.68 +}; 50.69 + 50.70 +/* IMA4 ADPCM Step index adjust decode table */ 50.71 +static const long IMA4Index_adjust[16] = { 50.72 + -1,-1,-1,-1, 2, 4, 6, 8, 50.73 + -1,-1,-1,-1, 2, 4, 6, 8 50.74 +}; 50.75 + 50.76 +/* A quick'n'dirty lookup table to decode a muLaw-encoded byte sample into a 50.77 + * signed 16-bit sample */ 50.78 +static const ALshort muLawDecompressionTable[256] = { 50.79 + -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, 50.80 + -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, 50.81 + -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412, 50.82 + -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316, 50.83 + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, 50.84 + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, 50.85 + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, 50.86 + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, 50.87 + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, 50.88 + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, 50.89 + -876, -844, -812, -780, -748, -716, -684, -652, 50.90 + -620, -588, -556, -524, -492, -460, -428, -396, 50.91 + -372, -356, -340, -324, -308, -292, -276, -260, 50.92 + -244, -228, -212, -196, -180, -164, -148, -132, 50.93 + -120, -112, -104, -96, -88, -80, -72, -64, 50.94 + -56, -48, -40, -32, -24, -16, -8, 0, 50.95 + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, 50.96 + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, 50.97 + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, 50.98 + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, 50.99 + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, 50.100 + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, 50.101 + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, 50.102 + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, 50.103 + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, 50.104 + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, 50.105 + 876, 844, 812, 780, 748, 716, 684, 652, 50.106 + 620, 588, 556, 524, 492, 460, 428, 396, 50.107 + 372, 356, 340, 324, 308, 292, 276, 260, 50.108 + 244, 228, 212, 196, 180, 164, 148, 132, 50.109 + 120, 112, 104, 96, 88, 80, 72, 64, 50.110 + 56, 48, 40, 32, 24, 16, 8, 0 50.111 +}; 50.112 + 50.113 +/* Values used when encoding a muLaw sample */ 50.114 +static const int muLawBias = 0x84; 50.115 +static const int muLawClip = 32635; 50.116 +static const char muLawCompressTable[256] = 50.117 +{ 50.118 + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3, 50.119 + 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 50.120 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 50.121 + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 50.122 + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 50.123 + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 50.124 + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 50.125 + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 50.126 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.127 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.128 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.129 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.130 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.131 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.132 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 50.133 + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 50.134 +}; 50.135 + 50.136 +/* 50.137 + * alGenBuffers(ALsizei n, ALuint *buffers) 50.138 + * 50.139 + * Generates n AL Buffers, and stores the Buffers Names in the array pointed 50.140 + * to by buffers 50.141 + */ 50.142 +AL_API ALvoid AL_APIENTRY alGenBuffers(ALsizei n, ALuint *buffers) 50.143 +{ 50.144 + ALCcontext *Context; 50.145 + ALsizei i=0; 50.146 + 50.147 + Context = GetLockedContext(); 50.148 + if(!Context) return; 50.149 + 50.150 + /* Check that we are actually generating some Buffers */ 50.151 + if(n < 0 || IsBadWritePtr((void*)buffers, n * sizeof(ALuint))) 50.152 + alSetError(Context, AL_INVALID_VALUE); 50.153 + else 50.154 + { 50.155 + ALCdevice *device = Context->Device; 50.156 + ALenum err; 50.157 + 50.158 + // Create all the new Buffers 50.159 + while(i < n) 50.160 + { 50.161 + ALbuffer *buffer = calloc(1, sizeof(ALbuffer)); 50.162 + if(!buffer) 50.163 + { 50.164 + alSetError(Context, AL_OUT_OF_MEMORY); 50.165 + alDeleteBuffers(i, buffers); 50.166 + break; 50.167 + } 50.168 + 50.169 + err = NewThunkEntry(&buffer->buffer); 50.170 + if(err == AL_NO_ERROR) 50.171 + err = InsertUIntMapEntry(&device->BufferMap, buffer->buffer, buffer); 50.172 + if(err != AL_NO_ERROR) 50.173 + { 50.174 + FreeThunkEntry(buffer->buffer); 50.175 + memset(buffer, 0, sizeof(ALbuffer)); 50.176 + free(buffer); 50.177 + 50.178 + alSetError(Context, err); 50.179 + alDeleteBuffers(i, buffers); 50.180 + break; 50.181 + } 50.182 + buffers[i++] = buffer->buffer; 50.183 + } 50.184 + } 50.185 + 50.186 + UnlockContext(Context); 50.187 +} 50.188 + 50.189 +/* 50.190 + * alDeleteBuffers(ALsizei n, ALuint *buffers) 50.191 + * 50.192 + * Deletes the n AL Buffers pointed to by buffers 50.193 + */ 50.194 +AL_API ALvoid AL_APIENTRY alDeleteBuffers(ALsizei n, const ALuint *buffers) 50.195 +{ 50.196 + ALCcontext *Context; 50.197 + ALCdevice *device; 50.198 + ALboolean Failed; 50.199 + ALbuffer *ALBuf; 50.200 + ALsizei i; 50.201 + 50.202 + Context = GetLockedContext(); 50.203 + if(!Context) return; 50.204 + 50.205 + Failed = AL_TRUE; 50.206 + device = Context->Device; 50.207 + /* Check we are actually Deleting some Buffers */ 50.208 + if(n < 0) 50.209 + alSetError(Context, AL_INVALID_VALUE); 50.210 + else 50.211 + { 50.212 + Failed = AL_FALSE; 50.213 + 50.214 + /* Check that all the buffers are valid and can actually be deleted */ 50.215 + for(i = 0;i < n;i++) 50.216 + { 50.217 + if(!buffers[i]) 50.218 + continue; 50.219 + 50.220 + /* Check for valid Buffer ID */ 50.221 + if((ALBuf=LookupBuffer(device->BufferMap, buffers[i])) == NULL) 50.222 + { 50.223 + alSetError(Context, AL_INVALID_NAME); 50.224 + Failed = AL_TRUE; 50.225 + break; 50.226 + } 50.227 + else if(ALBuf->refcount != 0) 50.228 + { 50.229 + /* Buffer still in use, cannot be deleted */ 50.230 + alSetError(Context, AL_INVALID_OPERATION); 50.231 + Failed = AL_TRUE; 50.232 + break; 50.233 + } 50.234 + } 50.235 + } 50.236 + 50.237 + /* If all the Buffers were valid (and have Reference Counts of 0), then we 50.238 + * can delete them */ 50.239 + if(!Failed) 50.240 + { 50.241 + for(i = 0;i < n;i++) 50.242 + { 50.243 + if((ALBuf=LookupBuffer(device->BufferMap, buffers[i])) == NULL) 50.244 + continue; 50.245 + 50.246 + /* Release the memory used to store audio data */ 50.247 + free(ALBuf->data); 50.248 + 50.249 + /* Release buffer structure */ 50.250 + RemoveUIntMapKey(&device->BufferMap, ALBuf->buffer); 50.251 + FreeThunkEntry(ALBuf->buffer); 50.252 + 50.253 + memset(ALBuf, 0, sizeof(ALbuffer)); 50.254 + free(ALBuf); 50.255 + } 50.256 + } 50.257 + 50.258 + UnlockContext(Context); 50.259 +} 50.260 + 50.261 +/* 50.262 + * alIsBuffer(ALuint buffer) 50.263 + * 50.264 + * Checks if buffer is a valid Buffer Name 50.265 + */ 50.266 +AL_API ALboolean AL_APIENTRY alIsBuffer(ALuint buffer) 50.267 +{ 50.268 + ALCcontext *Context; 50.269 + ALboolean result; 50.270 + 50.271 + Context = GetLockedContext(); 50.272 + if(!Context) return AL_FALSE; 50.273 + 50.274 + result = ((!buffer || LookupBuffer(Context->Device->BufferMap, buffer)) ? 50.275 + AL_TRUE : AL_FALSE); 50.276 + 50.277 + UnlockContext(Context); 50.278 + 50.279 + return result; 50.280 +} 50.281 + 50.282 +/* 50.283 + * alBufferData(ALuint buffer, ALenum format, const ALvoid *data, 50.284 + * ALsizei size, ALsizei freq) 50.285 + * 50.286 + * Fill buffer with audio data 50.287 + */ 50.288 +AL_API ALvoid AL_APIENTRY alBufferData(ALuint buffer,ALenum format,const ALvoid *data,ALsizei size,ALsizei freq) 50.289 +{ 50.290 + enum UserFmtChannels SrcChannels; 50.291 + enum UserFmtType SrcType; 50.292 + ALCcontext *Context; 50.293 + ALCdevice *device; 50.294 + ALbuffer *ALBuf; 50.295 + ALenum err; 50.296 + 50.297 + Context = GetLockedContext(); 50.298 + if(!Context) return; 50.299 + 50.300 + device = Context->Device; 50.301 + if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.302 + alSetError(Context, AL_INVALID_NAME); 50.303 + else if(ALBuf->refcount != 0) 50.304 + alSetError(Context, AL_INVALID_VALUE); 50.305 + else if(size < 0 || freq < 0) 50.306 + alSetError(Context, AL_INVALID_VALUE); 50.307 + else if(DecomposeUserFormat(format, &SrcChannels, &SrcType) == AL_FALSE) 50.308 + alSetError(Context, AL_INVALID_ENUM); 50.309 + else switch(SrcType) 50.310 + { 50.311 + case UserFmtByte: 50.312 + case UserFmtUByte: 50.313 + case UserFmtShort: 50.314 + case UserFmtUShort: 50.315 + case UserFmtInt: 50.316 + case UserFmtUInt: 50.317 + case UserFmtFloat: { 50.318 + ALuint FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType); 50.319 + if((size%FrameSize) != 0) 50.320 + err = AL_INVALID_VALUE; 50.321 + else 50.322 + err = LoadData(ALBuf, freq, format, size/FrameSize, 50.323 + SrcChannels, SrcType, data, AL_TRUE); 50.324 + if(err != AL_NO_ERROR) 50.325 + alSetError(Context, err); 50.326 + } break; 50.327 + 50.328 + case UserFmtByte3: 50.329 + case UserFmtUByte3: 50.330 + case UserFmtDouble: { 50.331 + ALuint FrameSize = FrameSizeFromUserFmt(SrcChannels, SrcType); 50.332 + ALenum NewFormat = AL_FORMAT_MONO_FLOAT32; 50.333 + switch(SrcChannels) 50.334 + { 50.335 + case UserFmtMono: NewFormat = AL_FORMAT_MONO_FLOAT32; break; 50.336 + case UserFmtStereo: NewFormat = AL_FORMAT_STEREO_FLOAT32; break; 50.337 + case UserFmtRear: NewFormat = AL_FORMAT_REAR32; break; 50.338 + case UserFmtQuad: NewFormat = AL_FORMAT_QUAD32; break; 50.339 + case UserFmtX51: NewFormat = AL_FORMAT_51CHN32; break; 50.340 + case UserFmtX61: NewFormat = AL_FORMAT_61CHN32; break; 50.341 + case UserFmtX71: NewFormat = AL_FORMAT_71CHN32; break; 50.342 + } 50.343 + if((size%FrameSize) != 0) 50.344 + err = AL_INVALID_VALUE; 50.345 + else 50.346 + err = LoadData(ALBuf, freq, NewFormat, size/FrameSize, 50.347 + SrcChannels, SrcType, data, AL_TRUE); 50.348 + if(err != AL_NO_ERROR) 50.349 + alSetError(Context, err); 50.350 + } break; 50.351 + 50.352 + case UserFmtMulaw: 50.353 + case UserFmtIMA4: { 50.354 + /* Here is where things vary: 50.355 + * nVidia and Apple use 64+1 sample frames per block -> block_size=36 bytes per channel 50.356 + * Most PC sound software uses 2040+1 sample frames per block -> block_size=1024 bytes per channel 50.357 + */ 50.358 + ALuint FrameSize = (SrcType == UserFmtIMA4) ? 50.359 + (ChannelsFromUserFmt(SrcChannels) * 36) : 50.360 + FrameSizeFromUserFmt(SrcChannels, SrcType); 50.361 + ALenum NewFormat = AL_FORMAT_MONO16; 50.362 + switch(SrcChannels) 50.363 + { 50.364 + case UserFmtMono: NewFormat = AL_FORMAT_MONO16; break; 50.365 + case UserFmtStereo: NewFormat = AL_FORMAT_STEREO16; break; 50.366 + case UserFmtRear: NewFormat = AL_FORMAT_REAR16; break; 50.367 + case UserFmtQuad: NewFormat = AL_FORMAT_QUAD16; break; 50.368 + case UserFmtX51: NewFormat = AL_FORMAT_51CHN16; break; 50.369 + case UserFmtX61: NewFormat = AL_FORMAT_61CHN16; break; 50.370 + case UserFmtX71: NewFormat = AL_FORMAT_71CHN16; break; 50.371 + } 50.372 + if((size%FrameSize) != 0) 50.373 + err = AL_INVALID_VALUE; 50.374 + else 50.375 + err = LoadData(ALBuf, freq, NewFormat, size/FrameSize, 50.376 + SrcChannels, SrcType, data, AL_TRUE); 50.377 + if(err != AL_NO_ERROR) 50.378 + alSetError(Context, err); 50.379 + } break; 50.380 + } 50.381 + 50.382 + UnlockContext(Context); 50.383 +} 50.384 + 50.385 +/* 50.386 + * alBufferSubDataSOFT(ALuint buffer, ALenum format, const ALvoid *data, 50.387 + * ALsizei offset, ALsizei length) 50.388 + * 50.389 + * Update buffer's audio data 50.390 + */ 50.391 +AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length) 50.392 +{ 50.393 + enum UserFmtChannels SrcChannels; 50.394 + enum UserFmtType SrcType; 50.395 + ALCcontext *Context; 50.396 + ALCdevice *device; 50.397 + ALbuffer *ALBuf; 50.398 + 50.399 + Context = GetLockedContext(); 50.400 + if(!Context) return; 50.401 + 50.402 + device = Context->Device; 50.403 + if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.404 + alSetError(Context, AL_INVALID_NAME); 50.405 + else if(length < 0 || offset < 0 || (length > 0 && data == NULL)) 50.406 + alSetError(Context, AL_INVALID_VALUE); 50.407 + else if(DecomposeUserFormat(format, &SrcChannels, &SrcType) == AL_FALSE || 50.408 + SrcChannels != ALBuf->OriginalChannels || 50.409 + SrcType != ALBuf->OriginalType) 50.410 + alSetError(Context, AL_INVALID_ENUM); 50.411 + else if(offset > ALBuf->OriginalSize || 50.412 + length > ALBuf->OriginalSize-offset || 50.413 + (offset%ALBuf->OriginalAlign) != 0 || 50.414 + (length%ALBuf->OriginalAlign) != 0) 50.415 + alSetError(Context, AL_INVALID_VALUE); 50.416 + else 50.417 + { 50.418 + ALuint Channels = ChannelsFromFmt(ALBuf->FmtChannels); 50.419 + ALuint Bytes = BytesFromFmt(ALBuf->FmtType); 50.420 + if(SrcType == UserFmtIMA4) 50.421 + { 50.422 + /* offset -> byte offset, length -> block count */ 50.423 + offset /= 36; 50.424 + offset *= 65; 50.425 + offset *= Bytes; 50.426 + length /= ALBuf->OriginalAlign; 50.427 + } 50.428 + else 50.429 + { 50.430 + ALuint OldBytes = BytesFromUserFmt(SrcType); 50.431 + 50.432 + offset /= OldBytes; 50.433 + offset *= Bytes; 50.434 + length /= OldBytes * Channels; 50.435 + } 50.436 + ConvertData(&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType, 50.437 + data, SrcType, Channels, length); 50.438 + } 50.439 + 50.440 + UnlockContext(Context); 50.441 +} 50.442 + 50.443 + 50.444 +AL_API void AL_APIENTRY alBufferSamplesSOFT(ALuint buffer, 50.445 + ALuint samplerate, ALenum internalformat, ALsizei frames, 50.446 + ALenum channels, ALenum type, const ALvoid *data) 50.447 +{ 50.448 + ALCcontext *Context; 50.449 + ALCdevice *device; 50.450 + ALbuffer *ALBuf; 50.451 + ALenum err; 50.452 + 50.453 + Context = GetLockedContext(); 50.454 + if(!Context) return; 50.455 + 50.456 + device = Context->Device; 50.457 + if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.458 + alSetError(Context, AL_INVALID_NAME); 50.459 + else if(ALBuf->refcount != 0) 50.460 + alSetError(Context, AL_INVALID_VALUE); 50.461 + else if(frames < 0 || samplerate == 0) 50.462 + alSetError(Context, AL_INVALID_VALUE); 50.463 + else if(IsValidType(type) == AL_FALSE || IsValidChannels(channels) == AL_FALSE) 50.464 + alSetError(Context, AL_INVALID_ENUM); 50.465 + else 50.466 + { 50.467 + err = AL_NO_ERROR; 50.468 + if(type == UserFmtIMA4) 50.469 + { 50.470 + if((frames%65) == 0) frames /= 65; 50.471 + else err = AL_INVALID_VALUE; 50.472 + } 50.473 + if(err == AL_NO_ERROR) 50.474 + err = LoadData(ALBuf, samplerate, internalformat, frames, 50.475 + channels, type, data, AL_FALSE); 50.476 + if(err != AL_NO_ERROR) 50.477 + alSetError(Context, err); 50.478 + } 50.479 + 50.480 + UnlockContext(Context); 50.481 +} 50.482 + 50.483 +AL_API void AL_APIENTRY alBufferSubSamplesSOFT(ALuint buffer, 50.484 + ALsizei offset, ALsizei frames, 50.485 + ALenum channels, ALenum type, const ALvoid *data) 50.486 +{ 50.487 + ALCcontext *Context; 50.488 + ALCdevice *device; 50.489 + ALbuffer *ALBuf; 50.490 + 50.491 + Context = GetLockedContext(); 50.492 + if(!Context) return; 50.493 + 50.494 + device = Context->Device; 50.495 + if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.496 + alSetError(Context, AL_INVALID_NAME); 50.497 + else if(frames < 0 || offset < 0 || (frames > 0 && data == NULL)) 50.498 + alSetError(Context, AL_INVALID_VALUE); 50.499 + else if(channels != (ALenum)ALBuf->FmtChannels || 50.500 + IsValidType(type) == AL_FALSE) 50.501 + alSetError(Context, AL_INVALID_ENUM); 50.502 + else 50.503 + { 50.504 + ALuint FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType); 50.505 + ALuint FrameCount = ALBuf->size / FrameSize; 50.506 + if((ALuint)offset > FrameCount || (ALuint)frames > FrameCount-offset) 50.507 + alSetError(Context, AL_INVALID_VALUE); 50.508 + else if(type == UserFmtIMA4 && (frames%65) != 0) 50.509 + alSetError(Context, AL_INVALID_VALUE); 50.510 + else 50.511 + { 50.512 + /* offset -> byte offset */ 50.513 + offset *= FrameSize; 50.514 + /* frames -> IMA4 block count */ 50.515 + if(type == UserFmtIMA4) frames /= 65; 50.516 + ConvertData(&((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType, 50.517 + data, type, 50.518 + ChannelsFromFmt(ALBuf->FmtChannels), frames); 50.519 + } 50.520 + } 50.521 + 50.522 + UnlockContext(Context); 50.523 +} 50.524 + 50.525 +AL_API void AL_APIENTRY alGetBufferSamplesSOFT(ALuint buffer, 50.526 + ALsizei offset, ALsizei frames, 50.527 + ALenum channels, ALenum type, ALvoid *data) 50.528 +{ 50.529 + ALCcontext *Context; 50.530 + ALCdevice *device; 50.531 + ALbuffer *ALBuf; 50.532 + 50.533 + Context = GetLockedContext(); 50.534 + if(!Context) return; 50.535 + 50.536 + device = Context->Device; 50.537 + if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.538 + alSetError(Context, AL_INVALID_NAME); 50.539 + else if(frames < 0 || offset < 0 || (frames > 0 && data == NULL)) 50.540 + alSetError(Context, AL_INVALID_VALUE); 50.541 + else if(channels != (ALenum)ALBuf->FmtChannels || 50.542 + IsValidType(type) == AL_FALSE) 50.543 + alSetError(Context, AL_INVALID_ENUM); 50.544 + else 50.545 + { 50.546 + ALuint FrameSize = FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType); 50.547 + ALuint FrameCount = ALBuf->size / FrameSize; 50.548 + if((ALuint)offset > FrameCount || (ALuint)frames > FrameCount-offset) 50.549 + alSetError(Context, AL_INVALID_VALUE); 50.550 + else if(type == UserFmtIMA4 && (frames%65) != 0) 50.551 + alSetError(Context, AL_INVALID_VALUE); 50.552 + else 50.553 + { 50.554 + /* offset -> byte offset */ 50.555 + offset *= FrameSize; 50.556 + /* frames -> IMA4 block count */ 50.557 + if(type == UserFmtIMA4) frames /= 65; 50.558 + ConvertData(data, type, 50.559 + &((ALubyte*)ALBuf->data)[offset], ALBuf->FmtType, 50.560 + ChannelsFromFmt(ALBuf->FmtChannels), frames); 50.561 + } 50.562 + } 50.563 + 50.564 + UnlockContext(Context); 50.565 +} 50.566 + 50.567 +AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum format) 50.568 +{ 50.569 + enum FmtChannels DstChannels; 50.570 + enum FmtType DstType; 50.571 + ALCcontext *Context; 50.572 + ALboolean ret; 50.573 + 50.574 + Context = GetLockedContext(); 50.575 + if(!Context) return AL_FALSE; 50.576 + 50.577 + ret = DecomposeFormat(format, &DstChannels, &DstType); 50.578 + 50.579 + UnlockContext(Context); 50.580 + 50.581 + return ret; 50.582 +} 50.583 + 50.584 + 50.585 +AL_API void AL_APIENTRY alBufferf(ALuint buffer, ALenum eParam, ALfloat flValue) 50.586 +{ 50.587 + ALCcontext *pContext; 50.588 + ALCdevice *device; 50.589 + 50.590 + (void)flValue; 50.591 + 50.592 + pContext = GetLockedContext(); 50.593 + if(!pContext) return; 50.594 + 50.595 + device = pContext->Device; 50.596 + if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.597 + alSetError(pContext, AL_INVALID_NAME); 50.598 + else 50.599 + { 50.600 + switch(eParam) 50.601 + { 50.602 + default: 50.603 + alSetError(pContext, AL_INVALID_ENUM); 50.604 + break; 50.605 + } 50.606 + } 50.607 + 50.608 + UnlockContext(pContext); 50.609 +} 50.610 + 50.611 + 50.612 +AL_API void AL_APIENTRY alBuffer3f(ALuint buffer, ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3) 50.613 +{ 50.614 + ALCcontext *pContext; 50.615 + ALCdevice *device; 50.616 + 50.617 + (void)flValue1; 50.618 + (void)flValue2; 50.619 + (void)flValue3; 50.620 + 50.621 + pContext = GetLockedContext(); 50.622 + if(!pContext) return; 50.623 + 50.624 + device = pContext->Device; 50.625 + if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.626 + alSetError(pContext, AL_INVALID_NAME); 50.627 + else 50.628 + { 50.629 + switch(eParam) 50.630 + { 50.631 + default: 50.632 + alSetError(pContext, AL_INVALID_ENUM); 50.633 + break; 50.634 + } 50.635 + } 50.636 + 50.637 + UnlockContext(pContext); 50.638 +} 50.639 + 50.640 + 50.641 +AL_API void AL_APIENTRY alBufferfv(ALuint buffer, ALenum eParam, const ALfloat* flValues) 50.642 +{ 50.643 + ALCcontext *pContext; 50.644 + ALCdevice *device; 50.645 + 50.646 + pContext = GetLockedContext(); 50.647 + if(!pContext) return; 50.648 + 50.649 + device = pContext->Device; 50.650 + if(!flValues) 50.651 + alSetError(pContext, AL_INVALID_VALUE); 50.652 + else if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.653 + alSetError(pContext, AL_INVALID_NAME); 50.654 + else 50.655 + { 50.656 + switch(eParam) 50.657 + { 50.658 + default: 50.659 + alSetError(pContext, AL_INVALID_ENUM); 50.660 + break; 50.661 + } 50.662 + } 50.663 + 50.664 + UnlockContext(pContext); 50.665 +} 50.666 + 50.667 + 50.668 +AL_API void AL_APIENTRY alBufferi(ALuint buffer, ALenum eParam, ALint lValue) 50.669 +{ 50.670 + ALCcontext *pContext; 50.671 + ALCdevice *device; 50.672 + 50.673 + (void)lValue; 50.674 + 50.675 + pContext = GetLockedContext(); 50.676 + if(!pContext) return; 50.677 + 50.678 + device = pContext->Device; 50.679 + if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.680 + alSetError(pContext, AL_INVALID_NAME); 50.681 + else 50.682 + { 50.683 + switch(eParam) 50.684 + { 50.685 + default: 50.686 + alSetError(pContext, AL_INVALID_ENUM); 50.687 + break; 50.688 + } 50.689 + } 50.690 + 50.691 + UnlockContext(pContext); 50.692 +} 50.693 + 50.694 + 50.695 +AL_API void AL_APIENTRY alBuffer3i( ALuint buffer, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3) 50.696 +{ 50.697 + ALCcontext *pContext; 50.698 + ALCdevice *device; 50.699 + 50.700 + (void)lValue1; 50.701 + (void)lValue2; 50.702 + (void)lValue3; 50.703 + 50.704 + pContext = GetLockedContext(); 50.705 + if(!pContext) return; 50.706 + 50.707 + device = pContext->Device; 50.708 + if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.709 + alSetError(pContext, AL_INVALID_NAME); 50.710 + else 50.711 + { 50.712 + switch(eParam) 50.713 + { 50.714 + default: 50.715 + alSetError(pContext, AL_INVALID_ENUM); 50.716 + break; 50.717 + } 50.718 + } 50.719 + 50.720 + UnlockContext(pContext); 50.721 +} 50.722 + 50.723 + 50.724 +AL_API void AL_APIENTRY alBufferiv(ALuint buffer, ALenum eParam, const ALint* plValues) 50.725 +{ 50.726 + ALCcontext *pContext; 50.727 + ALCdevice *device; 50.728 + ALbuffer *ALBuf; 50.729 + 50.730 + pContext = GetLockedContext(); 50.731 + if(!pContext) return; 50.732 + 50.733 + device = pContext->Device; 50.734 + if(!plValues) 50.735 + alSetError(pContext, AL_INVALID_VALUE); 50.736 + else if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.737 + alSetError(pContext, AL_INVALID_NAME); 50.738 + else 50.739 + { 50.740 + switch(eParam) 50.741 + { 50.742 + case AL_LOOP_POINTS_SOFT: 50.743 + if(ALBuf->refcount > 0) 50.744 + alSetError(pContext, AL_INVALID_OPERATION); 50.745 + else if(plValues[0] < 0 || plValues[1] < 0 || 50.746 + plValues[0] >= plValues[1] || ALBuf->size == 0) 50.747 + alSetError(pContext, AL_INVALID_VALUE); 50.748 + else 50.749 + { 50.750 + ALint maxlen = ALBuf->size / 50.751 + FrameSizeFromFmt(ALBuf->FmtChannels, ALBuf->FmtType); 50.752 + if(plValues[0] > maxlen || plValues[1] > maxlen) 50.753 + alSetError(pContext, AL_INVALID_VALUE); 50.754 + else 50.755 + { 50.756 + ALBuf->LoopStart = plValues[0]; 50.757 + ALBuf->LoopEnd = plValues[1]; 50.758 + } 50.759 + } 50.760 + break; 50.761 + 50.762 + default: 50.763 + alSetError(pContext, AL_INVALID_ENUM); 50.764 + break; 50.765 + } 50.766 + } 50.767 + 50.768 + UnlockContext(pContext); 50.769 +} 50.770 + 50.771 + 50.772 +AL_API ALvoid AL_APIENTRY alGetBufferf(ALuint buffer, ALenum eParam, ALfloat *pflValue) 50.773 +{ 50.774 + ALCcontext *pContext; 50.775 + ALCdevice *device; 50.776 + 50.777 + pContext = GetLockedContext(); 50.778 + if(!pContext) return; 50.779 + 50.780 + device = pContext->Device; 50.781 + if(!pflValue) 50.782 + alSetError(pContext, AL_INVALID_VALUE); 50.783 + else if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.784 + alSetError(pContext, AL_INVALID_NAME); 50.785 + else 50.786 + { 50.787 + switch(eParam) 50.788 + { 50.789 + default: 50.790 + alSetError(pContext, AL_INVALID_ENUM); 50.791 + break; 50.792 + } 50.793 + } 50.794 + 50.795 + UnlockContext(pContext); 50.796 +} 50.797 + 50.798 + 50.799 +AL_API void AL_APIENTRY alGetBuffer3f(ALuint buffer, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3) 50.800 +{ 50.801 + ALCcontext *pContext; 50.802 + ALCdevice *device; 50.803 + 50.804 + pContext = GetLockedContext(); 50.805 + if(!pContext) return; 50.806 + 50.807 + device = pContext->Device; 50.808 + if(!pflValue1 || !pflValue2 || !pflValue3) 50.809 + alSetError(pContext, AL_INVALID_VALUE); 50.810 + else if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.811 + alSetError(pContext, AL_INVALID_NAME); 50.812 + else 50.813 + { 50.814 + switch(eParam) 50.815 + { 50.816 + default: 50.817 + alSetError(pContext, AL_INVALID_ENUM); 50.818 + break; 50.819 + } 50.820 + } 50.821 + 50.822 + UnlockContext(pContext); 50.823 +} 50.824 + 50.825 + 50.826 +AL_API void AL_APIENTRY alGetBufferfv(ALuint buffer, ALenum eParam, ALfloat* pflValues) 50.827 +{ 50.828 + ALCcontext *pContext; 50.829 + ALCdevice *device; 50.830 + 50.831 + pContext = GetLockedContext(); 50.832 + if(!pContext) return; 50.833 + 50.834 + device = pContext->Device; 50.835 + if(!pflValues) 50.836 + alSetError(pContext, AL_INVALID_VALUE); 50.837 + else if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.838 + alSetError(pContext, AL_INVALID_NAME); 50.839 + else 50.840 + { 50.841 + switch(eParam) 50.842 + { 50.843 + default: 50.844 + alSetError(pContext, AL_INVALID_ENUM); 50.845 + break; 50.846 + } 50.847 + } 50.848 + 50.849 + UnlockContext(pContext); 50.850 +} 50.851 + 50.852 + 50.853 +AL_API ALvoid AL_APIENTRY alGetBufferi(ALuint buffer, ALenum eParam, ALint *plValue) 50.854 +{ 50.855 + ALCcontext *pContext; 50.856 + ALbuffer *pBuffer; 50.857 + ALCdevice *device; 50.858 + 50.859 + pContext = GetLockedContext(); 50.860 + if(!pContext) return; 50.861 + 50.862 + device = pContext->Device; 50.863 + if(!plValue) 50.864 + alSetError(pContext, AL_INVALID_VALUE); 50.865 + else if((pBuffer=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.866 + alSetError(pContext, AL_INVALID_NAME); 50.867 + else 50.868 + { 50.869 + switch(eParam) 50.870 + { 50.871 + case AL_FREQUENCY: 50.872 + *plValue = pBuffer->Frequency; 50.873 + break; 50.874 + 50.875 + case AL_BITS: 50.876 + *plValue = BytesFromFmt(pBuffer->FmtType) * 8; 50.877 + break; 50.878 + 50.879 + case AL_CHANNELS: 50.880 + *plValue = ChannelsFromFmt(pBuffer->FmtChannels); 50.881 + break; 50.882 + 50.883 + case AL_SIZE: 50.884 + *plValue = pBuffer->size; 50.885 + break; 50.886 + 50.887 + default: 50.888 + alSetError(pContext, AL_INVALID_ENUM); 50.889 + break; 50.890 + } 50.891 + } 50.892 + 50.893 + UnlockContext(pContext); 50.894 +} 50.895 + 50.896 + 50.897 +AL_API void AL_APIENTRY alGetBuffer3i(ALuint buffer, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3) 50.898 +{ 50.899 + ALCcontext *pContext; 50.900 + ALCdevice *device; 50.901 + 50.902 + pContext = GetLockedContext(); 50.903 + if(!pContext) return; 50.904 + 50.905 + device = pContext->Device; 50.906 + if(!plValue1 || !plValue2 || !plValue3) 50.907 + alSetError(pContext, AL_INVALID_VALUE); 50.908 + else if(LookupBuffer(device->BufferMap, buffer) == NULL) 50.909 + alSetError(pContext, AL_INVALID_NAME); 50.910 + else 50.911 + { 50.912 + switch(eParam) 50.913 + { 50.914 + default: 50.915 + alSetError(pContext, AL_INVALID_ENUM); 50.916 + break; 50.917 + } 50.918 + } 50.919 + 50.920 + UnlockContext(pContext); 50.921 +} 50.922 + 50.923 + 50.924 +AL_API void AL_APIENTRY alGetBufferiv(ALuint buffer, ALenum eParam, ALint* plValues) 50.925 +{ 50.926 + ALCcontext *pContext; 50.927 + ALCdevice *device; 50.928 + ALbuffer *ALBuf; 50.929 + 50.930 + switch(eParam) 50.931 + { 50.932 + case AL_FREQUENCY: 50.933 + case AL_BITS: 50.934 + case AL_CHANNELS: 50.935 + case AL_SIZE: 50.936 + alGetBufferi(buffer, eParam, plValues); 50.937 + return; 50.938 + } 50.939 + 50.940 + pContext = GetLockedContext(); 50.941 + if(!pContext) return; 50.942 + 50.943 + device = pContext->Device; 50.944 + if(!plValues) 50.945 + alSetError(pContext, AL_INVALID_VALUE); 50.946 + else if((ALBuf=LookupBuffer(device->BufferMap, buffer)) == NULL) 50.947 + alSetError(pContext, AL_INVALID_NAME); 50.948 + else 50.949 + { 50.950 + switch(eParam) 50.951 + { 50.952 + case AL_LOOP_POINTS_SOFT: 50.953 + plValues[0] = ALBuf->LoopStart; 50.954 + plValues[1] = ALBuf->LoopEnd; 50.955 + break; 50.956 + 50.957 + default: 50.958 + alSetError(pContext, AL_INVALID_ENUM); 50.959 + break; 50.960 + } 50.961 + } 50.962 + 50.963 + UnlockContext(pContext); 50.964 +} 50.965 + 50.966 + 50.967 +typedef ALubyte ALmulaw; 50.968 +typedef ALubyte ALima4; 50.969 +typedef struct { 50.970 + ALbyte b[3]; 50.971 +} ALbyte3; 50.972 +typedef struct { 50.973 + ALubyte b[3]; 50.974 +} ALubyte3; 50.975 + 50.976 +static __inline ALshort DecodeMuLaw(ALmulaw val) 50.977 +{ return muLawDecompressionTable[val]; } 50.978 + 50.979 +static ALmulaw EncodeMuLaw(ALshort val) 50.980 +{ 50.981 + ALint mant, exp, sign; 50.982 + 50.983 + sign = (val>>8) & 0x80; 50.984 + if(sign) 50.985 + { 50.986 + /* -32768 doesn't properly negate on a short; it results in itself. 50.987 + * So clamp to -32767 */ 50.988 + val = maxi(val, -32767); 50.989 + val = -val; 50.990 + } 50.991 + 50.992 + val = mini(val, muLawClip); 50.993 + val += muLawBias; 50.994 + 50.995 + exp = muLawCompressTable[(val>>7) & 0xff]; 50.996 + mant = (val >> (exp+3)) & 0x0f; 50.997 + 50.998 + return ~(sign | (exp<<4) | mant); 50.999 +} 50.1000 + 50.1001 +static void DecodeIMA4Block(ALshort *dst, const ALima4 *src, ALint numchans) 50.1002 +{ 50.1003 + ALint sample[MAXCHANNELS], index[MAXCHANNELS]; 50.1004 + ALuint code[MAXCHANNELS]; 50.1005 + ALsizei j,k,c; 50.1006 + 50.1007 + for(c = 0;c < numchans;c++) 50.1008 + { 50.1009 + sample[c] = *(src++); 50.1010 + sample[c] |= *(src++) << 8; 50.1011 + sample[c] = (sample[c]^0x8000) - 32768; 50.1012 + index[c] = *(src++); 50.1013 + index[c] |= *(src++) << 8; 50.1014 + index[c] = (index[c]^0x8000) - 32768; 50.1015 + 50.1016 + index[c] = clampi(index[c], 0, 88); 50.1017 + 50.1018 + dst[c] = sample[c]; 50.1019 + } 50.1020 + 50.1021 + j = 1; 50.1022 + while(j < 65) 50.1023 + { 50.1024 + for(c = 0;c < numchans;c++) 50.1025 + { 50.1026 + code[c] = *(src++); 50.1027 + code[c] |= *(src++) << 8; 50.1028 + code[c] |= *(src++) << 16; 50.1029 + code[c] |= *(src++) << 24; 50.1030 + } 50.1031 + 50.1032 + for(k = 0;k < 8;k++,j++) 50.1033 + { 50.1034 + for(c = 0;c < numchans;c++) 50.1035 + { 50.1036 + int nibble = code[c]&0xf; 50.1037 + code[c] >>= 4; 50.1038 + 50.1039 + sample[c] += IMA4Codeword[nibble] * IMAStep_size[index[c]] / 8; 50.1040 + sample[c] = clampi(sample[c], -32768, 32767); 50.1041 + 50.1042 + index[c] += IMA4Index_adjust[nibble]; 50.1043 + index[c] = clampi(index[c], 0, 88); 50.1044 + 50.1045 + dst[j*numchans + c] = sample[c]; 50.1046 + } 50.1047 + } 50.1048 + } 50.1049 +} 50.1050 + 50.1051 +static void EncodeIMA4Block(ALima4 *dst, const ALshort *src, ALint *sample, ALint *index, ALint numchans) 50.1052 +{ 50.1053 + ALsizei j,k,c; 50.1054 + 50.1055 + for(c = 0;c < numchans;c++) 50.1056 + { 50.1057 + int diff = src[c] - sample[c]; 50.1058 + int step = IMAStep_size[index[c]]; 50.1059 + int nibble; 50.1060 + 50.1061 + nibble = 0; 50.1062 + if(diff < 0) 50.1063 + { 50.1064 + nibble = 0x8; 50.1065 + diff = -diff; 50.1066 + } 50.1067 + 50.1068 + diff = mini(step*2, diff); 50.1069 + nibble |= (diff*8/step - 1) / 2; 50.1070 + 50.1071 + sample[c] += IMA4Codeword[nibble] * step / 8; 50.1072 + sample[c] = clampi(sample[c], -32768, 32767); 50.1073 + 50.1074 + index[c] += IMA4Index_adjust[nibble]; 50.1075 + index[c] = clampi(index[c], 0, 88); 50.1076 + 50.1077 + *(dst++) = sample[c] & 0xff; 50.1078 + *(dst++) = (sample[c]>>8) & 0xff; 50.1079 + *(dst++) = index[c] & 0xff; 50.1080 + *(dst++) = (index[c]>>8) & 0xff; 50.1081 + } 50.1082 + 50.1083 + j = 1; 50.1084 + while(j < 65) 50.1085 + { 50.1086 + for(c = 0;c < numchans;c++) 50.1087 + { 50.1088 + for(k = 0;k < 8;k++) 50.1089 + { 50.1090 + int diff = src[(j+k)*numchans + c] - sample[c]; 50.1091 + int step = IMAStep_size[index[c]]; 50.1092 + int nibble; 50.1093 + 50.1094 + nibble = 0; 50.1095 + if(diff < 0) 50.1096 + { 50.1097 + nibble = 0x8; 50.1098 + diff = -diff; 50.1099 + } 50.1100 + 50.1101 + diff = mini(step*2, diff); 50.1102 + nibble |= (diff*8/step - 1) / 2; 50.1103 + 50.1104 + sample[c] += IMA4Codeword[nibble] * step / 8; 50.1105 + sample[c] = clampi(sample[c], -32768, 32767); 50.1106 + 50.1107 + index[c] += IMA4Index_adjust[nibble]; 50.1108 + index[c] = clampi(index[c], 0, 88); 50.1109 + 50.1110 + if(!(k&1)) *dst = nibble; 50.1111 + else *(dst++) |= nibble<<4; 50.1112 + } 50.1113 + } 50.1114 + j += 8; 50.1115 + } 50.1116 +} 50.1117 + 50.1118 +static const union { 50.1119 + ALuint u; 50.1120 + ALubyte b[sizeof(ALuint)]; 50.1121 +} EndianTest = { 1 }; 50.1122 +#define IS_LITTLE_ENDIAN (EndianTest.b[0] == 1) 50.1123 + 50.1124 +static __inline ALint DecodeByte3(ALbyte3 val) 50.1125 +{ 50.1126 + if(IS_LITTLE_ENDIAN) 50.1127 + return (val.b[2]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[0]); 50.1128 + return (val.b[0]<<16) | (((ALubyte)val.b[1])<<8) | ((ALubyte)val.b[2]); 50.1129 +} 50.1130 + 50.1131 +static __inline ALbyte3 EncodeByte3(ALint val) 50.1132 +{ 50.1133 + if(IS_LITTLE_ENDIAN) 50.1134 + { 50.1135 + ALbyte3 ret = {{ val, val>>8, val>>16 }}; 50.1136 + return ret; 50.1137 + } 50.1138 + else 50.1139 + { 50.1140 + ALbyte3 ret = {{ val>>16, val>>8, val }}; 50.1141 + return ret; 50.1142 + } 50.1143 +} 50.1144 + 50.1145 +static __inline ALint DecodeUByte3(ALubyte3 val) 50.1146 +{ 50.1147 + if(IS_LITTLE_ENDIAN) 50.1148 + return (val.b[2]<<16) | (val.b[1]<<8) | (val.b[0]); 50.1149 + return (val.b[0]<<16) | (val.b[1]<<8) | val.b[2]; 50.1150 +} 50.1151 + 50.1152 +static __inline ALubyte3 EncodeUByte3(ALint val) 50.1153 +{ 50.1154 + if(IS_LITTLE_ENDIAN) 50.1155 + { 50.1156 + ALubyte3 ret = {{ val, val>>8, val>>16 }}; 50.1157 + return ret; 50.1158 + } 50.1159 + else 50.1160 + { 50.1161 + ALubyte3 ret = {{ val>>16, val>>8, val }}; 50.1162 + return ret; 50.1163 + } 50.1164 +} 50.1165 + 50.1166 + 50.1167 +static __inline ALbyte Conv_ALbyte_ALbyte(ALbyte val) 50.1168 +{ return val; } 50.1169 +static __inline ALbyte Conv_ALbyte_ALubyte(ALubyte val) 50.1170 +{ return val-128; } 50.1171 +static __inline ALbyte Conv_ALbyte_ALshort(ALshort val) 50.1172 +{ return val>>8; } 50.1173 +static __inline ALbyte Conv_ALbyte_ALushort(ALushort val) 50.1174 +{ return (val>>8)-128; } 50.1175 +static __inline ALbyte Conv_ALbyte_ALint(ALint val) 50.1176 +{ return val>>24; } 50.1177 +static __inline ALbyte Conv_ALbyte_ALuint(ALuint val) 50.1178 +{ return (val>>24)-128; } 50.1179 +static __inline ALbyte Conv_ALbyte_ALfloat(ALfloat val) 50.1180 +{ 50.1181 + if(val > 1.0f) return 127; 50.1182 + if(val < -1.0f) return -128; 50.1183 + return (ALint)(val * 127.0f); 50.1184 +} 50.1185 +static __inline ALbyte Conv_ALbyte_ALdouble(ALdouble val) 50.1186 +{ 50.1187 + if(val > 1.0) return 127; 50.1188 + if(val < -1.0) return -128; 50.1189 + return (ALint)(val * 127.0); 50.1190 +} 50.1191 +static __inline ALbyte Conv_ALbyte_ALmulaw(ALmulaw val) 50.1192 +{ return Conv_ALbyte_ALshort(DecodeMuLaw(val)); } 50.1193 +static __inline ALbyte Conv_ALbyte_ALbyte3(ALbyte3 val) 50.1194 +{ return DecodeByte3(val)>>16; } 50.1195 +static __inline ALbyte Conv_ALbyte_ALubyte3(ALubyte3 val) 50.1196 +{ return (DecodeUByte3(val)>>16)-128; } 50.1197 + 50.1198 +static __inline ALubyte Conv_ALubyte_ALbyte(ALbyte val) 50.1199 +{ return val+128; } 50.1200 +static __inline ALubyte Conv_ALubyte_ALubyte(ALubyte val) 50.1201 +{ return val; } 50.1202 +static __inline ALubyte Conv_ALubyte_ALshort(ALshort val) 50.1203 +{ return (val>>8)+128; } 50.1204 +static __inline ALubyte Conv_ALubyte_ALushort(ALushort val) 50.1205 +{ return val>>8; } 50.1206 +static __inline ALubyte Conv_ALubyte_ALint(ALint val) 50.1207 +{ return (val>>24)+128; } 50.1208 +static __inline ALubyte Conv_ALubyte_ALuint(ALuint val) 50.1209 +{ return val>>24; } 50.1210 +static __inline ALubyte Conv_ALubyte_ALfloat(ALfloat val) 50.1211 +{ 50.1212 + if(val > 1.0f) return 255; 50.1213 + if(val < -1.0f) return 0; 50.1214 + return (ALint)(val * 127.0f) + 128; 50.1215 +} 50.1216 +static __inline ALubyte Conv_ALubyte_ALdouble(ALdouble val) 50.1217 +{ 50.1218 + if(val > 1.0) return 255; 50.1219 + if(val < -1.0) return 0; 50.1220 + return (ALint)(val * 127.0) + 128; 50.1221 +} 50.1222 +static __inline ALubyte Conv_ALubyte_ALmulaw(ALmulaw val) 50.1223 +{ return Conv_ALubyte_ALshort(DecodeMuLaw(val)); } 50.1224 +static __inline ALubyte Conv_ALubyte_ALbyte3(ALbyte3 val) 50.1225 +{ return (DecodeByte3(val)>>16)+128; } 50.1226 +static __inline ALubyte Conv_ALubyte_ALubyte3(ALubyte3 val) 50.1227 +{ return DecodeUByte3(val)>>16; } 50.1228 + 50.1229 +static __inline ALshort Conv_ALshort_ALbyte(ALbyte val) 50.1230 +{ return val<<8; } 50.1231 +static __inline ALshort Conv_ALshort_ALubyte(ALubyte val) 50.1232 +{ return (val-128)<<8; } 50.1233 +static __inline ALshort Conv_ALshort_ALshort(ALshort val) 50.1234 +{ return val; } 50.1235 +static __inline ALshort Conv_ALshort_ALushort(ALushort val) 50.1236 +{ return val-32768; } 50.1237 +static __inline ALshort Conv_ALshort_ALint(ALint val) 50.1238 +{ return val>>16; } 50.1239 +static __inline ALshort Conv_ALshort_ALuint(ALuint val) 50.1240 +{ return (val>>16)-32768; } 50.1241 +static __inline ALshort Conv_ALshort_ALfloat(ALfloat val) 50.1242 +{ 50.1243 + if(val > 1.0f) return 32767; 50.1244 + if(val < -1.0f) return -32768; 50.1245 + return (ALint)(val * 32767.0f); 50.1246 +} 50.1247 +static __inline ALshort Conv_ALshort_ALdouble(ALdouble val) 50.1248 +{ 50.1249 + if(val > 1.0) return 32767; 50.1250 + if(val < -1.0) return -32768; 50.1251 + return (ALint)(val * 32767.0); 50.1252 +} 50.1253 +static __inline ALshort Conv_ALshort_ALmulaw(ALmulaw val) 50.1254 +{ return Conv_ALshort_ALshort(DecodeMuLaw(val)); } 50.1255 +static __inline ALshort Conv_ALshort_ALbyte3(ALbyte3 val) 50.1256 +{ return DecodeByte3(val)>>8; } 50.1257 +static __inline ALshort Conv_ALshort_ALubyte3(ALubyte3 val) 50.1258 +{ return (DecodeUByte3(val)>>8)-32768; } 50.1259 + 50.1260 +static __inline ALushort Conv_ALushort_ALbyte(ALbyte val) 50.1261 +{ return (val+128)<<8; } 50.1262 +static __inline ALushort Conv_ALushort_ALubyte(ALubyte val) 50.1263 +{ return val<<8; } 50.1264 +static __inline ALushort Conv_ALushort_ALshort(ALshort val) 50.1265 +{ return val+32768; } 50.1266 +static __inline ALushort Conv_ALushort_ALushort(ALushort val) 50.1267 +{ return val; } 50.1268 +static __inline ALushort Conv_ALushort_ALint(ALint val) 50.1269 +{ return (val>>16)+32768; } 50.1270 +static __inline ALushort Conv_ALushort_ALuint(ALuint val) 50.1271 +{ return val>>16; } 50.1272 +static __inline ALushort Conv_ALushort_ALfloat(ALfloat val) 50.1273 +{ 50.1274 + if(val > 1.0f) return 65535; 50.1275 + if(val < -1.0f) return 0; 50.1276 + return (ALint)(val * 32767.0f) + 32768; 50.1277 +} 50.1278 +static __inline ALushort Conv_ALushort_ALdouble(ALdouble val) 50.1279 +{ 50.1280 + if(val > 1.0) return 65535; 50.1281 + if(val < -1.0) return 0; 50.1282 + return (ALint)(val * 32767.0) + 32768; 50.1283 +} 50.1284 +static __inline ALushort Conv_ALushort_ALmulaw(ALmulaw val) 50.1285 +{ return Conv_ALushort_ALshort(DecodeMuLaw(val)); } 50.1286 +static __inline ALushort Conv_ALushort_ALbyte3(ALbyte3 val) 50.1287 +{ return (DecodeByte3(val)>>8)+32768; } 50.1288 +static __inline ALushort Conv_ALushort_ALubyte3(ALubyte3 val) 50.1289 +{ return DecodeUByte3(val)>>8; } 50.1290 + 50.1291 +static __inline ALint Conv_ALint_ALbyte(ALbyte val) 50.1292 +{ return val<<24; } 50.1293 +static __inline ALint Conv_ALint_ALubyte(ALubyte val) 50.1294 +{ return (val-128)<<24; } 50.1295 +static __inline ALint Conv_ALint_ALshort(ALshort val) 50.1296 +{ return val<<16; } 50.1297 +static __inline ALint Conv_ALint_ALushort(ALushort val) 50.1298 +{ return (val-32768)<<16; } 50.1299 +static __inline ALint Conv_ALint_ALint(ALint val) 50.1300 +{ return val; } 50.1301 +static __inline ALint Conv_ALint_ALuint(ALuint val) 50.1302 +{ return val-2147483648u; } 50.1303 +static __inline ALint Conv_ALint_ALfloat(ALfloat val) 50.1304 +{ 50.1305 + if(val > 1.0f) return 2147483647; 50.1306 + if(val < -1.0f) return -2147483647-1; 50.1307 + return (ALint)(val * 2147483647.0); 50.1308 +} 50.1309 +static __inline ALint Conv_ALint_ALdouble(ALdouble val) 50.1310 +{ 50.1311 + if(val > 1.0) return 2147483647; 50.1312 + if(val < -1.0) return -2147483647-1; 50.1313 + return (ALint)(val * 2147483647.0); 50.1314 +} 50.1315 +static __inline ALint Conv_ALint_ALmulaw(ALmulaw val) 50.1316 +{ return Conv_ALint_ALshort(DecodeMuLaw(val)); } 50.1317 +static __inline ALint Conv_ALint_ALbyte3(ALbyte3 val) 50.1318 +{ return DecodeByte3(val)<<8; } 50.1319 +static __inline ALint Conv_ALint_ALubyte3(ALubyte3 val) 50.1320 +{ return (DecodeUByte3(val)-8388608)<<8; } 50.1321 + 50.1322 +static __inline ALuint Conv_ALuint_ALbyte(ALbyte val) 50.1323 +{ return (val+128)<<24; } 50.1324 +static __inline ALuint Conv_ALuint_ALubyte(ALubyte val) 50.1325 +{ return val<<24; } 50.1326 +static __inline ALuint Conv_ALuint_ALshort(ALshort val) 50.1327 +{ return (val+32768)<<16; } 50.1328 +static __inline ALuint Conv_ALuint_ALushort(ALushort val) 50.1329 +{ return val<<16; } 50.1330 +static __inline ALuint Conv_ALuint_ALint(ALint val) 50.1331 +{ return val+2147483648u; } 50.1332 +static __inline ALuint Conv_ALuint_ALuint(ALuint val) 50.1333 +{ return val; } 50.1334 +static __inline ALuint Conv_ALuint_ALfloat(ALfloat val) 50.1335 +{ 50.1336 + if(val > 1.0f) return 4294967295u; 50.1337 + if(val < -1.0f) return 0; 50.1338 + return (ALint)(val * 2147483647.0) + 2147483648u; 50.1339 +} 50.1340 +static __inline ALuint Conv_ALuint_ALdouble(ALdouble val) 50.1341 +{ 50.1342 + if(val > 1.0) return 4294967295u; 50.1343 + if(val < -1.0) return 0; 50.1344 + return (ALint)(val * 2147483647.0) + 2147483648u; 50.1345 +} 50.1346 +static __inline ALuint Conv_ALuint_ALmulaw(ALmulaw val) 50.1347 +{ return Conv_ALuint_ALshort(DecodeMuLaw(val)); } 50.1348 +static __inline ALuint Conv_ALuint_ALbyte3(ALbyte3 val) 50.1349 +{ return (DecodeByte3(val)+8388608)<<8; } 50.1350 +static __inline ALuint Conv_ALuint_ALubyte3(ALubyte3 val) 50.1351 +{ return DecodeUByte3(val)<<8; } 50.1352 + 50.1353 +static __inline ALfloat Conv_ALfloat_ALbyte(ALbyte val) 50.1354 +{ return val * (1.0f/127.0f); } 50.1355 +static __inline ALfloat Conv_ALfloat_ALubyte(ALubyte val) 50.1356 +{ return (val-128) * (1.0f/127.0f); } 50.1357 +static __inline ALfloat Conv_ALfloat_ALshort(ALshort val) 50.1358 +{ return val * (1.0f/32767.0f); } 50.1359 +static __inline ALfloat Conv_ALfloat_ALushort(ALushort val) 50.1360 +{ return (val-32768) * (1.0f/32767.0f); } 50.1361 +static __inline ALfloat Conv_ALfloat_ALint(ALint val) 50.1362 +{ return val * (1.0/2147483647.0); } 50.1363 +static __inline ALfloat Conv_ALfloat_ALuint(ALuint val) 50.1364 +{ return (ALint)(val-2147483648u) * (1.0/2147483647.0); } 50.1365 +static __inline ALfloat Conv_ALfloat_ALfloat(ALfloat val) 50.1366 +{ return (val==val) ? val : 0.0f; } 50.1367 +static __inline ALfloat Conv_ALfloat_ALdouble(ALdouble val) 50.1368 +{ return (val==val) ? val : 0.0; } 50.1369 +static __inline ALfloat Conv_ALfloat_ALmulaw(ALmulaw val) 50.1370 +{ return Conv_ALfloat_ALshort(DecodeMuLaw(val)); } 50.1371 +static __inline ALfloat Conv_ALfloat_ALbyte3(ALbyte3 val) 50.1372 +{ return DecodeByte3(val) * (1.0/8388607.0); } 50.1373 +static __inline ALfloat Conv_ALfloat_ALubyte3(ALubyte3 val) 50.1374 +{ return (DecodeUByte3(val)-8388608) * (1.0/8388607.0); } 50.1375 + 50.1376 +static __inline ALdouble Conv_ALdouble_ALbyte(ALbyte val) 50.1377 +{ return val * (1.0/127.0); } 50.1378 +static __inline ALdouble Conv_ALdouble_ALubyte(ALubyte val) 50.1379 +{ return (val-128) * (1.0/127.0); } 50.1380 +static __inline ALdouble Conv_ALdouble_ALshort(ALshort val) 50.1381 +{ return val * (1.0/32767.0); } 50.1382 +static __inline ALdouble Conv_ALdouble_ALushort(ALushort val) 50.1383 +{ return (val-32768) * (1.0/32767.0); } 50.1384 +static __inline ALdouble Conv_ALdouble_ALint(ALint val) 50.1385 +{ return val * (1.0/2147483647.0); } 50.1386 +static __inline ALdouble Conv_ALdouble_ALuint(ALuint val) 50.1387 +{ return (ALint)(val-2147483648u) * (1.0/2147483647.0); } 50.1388 +static __inline ALdouble Conv_ALdouble_ALfloat(ALfloat val) 50.1389 +{ return (val==val) ? val : 0.0f; } 50.1390 +static __inline ALdouble Conv_ALdouble_ALdouble(ALdouble val) 50.1391 +{ return (val==val) ? val : 0.0; } 50.1392 +static __inline ALdouble Conv_ALdouble_ALmulaw(ALmulaw val) 50.1393 +{ return Conv_ALdouble_ALshort(DecodeMuLaw(val)); } 50.1394 +static __inline ALdouble Conv_ALdouble_ALbyte3(ALbyte3 val) 50.1395 +{ return DecodeByte3(val) * (1.0/8388607.0); } 50.1396 +static __inline ALdouble Conv_ALdouble_ALubyte3(ALubyte3 val) 50.1397 +{ return (DecodeUByte3(val)-8388608) * (1.0/8388607.0); } 50.1398 + 50.1399 +#define DECL_TEMPLATE(T) \ 50.1400 +static __inline ALmulaw Conv_ALmulaw_##T(T val) \ 50.1401 +{ return EncodeMuLaw(Conv_ALshort_##T(val)); } 50.1402 + 50.1403 +DECL_TEMPLATE(ALbyte) 50.1404 +DECL_TEMPLATE(ALubyte) 50.1405 +DECL_TEMPLATE(ALshort) 50.1406 +DECL_TEMPLATE(ALushort) 50.1407 +DECL_TEMPLATE(ALint) 50.1408 +DECL_TEMPLATE(ALuint) 50.1409 +DECL_TEMPLATE(ALfloat) 50.1410 +DECL_TEMPLATE(ALdouble) 50.1411 +static __inline ALmulaw Conv_ALmulaw_ALmulaw(ALmulaw val) 50.1412 +{ return val; } 50.1413 +DECL_TEMPLATE(ALbyte3) 50.1414 +DECL_TEMPLATE(ALubyte3) 50.1415 + 50.1416 +#undef DECL_TEMPLATE 50.1417 + 50.1418 +#define DECL_TEMPLATE(T) \ 50.1419 +static __inline ALbyte3 Conv_ALbyte3_##T(T val) \ 50.1420 +{ return EncodeByte3(Conv_ALint_##T(val)>>8); } 50.1421 + 50.1422 +DECL_TEMPLATE(ALbyte) 50.1423 +DECL_TEMPLATE(ALubyte) 50.1424 +DECL_TEMPLATE(ALshort) 50.1425 +DECL_TEMPLATE(ALushort) 50.1426 +DECL_TEMPLATE(ALint) 50.1427 +DECL_TEMPLATE(ALuint) 50.1428 +DECL_TEMPLATE(ALfloat) 50.1429 +DECL_TEMPLATE(ALdouble) 50.1430 +DECL_TEMPLATE(ALmulaw) 50.1431 +static __inline ALbyte3 Conv_ALbyte3_ALbyte3(ALbyte3 val) 50.1432 +{ return val; } 50.1433 +DECL_TEMPLATE(ALubyte3) 50.1434 + 50.1435 +#undef DECL_TEMPLATE 50.1436 + 50.1437 +#define DECL_TEMPLATE(T) \ 50.1438 +static __inline ALubyte3 Conv_ALubyte3_##T(T val) \ 50.1439 +{ return EncodeUByte3(Conv_ALuint_##T(val)>>8); } 50.1440 + 50.1441 +DECL_TEMPLATE(ALbyte) 50.1442 +DECL_TEMPLATE(ALubyte) 50.1443 +DECL_TEMPLATE(ALshort) 50.1444 +DECL_TEMPLATE(ALushort) 50.1445 +DECL_TEMPLATE(ALint) 50.1446 +DECL_TEMPLATE(ALuint) 50.1447 +DECL_TEMPLATE(ALfloat) 50.1448 +DECL_TEMPLATE(ALdouble) 50.1449 +DECL_TEMPLATE(ALmulaw) 50.1450 +DECL_TEMPLATE(ALbyte3) 50.1451 +static __inline ALubyte3 Conv_ALubyte3_ALubyte3(ALubyte3 val) 50.1452 +{ return val; } 50.1453 + 50.1454 +#undef DECL_TEMPLATE 50.1455 + 50.1456 + 50.1457 +#define DECL_TEMPLATE(T1, T2) \ 50.1458 +static void Convert_##T1##_##T2(T1 *dst, const T2 *src, ALuint numchans, \ 50.1459 + ALuint len) \ 50.1460 +{ \ 50.1461 + ALuint i, j; \ 50.1462 + for(i = 0;i < len;i++) \ 50.1463 + { \ 50.1464 + for(j = 0;j < numchans;j++) \ 50.1465 + *(dst++) = Conv_##T1##_##T2(*(src++)); \ 50.1466 + } \ 50.1467 +} 50.1468 + 50.1469 +DECL_TEMPLATE(ALbyte, ALbyte) 50.1470 +DECL_TEMPLATE(ALbyte, ALubyte) 50.1471 +DECL_TEMPLATE(ALbyte, ALshort) 50.1472 +DECL_TEMPLATE(ALbyte, ALushort) 50.1473 +DECL_TEMPLATE(ALbyte, ALint) 50.1474 +DECL_TEMPLATE(ALbyte, ALuint) 50.1475 +DECL_TEMPLATE(ALbyte, ALfloat) 50.1476 +DECL_TEMPLATE(ALbyte, ALdouble) 50.1477 +DECL_TEMPLATE(ALbyte, ALmulaw) 50.1478 +DECL_TEMPLATE(ALbyte, ALbyte3) 50.1479 +DECL_TEMPLATE(ALbyte, ALubyte3) 50.1480 + 50.1481 +DECL_TEMPLATE(ALubyte, ALbyte) 50.1482 +DECL_TEMPLATE(ALubyte, ALubyte) 50.1483 +DECL_TEMPLATE(ALubyte, ALshort) 50.1484 +DECL_TEMPLATE(ALubyte, ALushort) 50.1485 +DECL_TEMPLATE(ALubyte, ALint) 50.1486 +DECL_TEMPLATE(ALubyte, ALuint) 50.1487 +DECL_TEMPLATE(ALubyte, ALfloat) 50.1488 +DECL_TEMPLATE(ALubyte, ALdouble) 50.1489 +DECL_TEMPLATE(ALubyte, ALmulaw) 50.1490 +DECL_TEMPLATE(ALubyte, ALbyte3) 50.1491 +DECL_TEMPLATE(ALubyte, ALubyte3) 50.1492 + 50.1493 +DECL_TEMPLATE(ALshort, ALbyte) 50.1494 +DECL_TEMPLATE(ALshort, ALubyte) 50.1495 +DECL_TEMPLATE(ALshort, ALshort) 50.1496 +DECL_TEMPLATE(ALshort, ALushort) 50.1497 +DECL_TEMPLATE(ALshort, ALint) 50.1498 +DECL_TEMPLATE(ALshort, ALuint) 50.1499 +DECL_TEMPLATE(ALshort, ALfloat) 50.1500 +DECL_TEMPLATE(ALshort, ALdouble) 50.1501 +DECL_TEMPLATE(ALshort, ALmulaw) 50.1502 +DECL_TEMPLATE(ALshort, ALbyte3) 50.1503 +DECL_TEMPLATE(ALshort, ALubyte3) 50.1504 + 50.1505 +DECL_TEMPLATE(ALushort, ALbyte) 50.1506 +DECL_TEMPLATE(ALushort, ALubyte) 50.1507 +DECL_TEMPLATE(ALushort, ALshort) 50.1508 +DECL_TEMPLATE(ALushort, ALushort) 50.1509 +DECL_TEMPLATE(ALushort, ALint) 50.1510 +DECL_TEMPLATE(ALushort, ALuint) 50.1511 +DECL_TEMPLATE(ALushort, ALfloat) 50.1512 +DECL_TEMPLATE(ALushort, ALdouble) 50.1513 +DECL_TEMPLATE(ALushort, ALmulaw) 50.1514 +DECL_TEMPLATE(ALushort, ALbyte3) 50.1515 +DECL_TEMPLATE(ALushort, ALubyte3) 50.1516 + 50.1517 +DECL_TEMPLATE(ALint, ALbyte) 50.1518 +DECL_TEMPLATE(ALint, ALubyte) 50.1519 +DECL_TEMPLATE(ALint, ALshort) 50.1520 +DECL_TEMPLATE(ALint, ALushort) 50.1521 +DECL_TEMPLATE(ALint, ALint) 50.1522 +DECL_TEMPLATE(ALint, ALuint) 50.1523 +DECL_TEMPLATE(ALint, ALfloat) 50.1524 +DECL_TEMPLATE(ALint, ALdouble) 50.1525 +DECL_TEMPLATE(ALint, ALmulaw) 50.1526 +DECL_TEMPLATE(ALint, ALbyte3) 50.1527 +DECL_TEMPLATE(ALint, ALubyte3) 50.1528 + 50.1529 +DECL_TEMPLATE(ALuint, ALbyte) 50.1530 +DECL_TEMPLATE(ALuint, ALubyte) 50.1531 +DECL_TEMPLATE(ALuint, ALshort) 50.1532 +DECL_TEMPLATE(ALuint, ALushort) 50.1533 +DECL_TEMPLATE(ALuint, ALint) 50.1534 +DECL_TEMPLATE(ALuint, ALuint) 50.1535 +DECL_TEMPLATE(ALuint, ALfloat) 50.1536 +DECL_TEMPLATE(ALuint, ALdouble) 50.1537 +DECL_TEMPLATE(ALuint, ALmulaw) 50.1538 +DECL_TEMPLATE(ALuint, ALbyte3) 50.1539 +DECL_TEMPLATE(ALuint, ALubyte3) 50.1540 + 50.1541 +DECL_TEMPLATE(ALfloat, ALbyte) 50.1542 +DECL_TEMPLATE(ALfloat, ALubyte) 50.1543 +DECL_TEMPLATE(ALfloat, ALshort) 50.1544 +DECL_TEMPLATE(ALfloat, ALushort) 50.1545 +DECL_TEMPLATE(ALfloat, ALint) 50.1546 +DECL_TEMPLATE(ALfloat, ALuint) 50.1547 +DECL_TEMPLATE(ALfloat, ALfloat) 50.1548 +DECL_TEMPLATE(ALfloat, ALdouble) 50.1549 +DECL_TEMPLATE(ALfloat, ALmulaw) 50.1550 +DECL_TEMPLATE(ALfloat, ALbyte3) 50.1551 +DECL_TEMPLATE(ALfloat, ALubyte3) 50.1552 + 50.1553 +DECL_TEMPLATE(ALdouble, ALbyte) 50.1554 +DECL_TEMPLATE(ALdouble, ALubyte) 50.1555 +DECL_TEMPLATE(ALdouble, ALshort) 50.1556 +DECL_TEMPLATE(ALdouble, ALushort) 50.1557 +DECL_TEMPLATE(ALdouble, ALint) 50.1558 +DECL_TEMPLATE(ALdouble, ALuint) 50.1559 +DECL_TEMPLATE(ALdouble, ALfloat) 50.1560 +DECL_TEMPLATE(ALdouble, ALdouble) 50.1561 +DECL_TEMPLATE(ALdouble, ALmulaw) 50.1562 +DECL_TEMPLATE(ALdouble, ALbyte3) 50.1563 +DECL_TEMPLATE(ALdouble, ALubyte3) 50.1564 + 50.1565 +DECL_TEMPLATE(ALmulaw, ALbyte) 50.1566 +DECL_TEMPLATE(ALmulaw, ALubyte) 50.1567 +DECL_TEMPLATE(ALmulaw, ALshort) 50.1568 +DECL_TEMPLATE(ALmulaw, ALushort) 50.1569 +DECL_TEMPLATE(ALmulaw, ALint) 50.1570 +DECL_TEMPLATE(ALmulaw, ALuint) 50.1571 +DECL_TEMPLATE(ALmulaw, ALfloat) 50.1572 +DECL_TEMPLATE(ALmulaw, ALdouble) 50.1573 +DECL_TEMPLATE(ALmulaw, ALmulaw) 50.1574 +DECL_TEMPLATE(ALmulaw, ALbyte3) 50.1575 +DECL_TEMPLATE(ALmulaw, ALubyte3) 50.1576 + 50.1577 +DECL_TEMPLATE(ALbyte3, ALbyte) 50.1578 +DECL_TEMPLATE(ALbyte3, ALubyte) 50.1579 +DECL_TEMPLATE(ALbyte3, ALshort) 50.1580 +DECL_TEMPLATE(ALbyte3, ALushort) 50.1581 +DECL_TEMPLATE(ALbyte3, ALint) 50.1582 +DECL_TEMPLATE(ALbyte3, ALuint) 50.1583 +DECL_TEMPLATE(ALbyte3, ALfloat) 50.1584 +DECL_TEMPLATE(ALbyte3, ALdouble) 50.1585 +DECL_TEMPLATE(ALbyte3, ALmulaw) 50.1586 +DECL_TEMPLATE(ALbyte3, ALbyte3) 50.1587 +DECL_TEMPLATE(ALbyte3, ALubyte3) 50.1588 + 50.1589 +DECL_TEMPLATE(ALubyte3, ALbyte) 50.1590 +DECL_TEMPLATE(ALubyte3, ALubyte) 50.1591 +DECL_TEMPLATE(ALubyte3, ALshort) 50.1592 +DECL_TEMPLATE(ALubyte3, ALushort) 50.1593 +DECL_TEMPLATE(ALubyte3, ALint) 50.1594 +DECL_TEMPLATE(ALubyte3, ALuint) 50.1595 +DECL_TEMPLATE(ALubyte3, ALfloat) 50.1596 +DECL_TEMPLATE(ALubyte3, ALdouble) 50.1597 +DECL_TEMPLATE(ALubyte3, ALmulaw) 50.1598 +DECL_TEMPLATE(ALubyte3, ALbyte3) 50.1599 +DECL_TEMPLATE(ALubyte3, ALubyte3) 50.1600 + 50.1601 +#undef DECL_TEMPLATE 50.1602 + 50.1603 +#define DECL_TEMPLATE(T) \ 50.1604 +static void Convert_##T##_ALima4(T *dst, const ALima4 *src, ALuint numchans, \ 50.1605 + ALuint numblocks) \ 50.1606 +{ \ 50.1607 + ALuint i, j; \ 50.1608 + ALshort tmp[65*MAXCHANNELS]; /* Max samples an IMA4 frame can be */ \ 50.1609 + for(i = 0;i < numblocks;i++) \ 50.1610 + { \ 50.1611 + DecodeIMA4Block(tmp, src, numchans); \ 50.1612 + src += 36*numchans; \ 50.1613 + for(j = 0;j < 65*numchans;j++) \ 50.1614 + *(dst++) = Conv_##T##_ALshort(tmp[j]); \ 50.1615 + } \ 50.1616 +} 50.1617 + 50.1618 +DECL_TEMPLATE(ALbyte) 50.1619 +DECL_TEMPLATE(ALubyte) 50.1620 +DECL_TEMPLATE(ALshort) 50.1621 +DECL_TEMPLATE(ALushort) 50.1622 +DECL_TEMPLATE(ALint) 50.1623 +DECL_TEMPLATE(ALuint) 50.1624 +DECL_TEMPLATE(ALfloat) 50.1625 +DECL_TEMPLATE(ALdouble) 50.1626 +DECL_TEMPLATE(ALmulaw) 50.1627 +DECL_TEMPLATE(ALbyte3) 50.1628 +DECL_TEMPLATE(ALubyte3) 50.1629 + 50.1630 +#undef DECL_TEMPLATE 50.1631 + 50.1632 +#define DECL_TEMPLATE(T) \ 50.1633 +static void Convert_ALima4_##T(ALima4 *dst, const T *src, ALuint numchans, \ 50.1634 + ALuint numblocks) \ 50.1635 +{ \ 50.1636 + ALuint i, j; \ 50.1637 + ALshort tmp[65*MAXCHANNELS]; /* Max samples an IMA4 frame can be */ \ 50.1638 + ALint sample[MAXCHANNELS] = {0,0,0,0,0,0,0,0}; \ 50.1639 + ALint index[MAXCHANNELS] = {0,0,0,0,0,0,0,0}; \ 50.1640 + for(i = 0;i < numblocks;i++) \ 50.1641 + { \ 50.1642 + for(j = 0;j < 65*numchans;j++) \ 50.1643 + tmp[j] = Conv_ALshort_##T(*(src++)); \ 50.1644 + EncodeIMA4Block(dst, tmp, sample, index, numchans); \ 50.1645 + dst += 36*numchans; \ 50.1646 + } \ 50.1647 +} 50.1648 + 50.1649 +DECL_TEMPLATE(ALbyte) 50.1650 +DECL_TEMPLATE(ALubyte) 50.1651 +DECL_TEMPLATE(ALshort) 50.1652 +DECL_TEMPLATE(ALushort) 50.1653 +DECL_TEMPLATE(ALint) 50.1654 +DECL_TEMPLATE(ALuint) 50.1655 +DECL_TEMPLATE(ALfloat) 50.1656 +DECL_TEMPLATE(ALdouble) 50.1657 +DECL_TEMPLATE(ALmulaw) 50.1658 +static void Convert_ALima4_ALima4(ALima4 *dst, const ALima4 *src, 50.1659 + ALuint numchans, ALuint numblocks) 50.1660 +{ memcpy(dst, src, numblocks*36*numchans); } 50.1661 +DECL_TEMPLATE(ALbyte3) 50.1662 +DECL_TEMPLATE(ALubyte3) 50.1663 + 50.1664 +#undef DECL_TEMPLATE 50.1665 + 50.1666 +#define DECL_TEMPLATE(T) \ 50.1667 +static void Convert_##T(T *dst, const ALvoid *src, enum UserFmtType srcType, \ 50.1668 + ALsizei numchans, ALsizei len) \ 50.1669 +{ \ 50.1670 + switch(srcType) \ 50.1671 + { \ 50.1672 + case UserFmtByte: \ 50.1673 + Convert_##T##_ALbyte(dst, src, numchans, len); \ 50.1674 + break; \ 50.1675 + case UserFmtUByte: \ 50.1676 + Convert_##T##_ALubyte(dst, src, numchans, len); \ 50.1677 + break; \ 50.1678 + case UserFmtShort: \ 50.1679 + Convert_##T##_ALshort(dst, src, numchans, len); \ 50.1680 + break; \ 50.1681 + case UserFmtUShort: \ 50.1682 + Convert_##T##_ALushort(dst, src, numchans, len); \ 50.1683 + break; \ 50.1684 + case UserFmtInt: \ 50.1685 + Convert_##T##_ALint(dst, src, numchans, len); \ 50.1686 + break; \ 50.1687 + case UserFmtUInt: \ 50.1688 + Convert_##T##_ALuint(dst, src, numchans, len); \ 50.1689 + break; \ 50.1690 + case UserFmtFloat: \ 50.1691 + Convert_##T##_ALfloat(dst, src, numchans, len); \ 50.1692 + break; \ 50.1693 + case UserFmtDouble: \ 50.1694 + Convert_##T##_ALdouble(dst, src, numchans, len); \ 50.1695 + break; \ 50.1696 + case UserFmtMulaw: \ 50.1697 + Convert_##T##_ALmulaw(dst, src, numchans, len); \ 50.1698 + break; \ 50.1699 + case UserFmtIMA4: \ 50.1700 + Convert_##T##_ALima4(dst, src, numchans, len); \ 50.1701 + break; \ 50.1702 + case UserFmtByte3: \ 50.1703 + Convert_##T##_ALbyte3(dst, src, numchans, len); \ 50.1704 + break; \ 50.1705 + case UserFmtUByte3: \ 50.1706 + Convert_##T##_ALubyte3(dst, src, numchans, len); \ 50.1707 + break; \ 50.1708 + } \ 50.1709 +} 50.1710 + 50.1711 +DECL_TEMPLATE(ALbyte) 50.1712 +DECL_TEMPLATE(ALubyte) 50.1713 +DECL_TEMPLATE(ALshort) 50.1714 +DECL_TEMPLATE(ALushort) 50.1715 +DECL_TEMPLATE(ALint) 50.1716 +DECL_TEMPLATE(ALuint) 50.1717 +DECL_TEMPLATE(ALfloat) 50.1718 +DECL_TEMPLATE(ALdouble) 50.1719 +DECL_TEMPLATE(ALmulaw) 50.1720 +DECL_TEMPLATE(ALima4) 50.1721 +DECL_TEMPLATE(ALbyte3) 50.1722 +DECL_TEMPLATE(ALubyte3) 50.1723 + 50.1724 +#undef DECL_TEMPLATE 50.1725 + 50.1726 + 50.1727 +static void ConvertData(ALvoid *dst, enum UserFmtType dstType, const ALvoid *src, enum UserFmtType srcType, ALsizei numchans, ALsizei len) 50.1728 +{ 50.1729 + switch(dstType) 50.1730 + { 50.1731 + case UserFmtByte: 50.1732 + Convert_ALbyte(dst, src, srcType, numchans, len); 50.1733 + break; 50.1734 + case UserFmtUByte: 50.1735 + Convert_ALubyte(dst, src, srcType, numchans, len); 50.1736 + break; 50.1737 + case UserFmtShort: 50.1738 + Convert_ALshort(dst, src, srcType, numchans, len); 50.1739 + break; 50.1740 + case UserFmtUShort: 50.1741 + Convert_ALushort(dst, src, srcType, numchans, len); 50.1742 + break; 50.1743 + case UserFmtInt: 50.1744 + Convert_ALint(dst, src, srcType, numchans, len); 50.1745 + break; 50.1746 + case UserFmtUInt: 50.1747 + Convert_ALuint(dst, src, srcType, numchans, len); 50.1748 + break; 50.1749 + case UserFmtFloat: 50.1750 + Convert_ALfloat(dst, src, srcType, numchans, len); 50.1751 + break; 50.1752 + case UserFmtDouble: 50.1753 + Convert_ALdouble(dst, src, srcType, numchans, len); 50.1754 + break; 50.1755 + case UserFmtMulaw: 50.1756 + Convert_ALmulaw(dst, src, srcType, numchans, len); 50.1757 + break; 50.1758 + case UserFmtIMA4: 50.1759 + Convert_ALima4(dst, src, srcType, numchans, len); 50.1760 + break; 50.1761 + case UserFmtByte3: 50.1762 + Convert_ALbyte3(dst, src, srcType, numchans, len); 50.1763 + break; 50.1764 + case UserFmtUByte3: 50.1765 + Convert_ALubyte3(dst, src, srcType, numchans, len); 50.1766 + break; 50.1767 + } 50.1768 +} 50.1769 + 50.1770 + 50.1771 +/* 50.1772 + * LoadData 50.1773 + * 50.1774 + * Loads the specified data into the buffer, using the specified formats. 50.1775 + * Currently, the new format must have the same channel configuration as the 50.1776 + * original format. 50.1777 + */ 50.1778 +static ALenum LoadData(ALbuffer *ALBuf, ALuint freq, ALenum NewFormat, ALsizei frames, enum UserFmtChannels SrcChannels, enum UserFmtType SrcType, const ALvoid *data, ALboolean storesrc) 50.1779 +{ 50.1780 + ALuint NewChannels, NewBytes; 50.1781 + enum FmtChannels DstChannels; 50.1782 + enum FmtType DstType; 50.1783 + ALuint64 newsize; 50.1784 + ALvoid *temp; 50.1785 + 50.1786 + if(DecomposeFormat(NewFormat, &DstChannels, &DstType) == AL_FALSE || 50.1787 + (long)SrcChannels != (long)DstChannels) 50.1788 + return AL_INVALID_ENUM; 50.1789 + 50.1790 + NewChannels = ChannelsFromFmt(DstChannels); 50.1791 + NewBytes = BytesFromFmt(DstType); 50.1792 + 50.1793 + if(SrcType == UserFmtIMA4) 50.1794 + { 50.1795 + ALuint OrigChannels = ChannelsFromUserFmt(SrcChannels); 50.1796 + 50.1797 + newsize = frames; 50.1798 + newsize *= 65; 50.1799 + newsize *= NewBytes; 50.1800 + newsize *= NewChannels; 50.1801 + if(newsize > INT_MAX) 50.1802 + return AL_OUT_OF_MEMORY; 50.1803 + 50.1804 + temp = realloc(ALBuf->data, newsize); 50.1805 + if(!temp && newsize) return AL_OUT_OF_MEMORY; 50.1806 + ALBuf->data = temp; 50.1807 + ALBuf->size = newsize; 50.1808 + 50.1809 + if(data != NULL) 50.1810 + ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames); 50.1811 + 50.1812 + if(storesrc) 50.1813 + { 50.1814 + ALBuf->OriginalChannels = SrcChannels; 50.1815 + ALBuf->OriginalType = SrcType; 50.1816 + ALBuf->OriginalSize = frames * 36 * OrigChannels; 50.1817 + ALBuf->OriginalAlign = 36 * OrigChannels; 50.1818 + } 50.1819 + } 50.1820 + else 50.1821 + { 50.1822 + ALuint OrigBytes = BytesFromUserFmt(SrcType); 50.1823 + ALuint OrigChannels = ChannelsFromUserFmt(SrcChannels); 50.1824 + 50.1825 + newsize = frames; 50.1826 + newsize *= NewBytes; 50.1827 + newsize *= NewChannels; 50.1828 + if(newsize > INT_MAX) 50.1829 + return AL_OUT_OF_MEMORY; 50.1830 + 50.1831 + temp = realloc(ALBuf->data, newsize); 50.1832 + if(!temp && newsize) return AL_OUT_OF_MEMORY; 50.1833 + ALBuf->data = temp; 50.1834 + ALBuf->size = newsize; 50.1835 + 50.1836 + if(data != NULL) 50.1837 + ConvertData(ALBuf->data, DstType, data, SrcType, NewChannels, frames); 50.1838 + 50.1839 + if(storesrc) 50.1840 + { 50.1841 + ALBuf->OriginalChannels = SrcChannels; 50.1842 + ALBuf->OriginalType = SrcType; 50.1843 + ALBuf->OriginalSize = frames * OrigBytes * OrigChannels; 50.1844 + ALBuf->OriginalAlign = OrigBytes * OrigChannels; 50.1845 + } 50.1846 + } 50.1847 + 50.1848 + if(!storesrc) 50.1849 + { 50.1850 + ALBuf->OriginalChannels = DstChannels; 50.1851 + ALBuf->OriginalType = DstType; 50.1852 + ALBuf->OriginalSize = frames * NewBytes * NewChannels; 50.1853 + ALBuf->OriginalAlign = NewBytes * NewChannels; 50.1854 + } 50.1855 + ALBuf->Frequency = freq; 50.1856 + ALBuf->FmtChannels = DstChannels; 50.1857 + ALBuf->FmtType = DstType; 50.1858 + 50.1859 + ALBuf->LoopStart = 0; 50.1860 + ALBuf->LoopEnd = newsize / NewChannels / NewBytes; 50.1861 + 50.1862 + return AL_NO_ERROR; 50.1863 +} 50.1864 + 50.1865 + 50.1866 +ALuint BytesFromUserFmt(enum UserFmtType type) 50.1867 +{ 50.1868 + switch(type) 50.1869 + { 50.1870 + case UserFmtByte: return sizeof(ALbyte); 50.1871 + case UserFmtUByte: return sizeof(ALubyte); 50.1872 + case UserFmtShort: return sizeof(ALshort); 50.1873 + case UserFmtUShort: return sizeof(ALushort); 50.1874 + case UserFmtInt: return sizeof(ALint); 50.1875 + case UserFmtUInt: return sizeof(ALuint); 50.1876 + case UserFmtFloat: return sizeof(ALfloat); 50.1877 + case UserFmtDouble: return sizeof(ALdouble); 50.1878 + case UserFmtByte3: return sizeof(ALbyte3); 50.1879 + case UserFmtUByte3: return sizeof(ALubyte3); 50.1880 + case UserFmtMulaw: return sizeof(ALubyte); 50.1881 + case UserFmtIMA4: break; /* not handled here */ 50.1882 + } 50.1883 + return 0; 50.1884 +} 50.1885 +ALuint ChannelsFromUserFmt(enum UserFmtChannels chans) 50.1886 +{ 50.1887 + switch(chans) 50.1888 + { 50.1889 + case UserFmtMono: return 1; 50.1890 + case UserFmtStereo: return 2; 50.1891 + case UserFmtRear: return 2; 50.1892 + case UserFmtQuad: return 4; 50.1893 + case UserFmtX51: return 6; 50.1894 + case UserFmtX61: return 7; 50.1895 + case UserFmtX71: return 8; 50.1896 + } 50.1897 + return 0; 50.1898 +} 50.1899 +ALboolean DecomposeUserFormat(ALenum format, enum UserFmtChannels *chans, 50.1900 + enum UserFmtType *type) 50.1901 +{ 50.1902 + switch(format) 50.1903 + { 50.1904 + case AL_FORMAT_MONO8: 50.1905 + *chans = UserFmtMono; 50.1906 + *type = UserFmtUByte; 50.1907 + return AL_TRUE; 50.1908 + case AL_FORMAT_MONO16: 50.1909 + *chans = UserFmtMono; 50.1910 + *type = UserFmtShort; 50.1911 + return AL_TRUE; 50.1912 + case AL_FORMAT_MONO_FLOAT32: 50.1913 + *chans = UserFmtMono; 50.1914 + *type = UserFmtFloat; 50.1915 + return AL_TRUE; 50.1916 + case AL_FORMAT_MONO_DOUBLE_EXT: 50.1917 + *chans = UserFmtMono; 50.1918 + *type = UserFmtDouble; 50.1919 + return AL_TRUE; 50.1920 + case AL_FORMAT_MONO_IMA4: 50.1921 + *chans = UserFmtMono; 50.1922 + *type = UserFmtIMA4; 50.1923 + return AL_TRUE; 50.1924 + case AL_FORMAT_STEREO8: 50.1925 + *chans = UserFmtStereo; 50.1926 + *type = UserFmtUByte; 50.1927 + return AL_TRUE; 50.1928 + case AL_FORMAT_STEREO16: 50.1929 + *chans = UserFmtStereo; 50.1930 + *type = UserFmtShort; 50.1931 + return AL_TRUE; 50.1932 + case AL_FORMAT_STEREO_FLOAT32: 50.1933 + *chans = UserFmtStereo; 50.1934 + *type = UserFmtFloat; 50.1935 + return AL_TRUE; 50.1936 + case AL_FORMAT_STEREO_DOUBLE_EXT: 50.1937 + *chans = UserFmtStereo; 50.1938 + *type = UserFmtDouble; 50.1939 + return AL_TRUE; 50.1940 + case AL_FORMAT_STEREO_IMA4: 50.1941 + *chans = UserFmtStereo; 50.1942 + *type = UserFmtIMA4; 50.1943 + return AL_TRUE; 50.1944 + case AL_FORMAT_QUAD8_LOKI: 50.1945 + case AL_FORMAT_QUAD8: 50.1946 + *chans = UserFmtQuad; 50.1947 + *type = UserFmtUByte; 50.1948 + return AL_TRUE; 50.1949 + case AL_FORMAT_QUAD16_LOKI: 50.1950 + case AL_FORMAT_QUAD16: 50.1951 + *chans = UserFmtQuad; 50.1952 + *type = UserFmtShort; 50.1953 + return AL_TRUE; 50.1954 + case AL_FORMAT_QUAD32: 50.1955 + *chans = UserFmtQuad; 50.1956 + *type = UserFmtFloat; 50.1957 + return AL_TRUE; 50.1958 + case AL_FORMAT_REAR8: 50.1959 + *chans = UserFmtRear; 50.1960 + *type = UserFmtUByte; 50.1961 + return AL_TRUE; 50.1962 + case AL_FORMAT_REAR16: 50.1963 + *chans = UserFmtRear; 50.1964 + *type = UserFmtShort; 50.1965 + return AL_TRUE; 50.1966 + case AL_FORMAT_REAR32: 50.1967 + *chans = UserFmtRear; 50.1968 + *type = UserFmtFloat; 50.1969 + return AL_TRUE; 50.1970 + case AL_FORMAT_51CHN8: 50.1971 + *chans = UserFmtX51; 50.1972 + *type = UserFmtUByte; 50.1973 + return AL_TRUE; 50.1974 + case AL_FORMAT_51CHN16: 50.1975 + *chans = UserFmtX51; 50.1976 + *type = UserFmtShort; 50.1977 + return AL_TRUE; 50.1978 + case AL_FORMAT_51CHN32: 50.1979 + *chans = UserFmtX51; 50.1980 + *type = UserFmtFloat; 50.1981 + return AL_TRUE; 50.1982 + case AL_FORMAT_61CHN8: 50.1983 + *chans = UserFmtX61; 50.1984 + *type = UserFmtUByte; 50.1985 + return AL_TRUE; 50.1986 + case AL_FORMAT_61CHN16: 50.1987 + *chans = UserFmtX61; 50.1988 + *type = UserFmtShort; 50.1989 + return AL_TRUE; 50.1990 + case AL_FORMAT_61CHN32: 50.1991 + *chans = UserFmtX61; 50.1992 + *type = UserFmtFloat; 50.1993 + return AL_TRUE; 50.1994 + case AL_FORMAT_71CHN8: 50.1995 + *chans = UserFmtX71; 50.1996 + *type = UserFmtUByte; 50.1997 + return AL_TRUE; 50.1998 + case AL_FORMAT_71CHN16: 50.1999 + *chans = UserFmtX71; 50.2000 + *type = UserFmtShort; 50.2001 + return AL_TRUE; 50.2002 + case AL_FORMAT_71CHN32: 50.2003 + *chans = UserFmtX71; 50.2004 + *type = UserFmtFloat; 50.2005 + return AL_TRUE; 50.2006 + case AL_FORMAT_MONO_MULAW: 50.2007 + *chans = UserFmtMono; 50.2008 + *type = UserFmtMulaw; 50.2009 + return AL_TRUE; 50.2010 + case AL_FORMAT_STEREO_MULAW: 50.2011 + *chans = UserFmtStereo; 50.2012 + *type = UserFmtMulaw; 50.2013 + return AL_TRUE; 50.2014 + case AL_FORMAT_QUAD_MULAW: 50.2015 + *chans = UserFmtQuad; 50.2016 + *type = UserFmtMulaw; 50.2017 + return AL_TRUE; 50.2018 + case AL_FORMAT_REAR_MULAW: 50.2019 + *chans = UserFmtRear; 50.2020 + *type = UserFmtMulaw; 50.2021 + return AL_TRUE; 50.2022 + case AL_FORMAT_51CHN_MULAW: 50.2023 + *chans = UserFmtX51; 50.2024 + *type = UserFmtMulaw; 50.2025 + return AL_TRUE; 50.2026 + case AL_FORMAT_61CHN_MULAW: 50.2027 + *chans = UserFmtX61; 50.2028 + *type = UserFmtMulaw; 50.2029 + return AL_TRUE; 50.2030 + case AL_FORMAT_71CHN_MULAW: 50.2031 + *chans = UserFmtX71; 50.2032 + *type = UserFmtMulaw; 50.2033 + return AL_TRUE; 50.2034 + } 50.2035 + return AL_FALSE; 50.2036 +} 50.2037 + 50.2038 +ALuint BytesFromFmt(enum FmtType type) 50.2039 +{ 50.2040 + switch(type) 50.2041 + { 50.2042 + case FmtByte: return sizeof(ALbyte); 50.2043 + case FmtShort: return sizeof(ALshort); 50.2044 + case FmtFloat: return sizeof(ALfloat); 50.2045 + } 50.2046 + return 0; 50.2047 +} 50.2048 +ALuint ChannelsFromFmt(enum FmtChannels chans) 50.2049 +{ 50.2050 + switch(chans) 50.2051 + { 50.2052 + case FmtMono: return 1; 50.2053 + case FmtStereo: return 2; 50.2054 + case FmtRear: return 2; 50.2055 + case FmtQuad: return 4; 50.2056 + case FmtX51: return 6; 50.2057 + case FmtX61: return 7; 50.2058 + case FmtX71: return 8; 50.2059 + } 50.2060 + return 0; 50.2061 +} 50.2062 +ALboolean DecomposeFormat(ALenum format, enum FmtChannels *chans, enum FmtType *type) 50.2063 +{ 50.2064 + switch(format) 50.2065 + { 50.2066 + case AL_MONO8: 50.2067 + *chans = FmtMono; 50.2068 + *type = FmtByte; 50.2069 + return AL_TRUE; 50.2070 + case AL_MONO16: 50.2071 + *chans = FmtMono; 50.2072 + *type = FmtShort; 50.2073 + return AL_TRUE; 50.2074 + case AL_MONO32F: 50.2075 + *chans = FmtMono; 50.2076 + *type = FmtFloat; 50.2077 + return AL_TRUE; 50.2078 + case AL_STEREO8: 50.2079 + *chans = FmtStereo; 50.2080 + *type = FmtByte; 50.2081 + return AL_TRUE; 50.2082 + case AL_STEREO16: 50.2083 + *chans = FmtStereo; 50.2084 + *type = FmtShort; 50.2085 + return AL_TRUE; 50.2086 + case AL_STEREO32F: 50.2087 + *chans = FmtStereo; 50.2088 + *type = FmtFloat; 50.2089 + return AL_TRUE; 50.2090 + case AL_FORMAT_QUAD8_LOKI: 50.2091 + case AL_QUAD8: 50.2092 + *chans = FmtQuad; 50.2093 + *type = FmtByte; 50.2094 + return AL_TRUE; 50.2095 + case AL_FORMAT_QUAD16_LOKI: 50.2096 + case AL_QUAD16: 50.2097 + *chans = FmtQuad; 50.2098 + *type = FmtShort; 50.2099 + return AL_TRUE; 50.2100 + case AL_QUAD32F: 50.2101 + *chans = FmtQuad; 50.2102 + *type = FmtFloat; 50.2103 + return AL_TRUE; 50.2104 + case AL_REAR8: 50.2105 + *chans = FmtRear; 50.2106 + *type = FmtByte; 50.2107 + return AL_TRUE; 50.2108 + case AL_REAR16: 50.2109 + *chans = FmtRear; 50.2110 + *type = FmtShort; 50.2111 + return AL_TRUE; 50.2112 + case AL_REAR32F: 50.2113 + *chans = FmtRear; 50.2114 + *type = FmtFloat; 50.2115 + return AL_TRUE; 50.2116 + case AL_5POINT1_8: 50.2117 + *chans = FmtX51; 50.2118 + *type = FmtByte; 50.2119 + return AL_TRUE; 50.2120 + case AL_5POINT1_16: 50.2121 + *chans = FmtX51; 50.2122 + *type = FmtShort; 50.2123 + return AL_TRUE; 50.2124 + case AL_5POINT1_32F: 50.2125 + *chans = FmtX51; 50.2126 + *type = FmtFloat; 50.2127 + return AL_TRUE; 50.2128 + case AL_6POINT1_8: 50.2129 + *chans = FmtX61; 50.2130 + *type = FmtByte; 50.2131 + return AL_TRUE; 50.2132 + case AL_6POINT1_16: 50.2133 + *chans = FmtX61; 50.2134 + *type = FmtShort; 50.2135 + return AL_TRUE; 50.2136 + case AL_6POINT1_32F: 50.2137 + *chans = FmtX61; 50.2138 + *type = FmtFloat; 50.2139 + return AL_TRUE; 50.2140 + case AL_7POINT1_8: 50.2141 + *chans = FmtX71; 50.2142 + *type = FmtByte; 50.2143 + return AL_TRUE; 50.2144 + case AL_7POINT1_16: 50.2145 + *chans = FmtX71; 50.2146 + *type = FmtShort; 50.2147 + return AL_TRUE; 50.2148 + case AL_7POINT1_32F: 50.2149 + *chans = FmtX71; 50.2150 + *type = FmtFloat; 50.2151 + return AL_TRUE; 50.2152 + } 50.2153 + return AL_FALSE; 50.2154 +} 50.2155 + 50.2156 + 50.2157 +static ALboolean IsValidType(ALenum type) 50.2158 +{ 50.2159 + switch(type) 50.2160 + { 50.2161 + case AL_BYTE: 50.2162 + case AL_UNSIGNED_BYTE: 50.2163 + case AL_SHORT: 50.2164 + case AL_UNSIGNED_SHORT: 50.2165 + case AL_INT: 50.2166 + case AL_UNSIGNED_INT: 50.2167 + case AL_FLOAT: 50.2168 + case AL_DOUBLE: 50.2169 + case AL_MULAW: 50.2170 + case AL_IMA4: 50.2171 + case AL_BYTE3: 50.2172 + case AL_UNSIGNED_BYTE3: 50.2173 + return AL_TRUE; 50.2174 + } 50.2175 + return AL_FALSE; 50.2176 +} 50.2177 + 50.2178 +static ALboolean IsValidChannels(ALenum channels) 50.2179 +{ 50.2180 + switch(channels) 50.2181 + { 50.2182 + case AL_MONO: 50.2183 + case AL_STEREO: 50.2184 + case AL_REAR: 50.2185 + case AL_QUAD: 50.2186 + case AL_5POINT1: 50.2187 + case AL_6POINT1: 50.2188 + case AL_7POINT1: 50.2189 + return AL_TRUE; 50.2190 + } 50.2191 + return AL_FALSE; 50.2192 +} 50.2193 + 50.2194 + 50.2195 +/* 50.2196 + * ReleaseALBuffers() 50.2197 + * 50.2198 + * INTERNAL: Called to destroy any buffers that still exist on the device 50.2199 + */ 50.2200 +ALvoid ReleaseALBuffers(ALCdevice *device) 50.2201 +{ 50.2202 + ALsizei i; 50.2203 + for(i = 0;i < device->BufferMap.size;i++) 50.2204 + { 50.2205 + ALbuffer *temp = device->BufferMap.array[i].value; 50.2206 + device->BufferMap.array[i].value = NULL; 50.2207 + 50.2208 + free(temp->data); 50.2209 + 50.2210 + FreeThunkEntry(temp->buffer); 50.2211 + memset(temp, 0, sizeof(ALbuffer)); 50.2212 + free(temp); 50.2213 + } 50.2214 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 51.2 +++ b/OpenAL32/alEffect.c Tue Oct 25 13:02:31 2011 -0700 51.3 @@ -0,0 +1,1142 @@ 51.4 +/** 51.5 + * OpenAL cross platform audio library 51.6 + * Copyright (C) 1999-2007 by authors. 51.7 + * This library is free software; you can redistribute it and/or 51.8 + * modify it under the terms of the GNU Library General Public 51.9 + * License as published by the Free Software Foundation; either 51.10 + * version 2 of the License, or (at your option) any later version. 51.11 + * 51.12 + * This library is distributed in the hope that it will be useful, 51.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 51.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 51.15 + * Library General Public License for more details. 51.16 + * 51.17 + * You should have received a copy of the GNU Library General Public 51.18 + * License along with this library; if not, write to the 51.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 51.20 + * Boston, MA 02111-1307, USA. 51.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 51.22 + */ 51.23 + 51.24 +#include "config.h" 51.25 + 51.26 +#include <stdlib.h> 51.27 +#include <math.h> 51.28 + 51.29 +#include "AL/al.h" 51.30 +#include "AL/alc.h" 51.31 +#include "alMain.h" 51.32 +#include "alEffect.h" 51.33 +#include "alThunk.h" 51.34 +#include "alError.h" 51.35 + 51.36 + 51.37 +ALboolean DisabledEffects[MAX_EFFECTS]; 51.38 + 51.39 + 51.40 +static void InitEffectParams(ALeffect *effect, ALenum type); 51.41 + 51.42 +#define LookupEffect(m, k) ((ALeffect*)LookupUIntMapKey(&(m), (k))) 51.43 + 51.44 +AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects) 51.45 +{ 51.46 + ALCcontext *Context; 51.47 + ALsizei i=0; 51.48 + 51.49 + Context = GetLockedContext(); 51.50 + if(!Context) return; 51.51 + 51.52 + if(n < 0 || IsBadWritePtr((void*)effects, n * sizeof(ALuint))) 51.53 + alSetError(Context, AL_INVALID_VALUE); 51.54 + else 51.55 + { 51.56 + ALCdevice *device = Context->Device; 51.57 + ALenum err; 51.58 + 51.59 + while(i < n) 51.60 + { 51.61 + ALeffect *effect = calloc(1, sizeof(ALeffect)); 51.62 + if(!effect) 51.63 + { 51.64 + alSetError(Context, AL_OUT_OF_MEMORY); 51.65 + alDeleteEffects(i, effects); 51.66 + break; 51.67 + } 51.68 + 51.69 + err = NewThunkEntry(&effect->effect); 51.70 + if(err == AL_NO_ERROR) 51.71 + err = InsertUIntMapEntry(&device->EffectMap, effect->effect, effect); 51.72 + if(err != AL_NO_ERROR) 51.73 + { 51.74 + FreeThunkEntry(effect->effect); 51.75 + memset(effect, 0, sizeof(ALeffect)); 51.76 + free(effect); 51.77 + 51.78 + alSetError(Context, err); 51.79 + alDeleteEffects(i, effects); 51.80 + break; 51.81 + } 51.82 + 51.83 + effects[i++] = effect->effect; 51.84 + InitEffectParams(effect, AL_EFFECT_NULL); 51.85 + } 51.86 + } 51.87 + 51.88 + UnlockContext(Context); 51.89 +} 51.90 + 51.91 +AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects) 51.92 +{ 51.93 + ALCcontext *Context; 51.94 + ALCdevice *device; 51.95 + ALeffect *ALEffect; 51.96 + ALboolean Failed; 51.97 + ALsizei i; 51.98 + 51.99 + Context = GetLockedContext(); 51.100 + if(!Context) return; 51.101 + 51.102 + Failed = AL_TRUE; 51.103 + device = Context->Device; 51.104 + if(n < 0) 51.105 + alSetError(Context, AL_INVALID_VALUE); 51.106 + else 51.107 + { 51.108 + Failed = AL_FALSE; 51.109 + // Check that all effects are valid 51.110 + for(i = 0;i < n;i++) 51.111 + { 51.112 + if(!effects[i]) 51.113 + continue; 51.114 + 51.115 + if(LookupEffect(device->EffectMap, effects[i]) == NULL) 51.116 + { 51.117 + alSetError(Context, AL_INVALID_NAME); 51.118 + Failed = AL_TRUE; 51.119 + break; 51.120 + } 51.121 + } 51.122 + } 51.123 + 51.124 + if(!Failed) 51.125 + { 51.126 + // All effects are valid 51.127 + for(i = 0;i < n;i++) 51.128 + { 51.129 + // Recheck that the effect is valid, because there could be duplicated names 51.130 + if((ALEffect=LookupEffect(device->EffectMap, effects[i])) == NULL) 51.131 + continue; 51.132 + 51.133 + RemoveUIntMapKey(&device->EffectMap, ALEffect->effect); 51.134 + FreeThunkEntry(ALEffect->effect); 51.135 + 51.136 + memset(ALEffect, 0, sizeof(ALeffect)); 51.137 + free(ALEffect); 51.138 + } 51.139 + } 51.140 + 51.141 + UnlockContext(Context); 51.142 +} 51.143 + 51.144 +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect) 51.145 +{ 51.146 + ALCcontext *Context; 51.147 + ALboolean result; 51.148 + 51.149 + Context = GetLockedContext(); 51.150 + if(!Context) return AL_FALSE; 51.151 + 51.152 + result = ((!effect || LookupEffect(Context->Device->EffectMap, effect)) ? 51.153 + AL_TRUE : AL_FALSE); 51.154 + 51.155 + UnlockContext(Context); 51.156 + 51.157 + return result; 51.158 +} 51.159 + 51.160 +AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue) 51.161 +{ 51.162 + ALCcontext *Context; 51.163 + ALCdevice *Device; 51.164 + ALeffect *ALEffect; 51.165 + 51.166 + Context = GetLockedContext(); 51.167 + if(!Context) return; 51.168 + 51.169 + Device = Context->Device; 51.170 + if((ALEffect=LookupEffect(Device->EffectMap, effect)) != NULL) 51.171 + { 51.172 + if(param == AL_EFFECT_TYPE) 51.173 + { 51.174 + ALboolean isOk = (iValue == AL_EFFECT_NULL); 51.175 + ALint i; 51.176 + for(i = 0;!isOk && EffectList[i].val;i++) 51.177 + { 51.178 + if(iValue == EffectList[i].val && 51.179 + !DisabledEffects[EffectList[i].type]) 51.180 + isOk = AL_TRUE; 51.181 + } 51.182 + 51.183 + if(isOk) 51.184 + InitEffectParams(ALEffect, iValue); 51.185 + else 51.186 + alSetError(Context, AL_INVALID_VALUE); 51.187 + } 51.188 + else if(ALEffect->type == AL_EFFECT_EAXREVERB) 51.189 + { 51.190 + switch(param) 51.191 + { 51.192 + case AL_EAXREVERB_DECAY_HFLIMIT: 51.193 + if(iValue >= AL_EAXREVERB_MIN_DECAY_HFLIMIT && 51.194 + iValue <= AL_EAXREVERB_MAX_DECAY_HFLIMIT) 51.195 + ALEffect->Params.Reverb.DecayHFLimit = iValue; 51.196 + else 51.197 + alSetError(Context, AL_INVALID_VALUE); 51.198 + break; 51.199 + 51.200 + default: 51.201 + alSetError(Context, AL_INVALID_ENUM); 51.202 + break; 51.203 + } 51.204 + } 51.205 + else if(ALEffect->type == AL_EFFECT_REVERB) 51.206 + { 51.207 + switch(param) 51.208 + { 51.209 + case AL_REVERB_DECAY_HFLIMIT: 51.210 + if(iValue >= AL_REVERB_MIN_DECAY_HFLIMIT && 51.211 + iValue <= AL_REVERB_MAX_DECAY_HFLIMIT) 51.212 + ALEffect->Params.Reverb.DecayHFLimit = iValue; 51.213 + else 51.214 + alSetError(Context, AL_INVALID_VALUE); 51.215 + break; 51.216 + 51.217 + default: 51.218 + alSetError(Context, AL_INVALID_ENUM); 51.219 + break; 51.220 + } 51.221 + } 51.222 + else if(ALEffect->type == AL_EFFECT_ECHO) 51.223 + { 51.224 + switch(param) 51.225 + { 51.226 + default: 51.227 + alSetError(Context, AL_INVALID_ENUM); 51.228 + break; 51.229 + } 51.230 + } 51.231 + else if(ALEffect->type == AL_EFFECT_RING_MODULATOR) 51.232 + { 51.233 + switch(param) 51.234 + { 51.235 + case AL_RING_MODULATOR_FREQUENCY: 51.236 + if(iValue >= AL_RING_MODULATOR_MIN_FREQUENCY && 51.237 + iValue <= AL_RING_MODULATOR_MAX_FREQUENCY) 51.238 + ALEffect->Params.Modulator.Frequency = iValue; 51.239 + else 51.240 + alSetError(Context, AL_INVALID_VALUE); 51.241 + break; 51.242 + 51.243 + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: 51.244 + if(iValue >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && 51.245 + iValue <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF) 51.246 + ALEffect->Params.Modulator.HighPassCutoff = iValue; 51.247 + else 51.248 + alSetError(Context, AL_INVALID_VALUE); 51.249 + break; 51.250 + 51.251 + case AL_RING_MODULATOR_WAVEFORM: 51.252 + if(iValue >= AL_RING_MODULATOR_MIN_WAVEFORM && 51.253 + iValue <= AL_RING_MODULATOR_MAX_WAVEFORM) 51.254 + ALEffect->Params.Modulator.Waveform = iValue; 51.255 + else 51.256 + alSetError(Context, AL_INVALID_VALUE); 51.257 + break; 51.258 + 51.259 + default: 51.260 + alSetError(Context, AL_INVALID_ENUM); 51.261 + break; 51.262 + } 51.263 + } 51.264 + else 51.265 + alSetError(Context, AL_INVALID_ENUM); 51.266 + } 51.267 + else 51.268 + alSetError(Context, AL_INVALID_NAME); 51.269 + 51.270 + UnlockContext(Context); 51.271 +} 51.272 + 51.273 +AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues) 51.274 +{ 51.275 + /* There are no multi-value int effect parameters */ 51.276 + alEffecti(effect, param, piValues[0]); 51.277 +} 51.278 + 51.279 +AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue) 51.280 +{ 51.281 + ALCcontext *Context; 51.282 + ALCdevice *Device; 51.283 + ALeffect *ALEffect; 51.284 + 51.285 + Context = GetLockedContext(); 51.286 + if(!Context) return; 51.287 + 51.288 + Device = Context->Device; 51.289 + if((ALEffect=LookupEffect(Device->EffectMap, effect)) != NULL) 51.290 + { 51.291 + if(ALEffect->type == AL_EFFECT_EAXREVERB) 51.292 + { 51.293 + switch(param) 51.294 + { 51.295 + case AL_EAXREVERB_DENSITY: 51.296 + if(flValue >= AL_EAXREVERB_MIN_DENSITY && 51.297 + flValue <= AL_EAXREVERB_MAX_DENSITY) 51.298 + ALEffect->Params.Reverb.Density = flValue; 51.299 + else 51.300 + alSetError(Context, AL_INVALID_VALUE); 51.301 + break; 51.302 + 51.303 + case AL_EAXREVERB_DIFFUSION: 51.304 + if(flValue >= AL_EAXREVERB_MIN_DIFFUSION && 51.305 + flValue <= AL_EAXREVERB_MAX_DIFFUSION) 51.306 + ALEffect->Params.Reverb.Diffusion = flValue; 51.307 + else 51.308 + alSetError(Context, AL_INVALID_VALUE); 51.309 + break; 51.310 + 51.311 + case AL_EAXREVERB_GAIN: 51.312 + if(flValue >= AL_EAXREVERB_MIN_GAIN && 51.313 + flValue <= AL_EAXREVERB_MAX_GAIN) 51.314 + ALEffect->Params.Reverb.Gain = flValue; 51.315 + else 51.316 + alSetError(Context, AL_INVALID_VALUE); 51.317 + break; 51.318 + 51.319 + case AL_EAXREVERB_GAINHF: 51.320 + if(flValue >= AL_EAXREVERB_MIN_GAINHF && 51.321 + flValue <= AL_EAXREVERB_MAX_GAINHF) 51.322 + ALEffect->Params.Reverb.GainHF = flValue; 51.323 + else 51.324 + alSetError(Context, AL_INVALID_VALUE); 51.325 + break; 51.326 + 51.327 + case AL_EAXREVERB_GAINLF: 51.328 + if(flValue >= AL_EAXREVERB_MIN_GAINLF && 51.329 + flValue <= AL_EAXREVERB_MAX_GAINLF) 51.330 + ALEffect->Params.Reverb.GainLF = flValue; 51.331 + else 51.332 + alSetError(Context, AL_INVALID_VALUE); 51.333 + break; 51.334 + 51.335 + case AL_EAXREVERB_DECAY_TIME: 51.336 + if(flValue >= AL_EAXREVERB_MIN_DECAY_TIME && 51.337 + flValue <= AL_EAXREVERB_MAX_DECAY_TIME) 51.338 + ALEffect->Params.Reverb.DecayTime = flValue; 51.339 + else 51.340 + alSetError(Context, AL_INVALID_VALUE); 51.341 + break; 51.342 + 51.343 + case AL_EAXREVERB_DECAY_HFRATIO: 51.344 + if(flValue >= AL_EAXREVERB_MIN_DECAY_HFRATIO && 51.345 + flValue <= AL_EAXREVERB_MAX_DECAY_HFRATIO) 51.346 + ALEffect->Params.Reverb.DecayHFRatio = flValue; 51.347 + else 51.348 + alSetError(Context, AL_INVALID_VALUE); 51.349 + break; 51.350 + 51.351 + case AL_EAXREVERB_DECAY_LFRATIO: 51.352 + if(flValue >= AL_EAXREVERB_MIN_DECAY_LFRATIO && 51.353 + flValue <= AL_EAXREVERB_MAX_DECAY_LFRATIO) 51.354 + ALEffect->Params.Reverb.DecayLFRatio = flValue; 51.355 + else 51.356 + alSetError(Context, AL_INVALID_VALUE); 51.357 + break; 51.358 + 51.359 + case AL_EAXREVERB_REFLECTIONS_GAIN: 51.360 + if(flValue >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN && 51.361 + flValue <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN) 51.362 + ALEffect->Params.Reverb.ReflectionsGain = flValue; 51.363 + else 51.364 + alSetError(Context, AL_INVALID_VALUE); 51.365 + break; 51.366 + 51.367 + case AL_EAXREVERB_REFLECTIONS_DELAY: 51.368 + if(flValue >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY && 51.369 + flValue <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY) 51.370 + ALEffect->Params.Reverb.ReflectionsDelay = flValue; 51.371 + else 51.372 + alSetError(Context, AL_INVALID_VALUE); 51.373 + break; 51.374 + 51.375 + case AL_EAXREVERB_LATE_REVERB_GAIN: 51.376 + if(flValue >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN && 51.377 + flValue <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN) 51.378 + ALEffect->Params.Reverb.LateReverbGain = flValue; 51.379 + else 51.380 + alSetError(Context, AL_INVALID_VALUE); 51.381 + break; 51.382 + 51.383 + case AL_EAXREVERB_LATE_REVERB_DELAY: 51.384 + if(flValue >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY && 51.385 + flValue <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY) 51.386 + ALEffect->Params.Reverb.LateReverbDelay = flValue; 51.387 + else 51.388 + alSetError(Context, AL_INVALID_VALUE); 51.389 + break; 51.390 + 51.391 + case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: 51.392 + if(flValue >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF && 51.393 + flValue <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF) 51.394 + ALEffect->Params.Reverb.AirAbsorptionGainHF = flValue; 51.395 + else 51.396 + alSetError(Context, AL_INVALID_VALUE); 51.397 + break; 51.398 + 51.399 + case AL_EAXREVERB_ECHO_TIME: 51.400 + if(flValue >= AL_EAXREVERB_MIN_ECHO_TIME && 51.401 + flValue <= AL_EAXREVERB_MAX_ECHO_TIME) 51.402 + ALEffect->Params.Reverb.EchoTime = flValue; 51.403 + else 51.404 + alSetError(Context, AL_INVALID_VALUE); 51.405 + break; 51.406 + 51.407 + case AL_EAXREVERB_ECHO_DEPTH: 51.408 + if(flValue >= AL_EAXREVERB_MIN_ECHO_DEPTH && 51.409 + flValue <= AL_EAXREVERB_MAX_ECHO_DEPTH) 51.410 + ALEffect->Params.Reverb.EchoDepth = flValue; 51.411 + else 51.412 + alSetError(Context, AL_INVALID_VALUE); 51.413 + break; 51.414 + 51.415 + case AL_EAXREVERB_MODULATION_TIME: 51.416 + if(flValue >= AL_EAXREVERB_MIN_MODULATION_TIME && 51.417 + flValue <= AL_EAXREVERB_MAX_MODULATION_TIME) 51.418 + ALEffect->Params.Reverb.ModulationTime = flValue; 51.419 + else 51.420 + alSetError(Context, AL_INVALID_VALUE); 51.421 + break; 51.422 + 51.423 + case AL_EAXREVERB_MODULATION_DEPTH: 51.424 + if(flValue >= AL_EAXREVERB_MIN_MODULATION_DEPTH && 51.425 + flValue <= AL_EAXREVERB_MAX_MODULATION_DEPTH) 51.426 + ALEffect->Params.Reverb.ModulationDepth = flValue; 51.427 + else 51.428 + alSetError(Context, AL_INVALID_VALUE); 51.429 + break; 51.430 + 51.431 + case AL_EAXREVERB_HFREFERENCE: 51.432 + if(flValue >= AL_EAXREVERB_MIN_HFREFERENCE && 51.433 + flValue <= AL_EAXREVERB_MAX_HFREFERENCE) 51.434 + ALEffect->Params.Reverb.HFReference = flValue; 51.435 + else 51.436 + alSetError(Context, AL_INVALID_VALUE); 51.437 + break; 51.438 + 51.439 + case AL_EAXREVERB_LFREFERENCE: 51.440 + if(flValue >= AL_EAXREVERB_MIN_LFREFERENCE && 51.441 + flValue <= AL_EAXREVERB_MAX_LFREFERENCE) 51.442 + ALEffect->Params.Reverb.LFReference = flValue; 51.443 + else 51.444 + alSetError(Context, AL_INVALID_VALUE); 51.445 + break; 51.446 + 51.447 + case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: 51.448 + if(flValue >= 0.0f && flValue <= 10.0f) 51.449 + ALEffect->Params.Reverb.RoomRolloffFactor = flValue; 51.450 + else 51.451 + alSetError(Context, AL_INVALID_VALUE); 51.452 + break; 51.453 + 51.454 + default: 51.455 + alSetError(Context, AL_INVALID_ENUM); 51.456 + break; 51.457 + } 51.458 + } 51.459 + else if(ALEffect->type == AL_EFFECT_REVERB) 51.460 + { 51.461 + switch(param) 51.462 + { 51.463 + case AL_REVERB_DENSITY: 51.464 + if(flValue >= AL_REVERB_MIN_DENSITY && 51.465 + flValue <= AL_REVERB_MAX_DENSITY) 51.466 + ALEffect->Params.Reverb.Density = flValue; 51.467 + else 51.468 + alSetError(Context, AL_INVALID_VALUE); 51.469 + break; 51.470 + 51.471 + case AL_REVERB_DIFFUSION: 51.472 + if(flValue >= AL_REVERB_MIN_DIFFUSION && 51.473 + flValue <= AL_REVERB_MAX_DIFFUSION) 51.474 + ALEffect->Params.Reverb.Diffusion = flValue; 51.475 + else 51.476 + alSetError(Context, AL_INVALID_VALUE); 51.477 + break; 51.478 + 51.479 + case AL_REVERB_GAIN: 51.480 + if(flValue >= AL_REVERB_MIN_GAIN && 51.481 + flValue <= AL_REVERB_MAX_GAIN) 51.482 + ALEffect->Params.Reverb.Gain = flValue; 51.483 + else 51.484 + alSetError(Context, AL_INVALID_VALUE); 51.485 + break; 51.486 + 51.487 + case AL_REVERB_GAINHF: 51.488 + if(flValue >= AL_REVERB_MIN_GAINHF && 51.489 + flValue <= AL_REVERB_MAX_GAINHF) 51.490 + ALEffect->Params.Reverb.GainHF = flValue; 51.491 + else 51.492 + alSetError(Context, AL_INVALID_VALUE); 51.493 + break; 51.494 + 51.495 + case AL_REVERB_DECAY_TIME: 51.496 + if(flValue >= AL_REVERB_MIN_DECAY_TIME && 51.497 + flValue <= AL_REVERB_MAX_DECAY_TIME) 51.498 + ALEffect->Params.Reverb.DecayTime = flValue; 51.499 + else 51.500 + alSetError(Context, AL_INVALID_VALUE); 51.501 + break; 51.502 + 51.503 + case AL_REVERB_DECAY_HFRATIO: 51.504 + if(flValue >= AL_REVERB_MIN_DECAY_HFRATIO && 51.505 + flValue <= AL_REVERB_MAX_DECAY_HFRATIO) 51.506 + ALEffect->Params.Reverb.DecayHFRatio = flValue; 51.507 + else 51.508 + alSetError(Context, AL_INVALID_VALUE); 51.509 + break; 51.510 + 51.511 + case AL_REVERB_REFLECTIONS_GAIN: 51.512 + if(flValue >= AL_REVERB_MIN_REFLECTIONS_GAIN && 51.513 + flValue <= AL_REVERB_MAX_REFLECTIONS_GAIN) 51.514 + ALEffect->Params.Reverb.ReflectionsGain = flValue; 51.515 + else 51.516 + alSetError(Context, AL_INVALID_VALUE); 51.517 + break; 51.518 + 51.519 + case AL_REVERB_REFLECTIONS_DELAY: 51.520 + if(flValue >= AL_REVERB_MIN_REFLECTIONS_DELAY && 51.521 + flValue <= AL_REVERB_MAX_REFLECTIONS_DELAY) 51.522 + ALEffect->Params.Reverb.ReflectionsDelay = flValue; 51.523 + else 51.524 + alSetError(Context, AL_INVALID_VALUE); 51.525 + break; 51.526 + 51.527 + case AL_REVERB_LATE_REVERB_GAIN: 51.528 + if(flValue >= AL_REVERB_MIN_LATE_REVERB_GAIN && 51.529 + flValue <= AL_REVERB_MAX_LATE_REVERB_GAIN) 51.530 + ALEffect->Params.Reverb.LateReverbGain = flValue; 51.531 + else 51.532 + alSetError(Context, AL_INVALID_VALUE); 51.533 + break; 51.534 + 51.535 + case AL_REVERB_LATE_REVERB_DELAY: 51.536 + if(flValue >= AL_REVERB_MIN_LATE_REVERB_DELAY && 51.537 + flValue <= AL_REVERB_MAX_LATE_REVERB_DELAY) 51.538 + ALEffect->Params.Reverb.LateReverbDelay = flValue; 51.539 + else 51.540 + alSetError(Context, AL_INVALID_VALUE); 51.541 + break; 51.542 + 51.543 + case AL_REVERB_AIR_ABSORPTION_GAINHF: 51.544 + if(flValue >= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF && 51.545 + flValue <= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF) 51.546 + ALEffect->Params.Reverb.AirAbsorptionGainHF = flValue; 51.547 + else 51.548 + alSetError(Context, AL_INVALID_VALUE); 51.549 + break; 51.550 + 51.551 + case AL_REVERB_ROOM_ROLLOFF_FACTOR: 51.552 + if(flValue >= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR && 51.553 + flValue <= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR) 51.554 + ALEffect->Params.Reverb.RoomRolloffFactor = flValue; 51.555 + else 51.556 + alSetError(Context, AL_INVALID_VALUE); 51.557 + break; 51.558 + 51.559 + default: 51.560 + alSetError(Context, AL_INVALID_ENUM); 51.561 + break; 51.562 + } 51.563 + } 51.564 + else if(ALEffect->type == AL_EFFECT_ECHO) 51.565 + { 51.566 + switch(param) 51.567 + { 51.568 + case AL_ECHO_DELAY: 51.569 + if(flValue >= AL_ECHO_MIN_DELAY && flValue <= AL_ECHO_MAX_DELAY) 51.570 + ALEffect->Params.Echo.Delay = flValue; 51.571 + else 51.572 + alSetError(Context, AL_INVALID_VALUE); 51.573 + break; 51.574 + 51.575 + case AL_ECHO_LRDELAY: 51.576 + if(flValue >= AL_ECHO_MIN_LRDELAY && flValue <= AL_ECHO_MAX_LRDELAY) 51.577 + ALEffect->Params.Echo.LRDelay = flValue; 51.578 + else 51.579 + alSetError(Context, AL_INVALID_VALUE); 51.580 + break; 51.581 + 51.582 + case AL_ECHO_DAMPING: 51.583 + if(flValue >= AL_ECHO_MIN_DAMPING && flValue <= AL_ECHO_MAX_DAMPING) 51.584 + ALEffect->Params.Echo.Damping = flValue; 51.585 + else 51.586 + alSetError(Context, AL_INVALID_VALUE); 51.587 + break; 51.588 + 51.589 + case AL_ECHO_FEEDBACK: 51.590 + if(flValue >= AL_ECHO_MIN_FEEDBACK && flValue <= AL_ECHO_MAX_FEEDBACK) 51.591 + ALEffect->Params.Echo.Feedback = flValue; 51.592 + else 51.593 + alSetError(Context, AL_INVALID_VALUE); 51.594 + break; 51.595 + 51.596 + case AL_ECHO_SPREAD: 51.597 + if(flValue >= AL_ECHO_MIN_SPREAD && flValue <= AL_ECHO_MAX_SPREAD) 51.598 + ALEffect->Params.Echo.Spread = flValue; 51.599 + else 51.600 + alSetError(Context, AL_INVALID_VALUE); 51.601 + break; 51.602 + 51.603 + default: 51.604 + alSetError(Context, AL_INVALID_ENUM); 51.605 + break; 51.606 + } 51.607 + } 51.608 + else if(ALEffect->type == AL_EFFECT_RING_MODULATOR) 51.609 + { 51.610 + switch(param) 51.611 + { 51.612 + case AL_RING_MODULATOR_FREQUENCY: 51.613 + if(flValue >= AL_RING_MODULATOR_MIN_FREQUENCY && 51.614 + flValue <= AL_RING_MODULATOR_MAX_FREQUENCY) 51.615 + ALEffect->Params.Modulator.Frequency = flValue; 51.616 + else 51.617 + alSetError(Context, AL_INVALID_VALUE); 51.618 + break; 51.619 + 51.620 + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: 51.621 + if(flValue >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && 51.622 + flValue <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF) 51.623 + ALEffect->Params.Modulator.HighPassCutoff = flValue; 51.624 + else 51.625 + alSetError(Context, AL_INVALID_VALUE); 51.626 + break; 51.627 + 51.628 + default: 51.629 + alSetError(Context, AL_INVALID_ENUM); 51.630 + break; 51.631 + } 51.632 + } 51.633 + else if(ALEffect->type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT || 51.634 + ALEffect->type == AL_EFFECT_DEDICATED_DIALOGUE) 51.635 + { 51.636 + switch(param) 51.637 + { 51.638 + case AL_DEDICATED_GAIN: 51.639 + if(flValue >= 0.0f && isfinite(flValue)) 51.640 + ALEffect->Params.Dedicated.Gain = flValue; 51.641 + else 51.642 + alSetError(Context, AL_INVALID_VALUE); 51.643 + break; 51.644 + 51.645 + default: 51.646 + alSetError(Context, AL_INVALID_ENUM); 51.647 + break; 51.648 + } 51.649 + } 51.650 + else 51.651 + alSetError(Context, AL_INVALID_ENUM); 51.652 + } 51.653 + else 51.654 + alSetError(Context, AL_INVALID_NAME); 51.655 + 51.656 + UnlockContext(Context); 51.657 +} 51.658 + 51.659 +AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues) 51.660 +{ 51.661 + ALCcontext *Context; 51.662 + ALCdevice *Device; 51.663 + ALeffect *ALEffect; 51.664 + 51.665 + Context = GetLockedContext(); 51.666 + if(!Context) return; 51.667 + 51.668 + Device = Context->Device; 51.669 + if((ALEffect=LookupEffect(Device->EffectMap, effect)) != NULL) 51.670 + { 51.671 + if(ALEffect->type == AL_EFFECT_EAXREVERB) 51.672 + { 51.673 + switch(param) 51.674 + { 51.675 + case AL_EAXREVERB_REFLECTIONS_PAN: 51.676 + if(isfinite(pflValues[0]) && isfinite(pflValues[1]) && isfinite(pflValues[2])) 51.677 + { 51.678 + ALEffect->Params.Reverb.ReflectionsPan[0] = pflValues[0]; 51.679 + ALEffect->Params.Reverb.ReflectionsPan[1] = pflValues[1]; 51.680 + ALEffect->Params.Reverb.ReflectionsPan[2] = pflValues[2]; 51.681 + } 51.682 + else 51.683 + alSetError(Context, AL_INVALID_VALUE); 51.684 + break; 51.685 + case AL_EAXREVERB_LATE_REVERB_PAN: 51.686 + if(isfinite(pflValues[0]) && isfinite(pflValues[1]) && isfinite(pflValues[2])) 51.687 + { 51.688 + ALEffect->Params.Reverb.LateReverbPan[0] = pflValues[0]; 51.689 + ALEffect->Params.Reverb.LateReverbPan[1] = pflValues[1]; 51.690 + ALEffect->Params.Reverb.LateReverbPan[2] = pflValues[2]; 51.691 + } 51.692 + else 51.693 + alSetError(Context, AL_INVALID_VALUE); 51.694 + break; 51.695 + 51.696 + default: 51.697 + UnlockContext(Context); 51.698 + alEffectf(effect, param, pflValues[0]); 51.699 + return; 51.700 + } 51.701 + } 51.702 + else 51.703 + { 51.704 + UnlockContext(Context); 51.705 + alEffectf(effect, param, pflValues[0]); 51.706 + return; 51.707 + } 51.708 + } 51.709 + else 51.710 + alSetError(Context, AL_INVALID_NAME); 51.711 + 51.712 + UnlockContext(Context); 51.713 +} 51.714 + 51.715 +AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue) 51.716 +{ 51.717 + ALCcontext *Context; 51.718 + ALCdevice *Device; 51.719 + ALeffect *ALEffect; 51.720 + 51.721 + Context = GetLockedContext(); 51.722 + if(!Context) return; 51.723 + 51.724 + Device = Context->Device; 51.725 + if((ALEffect=LookupEffect(Device->EffectMap, effect)) != NULL) 51.726 + { 51.727 + if(param == AL_EFFECT_TYPE) 51.728 + { 51.729 + *piValue = ALEffect->type; 51.730 + } 51.731 + else if(ALEffect->type == AL_EFFECT_EAXREVERB) 51.732 + { 51.733 + switch(param) 51.734 + { 51.735 + case AL_EAXREVERB_DECAY_HFLIMIT: 51.736 + *piValue = ALEffect->Params.Reverb.DecayHFLimit; 51.737 + break; 51.738 + 51.739 + default: 51.740 + alSetError(Context, AL_INVALID_ENUM); 51.741 + break; 51.742 + } 51.743 + } 51.744 + else if(ALEffect->type == AL_EFFECT_REVERB) 51.745 + { 51.746 + switch(param) 51.747 + { 51.748 + case AL_REVERB_DECAY_HFLIMIT: 51.749 + *piValue = ALEffect->Params.Reverb.DecayHFLimit; 51.750 + break; 51.751 + 51.752 + default: 51.753 + alSetError(Context, AL_INVALID_ENUM); 51.754 + break; 51.755 + } 51.756 + } 51.757 + else if(ALEffect->type == AL_EFFECT_ECHO) 51.758 + { 51.759 + switch(param) 51.760 + { 51.761 + default: 51.762 + alSetError(Context, AL_INVALID_ENUM); 51.763 + break; 51.764 + } 51.765 + } 51.766 + else if(ALEffect->type == AL_EFFECT_RING_MODULATOR) 51.767 + { 51.768 + switch(param) 51.769 + { 51.770 + case AL_RING_MODULATOR_FREQUENCY: 51.771 + *piValue = (ALint)ALEffect->Params.Modulator.Frequency; 51.772 + break; 51.773 + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: 51.774 + *piValue = (ALint)ALEffect->Params.Modulator.HighPassCutoff; 51.775 + break; 51.776 + case AL_RING_MODULATOR_WAVEFORM: 51.777 + *piValue = ALEffect->Params.Modulator.Waveform; 51.778 + break; 51.779 + 51.780 + default: 51.781 + alSetError(Context, AL_INVALID_ENUM); 51.782 + break; 51.783 + } 51.784 + } 51.785 + else 51.786 + alSetError(Context, AL_INVALID_ENUM); 51.787 + } 51.788 + else 51.789 + alSetError(Context, AL_INVALID_NAME); 51.790 + 51.791 + UnlockContext(Context); 51.792 +} 51.793 + 51.794 +AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues) 51.795 +{ 51.796 + /* There are no multi-value int effect parameters */ 51.797 + alGetEffecti(effect, param, piValues); 51.798 +} 51.799 + 51.800 +AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue) 51.801 +{ 51.802 + ALCcontext *Context; 51.803 + ALCdevice *Device; 51.804 + ALeffect *ALEffect; 51.805 + 51.806 + Context = GetLockedContext(); 51.807 + if(!Context) return; 51.808 + 51.809 + Device = Context->Device; 51.810 + if((ALEffect=LookupEffect(Device->EffectMap, effect)) != NULL) 51.811 + { 51.812 + if(ALEffect->type == AL_EFFECT_EAXREVERB) 51.813 + { 51.814 + switch(param) 51.815 + { 51.816 + case AL_EAXREVERB_DENSITY: 51.817 + *pflValue = ALEffect->Params.Reverb.Density; 51.818 + break; 51.819 + 51.820 + case AL_EAXREVERB_DIFFUSION: 51.821 + *pflValue = ALEffect->Params.Reverb.Diffusion; 51.822 + break; 51.823 + 51.824 + case AL_EAXREVERB_GAIN: 51.825 + *pflValue = ALEffect->Params.Reverb.Gain; 51.826 + break; 51.827 + 51.828 + case AL_EAXREVERB_GAINHF: 51.829 + *pflValue = ALEffect->Params.Reverb.GainHF; 51.830 + break; 51.831 + 51.832 + case AL_EAXREVERB_GAINLF: 51.833 + *pflValue = ALEffect->Params.Reverb.GainLF; 51.834 + break; 51.835 + 51.836 + case AL_EAXREVERB_DECAY_TIME: 51.837 + *pflValue = ALEffect->Params.Reverb.DecayTime; 51.838 + break; 51.839 + 51.840 + case AL_EAXREVERB_DECAY_HFRATIO: 51.841 + *pflValue = ALEffect->Params.Reverb.DecayHFRatio; 51.842 + break; 51.843 + 51.844 + case AL_EAXREVERB_DECAY_LFRATIO: 51.845 + *pflValue = ALEffect->Params.Reverb.DecayLFRatio; 51.846 + break; 51.847 + 51.848 + case AL_EAXREVERB_REFLECTIONS_GAIN: 51.849 + *pflValue = ALEffect->Params.Reverb.ReflectionsGain; 51.850 + break; 51.851 + 51.852 + case AL_EAXREVERB_REFLECTIONS_DELAY: 51.853 + *pflValue = ALEffect->Params.Reverb.ReflectionsDelay; 51.854 + break; 51.855 + 51.856 + case AL_EAXREVERB_LATE_REVERB_GAIN: 51.857 + *pflValue = ALEffect->Params.Reverb.LateReverbGain; 51.858 + break; 51.859 + 51.860 + case AL_EAXREVERB_LATE_REVERB_DELAY: 51.861 + *pflValue = ALEffect->Params.Reverb.LateReverbDelay; 51.862 + break; 51.863 + 51.864 + case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: 51.865 + *pflValue = ALEffect->Params.Reverb.AirAbsorptionGainHF; 51.866 + break; 51.867 + 51.868 + case AL_EAXREVERB_ECHO_TIME: 51.869 + *pflValue = ALEffect->Params.Reverb.EchoTime; 51.870 + break; 51.871 + 51.872 + case AL_EAXREVERB_ECHO_DEPTH: 51.873 + *pflValue = ALEffect->Params.Reverb.EchoDepth; 51.874 + break; 51.875 + 51.876 + case AL_EAXREVERB_MODULATION_TIME: 51.877 + *pflValue = ALEffect->Params.Reverb.ModulationTime; 51.878 + break; 51.879 + 51.880 + case AL_EAXREVERB_MODULATION_DEPTH: 51.881 + *pflValue = ALEffect->Params.Reverb.ModulationDepth; 51.882 + break; 51.883 + 51.884 + case AL_EAXREVERB_HFREFERENCE: 51.885 + *pflValue = ALEffect->Params.Reverb.HFReference; 51.886 + break; 51.887 + 51.888 + case AL_EAXREVERB_LFREFERENCE: 51.889 + *pflValue = ALEffect->Params.Reverb.LFReference; 51.890 + break; 51.891 + 51.892 + case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: 51.893 + *pflValue = ALEffect->Params.Reverb.RoomRolloffFactor; 51.894 + break; 51.895 + 51.896 + default: 51.897 + alSetError(Context, AL_INVALID_ENUM); 51.898 + break; 51.899 + } 51.900 + } 51.901 + else if(ALEffect->type == AL_EFFECT_REVERB) 51.902 + { 51.903 + switch(param) 51.904 + { 51.905 + case AL_REVERB_DENSITY: 51.906 + *pflValue = ALEffect->Params.Reverb.Density; 51.907 + break; 51.908 + 51.909 + case AL_REVERB_DIFFUSION: 51.910 + *pflValue = ALEffect->Params.Reverb.Diffusion; 51.911 + break; 51.912 + 51.913 + case AL_REVERB_GAIN: 51.914 + *pflValue = ALEffect->Params.Reverb.Gain; 51.915 + break; 51.916 + 51.917 + case AL_REVERB_GAINHF: 51.918 + *pflValue = ALEffect->Params.Reverb.GainHF; 51.919 + break; 51.920 + 51.921 + case AL_REVERB_DECAY_TIME: 51.922 + *pflValue = ALEffect->Params.Reverb.DecayTime; 51.923 + break; 51.924 + 51.925 + case AL_REVERB_DECAY_HFRATIO: 51.926 + *pflValue = ALEffect->Params.Reverb.DecayHFRatio; 51.927 + break; 51.928 + 51.929 + case AL_REVERB_REFLECTIONS_GAIN: 51.930 + *pflValue = ALEffect->Params.Reverb.ReflectionsGain; 51.931 + break; 51.932 + 51.933 + case AL_REVERB_REFLECTIONS_DELAY: 51.934 + *pflValue = ALEffect->Params.Reverb.ReflectionsDelay; 51.935 + break; 51.936 + 51.937 + case AL_REVERB_LATE_REVERB_GAIN: 51.938 + *pflValue = ALEffect->Params.Reverb.LateReverbGain; 51.939 + break; 51.940 + 51.941 + case AL_REVERB_LATE_REVERB_DELAY: 51.942 + *pflValue = ALEffect->Params.Reverb.LateReverbDelay; 51.943 + break; 51.944 + 51.945 + case AL_REVERB_AIR_ABSORPTION_GAINHF: 51.946 + *pflValue = ALEffect->Params.Reverb.AirAbsorptionGainHF; 51.947 + break; 51.948 + 51.949 + case AL_REVERB_ROOM_ROLLOFF_FACTOR: 51.950 + *pflValue = ALEffect->Params.Reverb.RoomRolloffFactor; 51.951 + break; 51.952 + 51.953 + default: 51.954 + alSetError(Context, AL_INVALID_ENUM); 51.955 + break; 51.956 + } 51.957 + } 51.958 + else if(ALEffect->type == AL_EFFECT_ECHO) 51.959 + { 51.960 + switch(param) 51.961 + { 51.962 + case AL_ECHO_DELAY: 51.963 + *pflValue = ALEffect->Params.Echo.Delay; 51.964 + break; 51.965 + 51.966 + case AL_ECHO_LRDELAY: 51.967 + *pflValue = ALEffect->Params.Echo.LRDelay; 51.968 + break; 51.969 + 51.970 + case AL_ECHO_DAMPING: 51.971 + *pflValue = ALEffect->Params.Echo.Damping; 51.972 + break; 51.973 + 51.974 + case AL_ECHO_FEEDBACK: 51.975 + *pflValue = ALEffect->Params.Echo.Feedback; 51.976 + break; 51.977 + 51.978 + case AL_ECHO_SPREAD: 51.979 + *pflValue = ALEffect->Params.Echo.Spread; 51.980 + break; 51.981 + 51.982 + default: 51.983 + alSetError(Context, AL_INVALID_ENUM); 51.984 + break; 51.985 + } 51.986 + } 51.987 + else if(ALEffect->type == AL_EFFECT_RING_MODULATOR) 51.988 + { 51.989 + switch(param) 51.990 + { 51.991 + case AL_RING_MODULATOR_FREQUENCY: 51.992 + *pflValue = ALEffect->Params.Modulator.Frequency; 51.993 + break; 51.994 + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: 51.995 + *pflValue = ALEffect->Params.Modulator.HighPassCutoff; 51.996 + break; 51.997 + 51.998 + default: 51.999 + alSetError(Context, AL_INVALID_ENUM); 51.1000 + break; 51.1001 + } 51.1002 + } 51.1003 + else if(ALEffect->type == AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT || 51.1004 + ALEffect->type == AL_EFFECT_DEDICATED_DIALOGUE) 51.1005 + { 51.1006 + switch(param) 51.1007 + { 51.1008 + case AL_DEDICATED_GAIN: 51.1009 + *pflValue = ALEffect->Params.Dedicated.Gain; 51.1010 + break; 51.1011 + 51.1012 + default: 51.1013 + alSetError(Context, AL_INVALID_ENUM); 51.1014 + break; 51.1015 + } 51.1016 + } 51.1017 + else 51.1018 + alSetError(Context, AL_INVALID_ENUM); 51.1019 + } 51.1020 + else 51.1021 + alSetError(Context, AL_INVALID_NAME); 51.1022 + 51.1023 + UnlockContext(Context); 51.1024 +} 51.1025 + 51.1026 +AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues) 51.1027 +{ 51.1028 + ALCcontext *Context; 51.1029 + ALCdevice *Device; 51.1030 + ALeffect *ALEffect; 51.1031 + 51.1032 + Context = GetLockedContext(); 51.1033 + if(!Context) return; 51.1034 + 51.1035 + Device = Context->Device; 51.1036 + if((ALEffect=LookupEffect(Device->EffectMap, effect)) != NULL) 51.1037 + { 51.1038 + if(ALEffect->type == AL_EFFECT_EAXREVERB) 51.1039 + { 51.1040 + switch(param) 51.1041 + { 51.1042 + case AL_EAXREVERB_REFLECTIONS_PAN: 51.1043 + pflValues[0] = ALEffect->Params.Reverb.ReflectionsPan[0]; 51.1044 + pflValues[1] = ALEffect->Params.Reverb.ReflectionsPan[1]; 51.1045 + pflValues[2] = ALEffect->Params.Reverb.ReflectionsPan[2]; 51.1046 + break; 51.1047 + case AL_EAXREVERB_LATE_REVERB_PAN: 51.1048 + pflValues[0] = ALEffect->Params.Reverb.LateReverbPan[0]; 51.1049 + pflValues[1] = ALEffect->Params.Reverb.LateReverbPan[1]; 51.1050 + pflValues[2] = ALEffect->Params.Reverb.LateReverbPan[2]; 51.1051 + break; 51.1052 + 51.1053 + default: 51.1054 + UnlockContext(Context); 51.1055 + alGetEffectf(effect, param, pflValues); 51.1056 + return; 51.1057 + } 51.1058 + } 51.1059 + else 51.1060 + { 51.1061 + UnlockContext(Context); 51.1062 + alGetEffectf(effect, param, pflValues); 51.1063 + return; 51.1064 + } 51.1065 + } 51.1066 + else 51.1067 + alSetError(Context, AL_INVALID_NAME); 51.1068 + 51.1069 + UnlockContext(Context); 51.1070 +} 51.1071 + 51.1072 + 51.1073 +ALvoid ReleaseALEffects(ALCdevice *device) 51.1074 +{ 51.1075 + ALsizei i; 51.1076 + for(i = 0;i < device->EffectMap.size;i++) 51.1077 + { 51.1078 + ALeffect *temp = device->EffectMap.array[i].value; 51.1079 + device->EffectMap.array[i].value = NULL; 51.1080 + 51.1081 + // Release effect structure 51.1082 + FreeThunkEntry(temp->effect); 51.1083 + memset(temp, 0, sizeof(ALeffect)); 51.1084 + free(temp); 51.1085 + } 51.1086 +} 51.1087 + 51.1088 + 51.1089 +static void InitEffectParams(ALeffect *effect, ALenum type) 51.1090 +{ 51.1091 + effect->type = type; 51.1092 + switch(type) 51.1093 + { 51.1094 + /* NOTE: Standard reverb and EAX reverb use the same defaults for the 51.1095 + * shared parameters, and EAX's additional parameters default to 51.1096 + * values assumed by standard reverb. 51.1097 + */ 51.1098 + case AL_EFFECT_EAXREVERB: 51.1099 + case AL_EFFECT_REVERB: 51.1100 + effect->Params.Reverb.Density = AL_EAXREVERB_DEFAULT_DENSITY; 51.1101 + effect->Params.Reverb.Diffusion = AL_EAXREVERB_DEFAULT_DIFFUSION; 51.1102 + effect->Params.Reverb.Gain = AL_EAXREVERB_DEFAULT_GAIN; 51.1103 + effect->Params.Reverb.GainHF = AL_EAXREVERB_DEFAULT_GAINHF; 51.1104 + effect->Params.Reverb.GainLF = AL_EAXREVERB_DEFAULT_GAINLF; 51.1105 + effect->Params.Reverb.DecayTime = AL_EAXREVERB_DEFAULT_DECAY_TIME; 51.1106 + effect->Params.Reverb.DecayHFRatio = AL_EAXREVERB_DEFAULT_DECAY_HFRATIO; 51.1107 + effect->Params.Reverb.DecayLFRatio = AL_EAXREVERB_DEFAULT_DECAY_LFRATIO; 51.1108 + effect->Params.Reverb.ReflectionsGain = AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN; 51.1109 + effect->Params.Reverb.ReflectionsDelay = AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY; 51.1110 + effect->Params.Reverb.ReflectionsPan[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; 51.1111 + effect->Params.Reverb.ReflectionsPan[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; 51.1112 + effect->Params.Reverb.ReflectionsPan[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; 51.1113 + effect->Params.Reverb.LateReverbGain = AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN; 51.1114 + effect->Params.Reverb.LateReverbDelay = AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY; 51.1115 + effect->Params.Reverb.LateReverbPan[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; 51.1116 + effect->Params.Reverb.LateReverbPan[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; 51.1117 + effect->Params.Reverb.LateReverbPan[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; 51.1118 + effect->Params.Reverb.EchoTime = AL_EAXREVERB_DEFAULT_ECHO_TIME; 51.1119 + effect->Params.Reverb.EchoDepth = AL_EAXREVERB_DEFAULT_ECHO_DEPTH; 51.1120 + effect->Params.Reverb.ModulationTime = AL_EAXREVERB_DEFAULT_MODULATION_TIME; 51.1121 + effect->Params.Reverb.ModulationDepth = AL_EAXREVERB_DEFAULT_MODULATION_DEPTH; 51.1122 + effect->Params.Reverb.AirAbsorptionGainHF = AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF; 51.1123 + effect->Params.Reverb.HFReference = AL_EAXREVERB_DEFAULT_HFREFERENCE; 51.1124 + effect->Params.Reverb.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE; 51.1125 + effect->Params.Reverb.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; 51.1126 + effect->Params.Reverb.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT; 51.1127 + break; 51.1128 + case AL_EFFECT_ECHO: 51.1129 + effect->Params.Echo.Delay = AL_ECHO_DEFAULT_DELAY; 51.1130 + effect->Params.Echo.LRDelay = AL_ECHO_DEFAULT_LRDELAY; 51.1131 + effect->Params.Echo.Damping = AL_ECHO_DEFAULT_DAMPING; 51.1132 + effect->Params.Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK; 51.1133 + effect->Params.Echo.Spread = AL_ECHO_DEFAULT_SPREAD; 51.1134 + break; 51.1135 + case AL_EFFECT_RING_MODULATOR: 51.1136 + effect->Params.Modulator.Frequency = AL_RING_MODULATOR_DEFAULT_FREQUENCY; 51.1137 + effect->Params.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF; 51.1138 + effect->Params.Modulator.Waveform = AL_RING_MODULATOR_DEFAULT_WAVEFORM; 51.1139 + break; 51.1140 + case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: 51.1141 + case AL_EFFECT_DEDICATED_DIALOGUE: 51.1142 + effect->Params.Dedicated.Gain = 1.0f; 51.1143 + break; 51.1144 + } 51.1145 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 52.2 +++ b/OpenAL32/alError.c Tue Oct 25 13:02:31 2011 -0700 52.3 @@ -0,0 +1,47 @@ 52.4 +/** 52.5 + * OpenAL cross platform audio library 52.6 + * Copyright (C) 1999-2000 by authors. 52.7 + * This library is free software; you can redistribute it and/or 52.8 + * modify it under the terms of the GNU Library General Public 52.9 + * License as published by the Free Software Foundation; either 52.10 + * version 2 of the License, or (at your option) any later version. 52.11 + * 52.12 + * This library is distributed in the hope that it will be useful, 52.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 52.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 52.15 + * Library General Public License for more details. 52.16 + * 52.17 + * You should have received a copy of the GNU Library General Public 52.18 + * License along with this library; if not, write to the 52.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 52.20 + * Boston, MA 02111-1307, USA. 52.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 52.22 + */ 52.23 + 52.24 +#include "config.h" 52.25 + 52.26 +#include "alMain.h" 52.27 +#include "AL/alc.h" 52.28 +#include "alError.h" 52.29 + 52.30 +AL_API ALenum AL_APIENTRY alGetError(ALvoid) 52.31 +{ 52.32 + ALCcontext *Context; 52.33 + ALenum errorCode; 52.34 + 52.35 + Context = GetLockedContext(); 52.36 + if(!Context) return AL_INVALID_OPERATION; 52.37 + 52.38 + errorCode = Context->LastError; 52.39 + Context->LastError = AL_NO_ERROR; 52.40 + 52.41 + UnlockContext(Context); 52.42 + 52.43 + return errorCode; 52.44 +} 52.45 + 52.46 +ALvoid alSetError(ALCcontext *Context, ALenum errorCode) 52.47 +{ 52.48 + if(Context->LastError == AL_NO_ERROR) 52.49 + Context->LastError = errorCode; 52.50 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 53.2 +++ b/OpenAL32/alExtension.c Tue Oct 25 13:02:31 2011 -0700 53.3 @@ -0,0 +1,399 @@ 53.4 +/** 53.5 + * OpenAL cross platform audio library 53.6 + * Copyright (C) 1999-2007 by authors. 53.7 + * This library is free software; you can redistribute it and/or 53.8 + * modify it under the terms of the GNU Library General Public 53.9 + * License as published by the Free Software Foundation; either 53.10 + * version 2 of the License, or (at your option) any later version. 53.11 + * 53.12 + * This library is distributed in the hope that it will be useful, 53.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 53.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 53.15 + * Library General Public License for more details. 53.16 + * 53.17 + * You should have received a copy of the GNU Library General Public 53.18 + * License along with this library; if not, write to the 53.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 53.20 + * Boston, MA 02111-1307, USA. 53.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 53.22 + */ 53.23 + 53.24 +#include "config.h" 53.25 + 53.26 +#include <stdlib.h> 53.27 +#include <string.h> 53.28 +#include <ctype.h> 53.29 + 53.30 +#include "alError.h" 53.31 +#include "alMain.h" 53.32 +#include "alFilter.h" 53.33 +#include "alEffect.h" 53.34 +#include "alAuxEffectSlot.h" 53.35 +#include "alSource.h" 53.36 +#include "alBuffer.h" 53.37 +#include "AL/al.h" 53.38 +#include "AL/alc.h" 53.39 + 53.40 +typedef struct ALenums { 53.41 + const ALchar *enumName; 53.42 + ALenum value; 53.43 +} ALenums; 53.44 + 53.45 + 53.46 +static const ALenums enumeration[] = { 53.47 + // Types 53.48 + { "AL_INVALID", AL_INVALID }, 53.49 + { "AL_NONE", AL_NONE }, 53.50 + { "AL_FALSE", AL_FALSE }, 53.51 + { "AL_TRUE", AL_TRUE }, 53.52 + 53.53 + // Source and Listener Properties 53.54 + { "AL_SOURCE_RELATIVE", AL_SOURCE_RELATIVE }, 53.55 + { "AL_CONE_INNER_ANGLE", AL_CONE_INNER_ANGLE }, 53.56 + { "AL_CONE_OUTER_ANGLE", AL_CONE_OUTER_ANGLE }, 53.57 + { "AL_PITCH", AL_PITCH }, 53.58 + { "AL_POSITION", AL_POSITION }, 53.59 + { "AL_DIRECTION", AL_DIRECTION }, 53.60 + { "AL_VELOCITY", AL_VELOCITY }, 53.61 + { "AL_LOOPING", AL_LOOPING }, 53.62 + { "AL_BUFFER", AL_BUFFER }, 53.63 + { "AL_GAIN", AL_GAIN }, 53.64 + { "AL_MIN_GAIN", AL_MIN_GAIN }, 53.65 + { "AL_MAX_GAIN", AL_MAX_GAIN }, 53.66 + { "AL_ORIENTATION", AL_ORIENTATION }, 53.67 + { "AL_REFERENCE_DISTANCE", AL_REFERENCE_DISTANCE }, 53.68 + { "AL_ROLLOFF_FACTOR", AL_ROLLOFF_FACTOR }, 53.69 + { "AL_CONE_OUTER_GAIN", AL_CONE_OUTER_GAIN }, 53.70 + { "AL_MAX_DISTANCE", AL_MAX_DISTANCE }, 53.71 + { "AL_SEC_OFFSET", AL_SEC_OFFSET }, 53.72 + { "AL_SAMPLE_OFFSET", AL_SAMPLE_OFFSET }, 53.73 + { "AL_SAMPLE_RW_OFFSETS_SOFT", AL_SAMPLE_RW_OFFSETS_SOFT }, 53.74 + { "AL_BYTE_OFFSET", AL_BYTE_OFFSET }, 53.75 + { "AL_BYTE_RW_OFFSETS_SOFT", AL_BYTE_RW_OFFSETS_SOFT }, 53.76 + { "AL_SOURCE_TYPE", AL_SOURCE_TYPE }, 53.77 + { "AL_STATIC", AL_STATIC }, 53.78 + { "AL_STREAMING", AL_STREAMING }, 53.79 + { "AL_UNDETERMINED", AL_UNDETERMINED }, 53.80 + { "AL_METERS_PER_UNIT", AL_METERS_PER_UNIT }, 53.81 + { "AL_VIRTUAL_CHANNELS_SOFT", AL_VIRTUAL_CHANNELS_SOFT }, 53.82 + 53.83 + // Source EFX Properties 53.84 + { "AL_DIRECT_FILTER", AL_DIRECT_FILTER }, 53.85 + { "AL_AUXILIARY_SEND_FILTER", AL_AUXILIARY_SEND_FILTER }, 53.86 + { "AL_AIR_ABSORPTION_FACTOR", AL_AIR_ABSORPTION_FACTOR }, 53.87 + { "AL_ROOM_ROLLOFF_FACTOR", AL_ROOM_ROLLOFF_FACTOR }, 53.88 + { "AL_CONE_OUTER_GAINHF", AL_CONE_OUTER_GAINHF }, 53.89 + { "AL_DIRECT_FILTER_GAINHF_AUTO", AL_DIRECT_FILTER_GAINHF_AUTO }, 53.90 + { "AL_AUXILIARY_SEND_FILTER_GAIN_AUTO", AL_AUXILIARY_SEND_FILTER_GAIN_AUTO }, 53.91 + { "AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO", AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO}, 53.92 + 53.93 + // Source State information 53.94 + { "AL_SOURCE_STATE", AL_SOURCE_STATE }, 53.95 + { "AL_INITIAL", AL_INITIAL }, 53.96 + { "AL_PLAYING", AL_PLAYING }, 53.97 + { "AL_PAUSED", AL_PAUSED }, 53.98 + { "AL_STOPPED", AL_STOPPED }, 53.99 + 53.100 + // Queue information 53.101 + { "AL_BUFFERS_QUEUED", AL_BUFFERS_QUEUED }, 53.102 + { "AL_BUFFERS_PROCESSED", AL_BUFFERS_PROCESSED }, 53.103 + 53.104 + // Buffer Formats 53.105 + { "AL_FORMAT_MONO8", AL_FORMAT_MONO8 }, 53.106 + { "AL_FORMAT_MONO16", AL_FORMAT_MONO16 }, 53.107 + { "AL_FORMAT_MONO_FLOAT32", AL_FORMAT_MONO_FLOAT32 }, 53.108 + { "AL_FORMAT_MONO_DOUBLE_EXT", AL_FORMAT_MONO_DOUBLE_EXT }, 53.109 + { "AL_FORMAT_STEREO8", AL_FORMAT_STEREO8 }, 53.110 + { "AL_FORMAT_STEREO16", AL_FORMAT_STEREO16 }, 53.111 + { "AL_FORMAT_STEREO_FLOAT32", AL_FORMAT_STEREO_FLOAT32 }, 53.112 + { "AL_FORMAT_STEREO_DOUBLE_EXT", AL_FORMAT_STEREO_DOUBLE_EXT }, 53.113 + { "AL_FORMAT_MONO_IMA4", AL_FORMAT_MONO_IMA4 }, 53.114 + { "AL_FORMAT_STEREO_IMA4", AL_FORMAT_STEREO_IMA4 }, 53.115 + { "AL_FORMAT_QUAD8_LOKI", AL_FORMAT_QUAD8_LOKI }, 53.116 + { "AL_FORMAT_QUAD16_LOKI", AL_FORMAT_QUAD16_LOKI }, 53.117 + { "AL_FORMAT_QUAD8", AL_FORMAT_QUAD8 }, 53.118 + { "AL_FORMAT_QUAD16", AL_FORMAT_QUAD16 }, 53.119 + { "AL_FORMAT_QUAD32", AL_FORMAT_QUAD32 }, 53.120 + { "AL_FORMAT_51CHN8", AL_FORMAT_51CHN8 }, 53.121 + { "AL_FORMAT_51CHN16", AL_FORMAT_51CHN16 }, 53.122 + { "AL_FORMAT_51CHN32", AL_FORMAT_51CHN32 }, 53.123 + { "AL_FORMAT_61CHN8", AL_FORMAT_61CHN8 }, 53.124 + { "AL_FORMAT_61CHN16", AL_FORMAT_61CHN16 }, 53.125 + { "AL_FORMAT_61CHN32", AL_FORMAT_61CHN32 }, 53.126 + { "AL_FORMAT_71CHN8", AL_FORMAT_71CHN8 }, 53.127 + { "AL_FORMAT_71CHN16", AL_FORMAT_71CHN16 }, 53.128 + { "AL_FORMAT_71CHN32", AL_FORMAT_71CHN32 }, 53.129 + { "AL_FORMAT_REAR8", AL_FORMAT_REAR8 }, 53.130 + { "AL_FORMAT_REAR16", AL_FORMAT_REAR16 }, 53.131 + { "AL_FORMAT_REAR32", AL_FORMAT_REAR32 }, 53.132 + { "AL_FORMAT_MONO_MULAW", AL_FORMAT_MONO_MULAW }, 53.133 + { "AL_FORMAT_MONO_MULAW_EXT", AL_FORMAT_MONO_MULAW }, 53.134 + { "AL_FORMAT_STEREO_MULAW", AL_FORMAT_STEREO_MULAW }, 53.135 + { "AL_FORMAT_STEREO_MULAW_EXT", AL_FORMAT_STEREO_MULAW }, 53.136 + { "AL_FORMAT_QUAD_MULAW", AL_FORMAT_QUAD_MULAW }, 53.137 + { "AL_FORMAT_51CHN_MULAW", AL_FORMAT_51CHN_MULAW }, 53.138 + { "AL_FORMAT_61CHN_MULAW", AL_FORMAT_61CHN_MULAW }, 53.139 + { "AL_FORMAT_71CHN_MULAW", AL_FORMAT_71CHN_MULAW }, 53.140 + { "AL_FORMAT_REAR_MULAW", AL_FORMAT_REAR_MULAW }, 53.141 + 53.142 + // Internal Buffer Formats 53.143 + { "AL_MONO8", AL_MONO8 }, 53.144 + { "AL_MONO16", AL_MONO16 }, 53.145 + { "AL_MONO32F", AL_MONO32F }, 53.146 + { "AL_STEREO8", AL_STEREO8 }, 53.147 + { "AL_STEREO16", AL_STEREO16 }, 53.148 + { "AL_STEREO32F", AL_STEREO32F }, 53.149 + { "AL_QUAD8", AL_QUAD8 }, 53.150 + { "AL_QUAD16", AL_QUAD16 }, 53.151 + { "AL_QUAD32F", AL_QUAD32F }, 53.152 + { "AL_REAR8", AL_REAR8 }, 53.153 + { "AL_REAR16", AL_REAR16 }, 53.154 + { "AL_REAR32F", AL_REAR32F }, 53.155 + { "AL_5POINT1_8", AL_5POINT1_8 }, 53.156 + { "AL_5POINT1_16", AL_5POINT1_16 }, 53.157 + { "AL_5POINT1_32F", AL_5POINT1_32F }, 53.158 + { "AL_6POINT1_8", AL_6POINT1_8 }, 53.159 + { "AL_6POINT1_16", AL_6POINT1_16 }, 53.160 + { "AL_6POINT1_32F", AL_6POINT1_32F }, 53.161 + { "AL_7POINT1_8", AL_7POINT1_8 }, 53.162 + { "AL_7POINT1_16", AL_7POINT1_16 }, 53.163 + { "AL_7POINT1_32F", AL_7POINT1_32F }, 53.164 + 53.165 + // Buffer Channel Configurations 53.166 + { "AL_MONO", AL_MONO }, 53.167 + { "AL_STEREO", AL_STEREO }, 53.168 + { "AL_QUAD", AL_QUAD }, 53.169 + { "AL_REAR", AL_REAR }, 53.170 + { "AL_5POINT1", AL_5POINT1 }, 53.171 + { "AL_6POINT1", AL_6POINT1 }, 53.172 + { "AL_7POINT1", AL_7POINT1 }, 53.173 + 53.174 + // Buffer Sample Types 53.175 + { "AL_BYTE", AL_BYTE }, 53.176 + { "AL_UNSIGNED_BYTE", AL_UNSIGNED_BYTE }, 53.177 + { "AL_SHORT", AL_SHORT }, 53.178 + { "AL_UNSIGNED_SHORT", AL_UNSIGNED_SHORT }, 53.179 + { "AL_INT", AL_INT }, 53.180 + { "AL_UNSIGNED_INT", AL_UNSIGNED_INT }, 53.181 + { "AL_FLOAT", AL_FLOAT }, 53.182 + { "AL_DOUBLE", AL_DOUBLE }, 53.183 + { "AL_MULAW", AL_MULAW }, 53.184 + { "AL_IMA4", AL_IMA4 }, 53.185 + { "AL_BYTE3", AL_BYTE3 }, 53.186 + { "AL_UNSIGNED_BYTE3", AL_UNSIGNED_BYTE3 }, 53.187 + 53.188 + // Buffer attributes 53.189 + { "AL_FREQUENCY", AL_FREQUENCY }, 53.190 + { "AL_BITS", AL_BITS }, 53.191 + { "AL_CHANNELS", AL_CHANNELS }, 53.192 + { "AL_SIZE", AL_SIZE }, 53.193 + 53.194 + // Buffer States (not supported yet) 53.195 + { "AL_UNUSED", AL_UNUSED }, 53.196 + { "AL_PENDING", AL_PENDING }, 53.197 + { "AL_PROCESSED", AL_PROCESSED }, 53.198 + 53.199 + // AL Error Messages 53.200 + { "AL_NO_ERROR", AL_NO_ERROR }, 53.201 + { "AL_INVALID_NAME", AL_INVALID_NAME }, 53.202 + { "AL_INVALID_ENUM", AL_INVALID_ENUM }, 53.203 + { "AL_INVALID_VALUE", AL_INVALID_VALUE }, 53.204 + { "AL_INVALID_OPERATION", AL_INVALID_OPERATION }, 53.205 + { "AL_OUT_OF_MEMORY", AL_OUT_OF_MEMORY }, 53.206 + 53.207 + // Context strings 53.208 + { "AL_VENDOR", AL_VENDOR }, 53.209 + { "AL_VERSION", AL_VERSION }, 53.210 + { "AL_RENDERER", AL_RENDERER }, 53.211 + { "AL_EXTENSIONS", AL_EXTENSIONS }, 53.212 + 53.213 + // Global states 53.214 + { "AL_DOPPLER_FACTOR", AL_DOPPLER_FACTOR }, 53.215 + { "AL_DOPPLER_VELOCITY", AL_DOPPLER_VELOCITY }, 53.216 + { "AL_DISTANCE_MODEL", AL_DISTANCE_MODEL }, 53.217 + { "AL_SPEED_OF_SOUND", AL_SPEED_OF_SOUND }, 53.218 + { "AL_SOURCE_DISTANCE_MODEL", AL_SOURCE_DISTANCE_MODEL }, 53.219 + { "AL_DEFERRED_UPDATES_SOFT", AL_DEFERRED_UPDATES_SOFT }, 53.220 + 53.221 + // Distance Models 53.222 + { "AL_INVERSE_DISTANCE", AL_INVERSE_DISTANCE }, 53.223 + { "AL_INVERSE_DISTANCE_CLAMPED", AL_INVERSE_DISTANCE_CLAMPED }, 53.224 + { "AL_LINEAR_DISTANCE", AL_LINEAR_DISTANCE }, 53.225 + { "AL_LINEAR_DISTANCE_CLAMPED", AL_LINEAR_DISTANCE_CLAMPED }, 53.226 + { "AL_EXPONENT_DISTANCE", AL_EXPONENT_DISTANCE }, 53.227 + { "AL_EXPONENT_DISTANCE_CLAMPED", AL_EXPONENT_DISTANCE_CLAMPED }, 53.228 + 53.229 + // Filter types 53.230 + { "AL_FILTER_TYPE", AL_FILTER_TYPE }, 53.231 + { "AL_FILTER_NULL", AL_FILTER_NULL }, 53.232 + { "AL_FILTER_LOWPASS", AL_FILTER_LOWPASS }, 53.233 +#if 0 53.234 + { "AL_FILTER_HIGHPASS", AL_FILTER_HIGHPASS }, 53.235 + { "AL_FILTER_BANDPASS", AL_FILTER_BANDPASS }, 53.236 +#endif 53.237 + 53.238 + // Filter params 53.239 + { "AL_LOWPASS_GAIN", AL_LOWPASS_GAIN }, 53.240 + { "AL_LOWPASS_GAINHF", AL_LOWPASS_GAINHF }, 53.241 + 53.242 + // Effect types 53.243 + { "AL_EFFECT_TYPE", AL_EFFECT_TYPE }, 53.244 + { "AL_EFFECT_NULL", AL_EFFECT_NULL }, 53.245 + { "AL_EFFECT_REVERB", AL_EFFECT_REVERB }, 53.246 + { "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB }, 53.247 +#if 0 53.248 + { "AL_EFFECT_CHORUS", AL_EFFECT_CHORUS }, 53.249 + { "AL_EFFECT_DISTORTION", AL_EFFECT_DISTORTION }, 53.250 +#endif 53.251 + { "AL_EFFECT_ECHO", AL_EFFECT_ECHO }, 53.252 +#if 0 53.253 + { "AL_EFFECT_FLANGER", AL_EFFECT_FLANGER }, 53.254 + { "AL_EFFECT_FREQUENCY_SHIFTER", AL_EFFECT_FREQUENCY_SHIFTER }, 53.255 + { "AL_EFFECT_VOCAL_MORPHER", AL_EFFECT_VOCAL_MORPHER }, 53.256 + { "AL_EFFECT_PITCH_SHIFTER", AL_EFFECT_PITCH_SHIFTER }, 53.257 +#endif 53.258 + { "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR }, 53.259 +#if 0 53.260 + { "AL_EFFECT_AUTOWAH", AL_EFFECT_AUTOWAH }, 53.261 + { "AL_EFFECT_COMPRESSOR", AL_EFFECT_COMPRESSOR }, 53.262 + { "AL_EFFECT_EQUALIZER", AL_EFFECT_EQUALIZER }, 53.263 +#endif 53.264 + { "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT",AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT}, 53.265 + { "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE }, 53.266 + 53.267 + // Reverb params 53.268 + { "AL_REVERB_DENSITY", AL_REVERB_DENSITY }, 53.269 + { "AL_REVERB_DIFFUSION", AL_REVERB_DIFFUSION }, 53.270 + { "AL_REVERB_GAIN", AL_REVERB_GAIN }, 53.271 + { "AL_REVERB_GAINHF", AL_REVERB_GAINHF }, 53.272 + { "AL_REVERB_DECAY_TIME", AL_REVERB_DECAY_TIME }, 53.273 + { "AL_REVERB_DECAY_HFRATIO", AL_REVERB_DECAY_HFRATIO }, 53.274 + { "AL_REVERB_REFLECTIONS_GAIN", AL_REVERB_REFLECTIONS_GAIN }, 53.275 + { "AL_REVERB_REFLECTIONS_DELAY", AL_REVERB_REFLECTIONS_DELAY }, 53.276 + { "AL_REVERB_LATE_REVERB_GAIN", AL_REVERB_LATE_REVERB_GAIN }, 53.277 + { "AL_REVERB_LATE_REVERB_DELAY", AL_REVERB_LATE_REVERB_DELAY }, 53.278 + { "AL_REVERB_AIR_ABSORPTION_GAINHF", AL_REVERB_AIR_ABSORPTION_GAINHF }, 53.279 + { "AL_REVERB_ROOM_ROLLOFF_FACTOR", AL_REVERB_ROOM_ROLLOFF_FACTOR }, 53.280 + { "AL_REVERB_DECAY_HFLIMIT", AL_REVERB_DECAY_HFLIMIT }, 53.281 + 53.282 + // EAX Reverb params 53.283 + { "AL_EAXREVERB_DENSITY", AL_EAXREVERB_DENSITY }, 53.284 + { "AL_EAXREVERB_DIFFUSION", AL_EAXREVERB_DIFFUSION }, 53.285 + { "AL_EAXREVERB_GAIN", AL_EAXREVERB_GAIN }, 53.286 + { "AL_EAXREVERB_GAINHF", AL_EAXREVERB_GAINHF }, 53.287 + { "AL_EAXREVERB_GAINLF", AL_EAXREVERB_GAINLF }, 53.288 + { "AL_EAXREVERB_DECAY_TIME", AL_EAXREVERB_DECAY_TIME }, 53.289 + { "AL_EAXREVERB_DECAY_HFRATIO", AL_EAXREVERB_DECAY_HFRATIO }, 53.290 + { "AL_EAXREVERB_DECAY_LFRATIO", AL_EAXREVERB_DECAY_LFRATIO }, 53.291 + { "AL_EAXREVERB_REFLECTIONS_GAIN", AL_EAXREVERB_REFLECTIONS_GAIN }, 53.292 + { "AL_EAXREVERB_REFLECTIONS_DELAY", AL_EAXREVERB_REFLECTIONS_DELAY }, 53.293 + { "AL_EAXREVERB_REFLECTIONS_PAN", AL_EAXREVERB_REFLECTIONS_PAN }, 53.294 + { "AL_EAXREVERB_LATE_REVERB_GAIN", AL_EAXREVERB_LATE_REVERB_GAIN }, 53.295 + { "AL_EAXREVERB_LATE_REVERB_DELAY", AL_EAXREVERB_LATE_REVERB_DELAY }, 53.296 + { "AL_EAXREVERB_LATE_REVERB_PAN", AL_EAXREVERB_LATE_REVERB_PAN }, 53.297 + { "AL_EAXREVERB_ECHO_TIME", AL_EAXREVERB_ECHO_TIME }, 53.298 + { "AL_EAXREVERB_ECHO_DEPTH", AL_EAXREVERB_ECHO_DEPTH }, 53.299 + { "AL_EAXREVERB_MODULATION_TIME", AL_EAXREVERB_MODULATION_TIME }, 53.300 + { "AL_EAXREVERB_MODULATION_DEPTH", AL_EAXREVERB_MODULATION_DEPTH }, 53.301 + { "AL_EAXREVERB_AIR_ABSORPTION_GAINHF", AL_EAXREVERB_AIR_ABSORPTION_GAINHF }, 53.302 + { "AL_EAXREVERB_HFREFERENCE", AL_EAXREVERB_HFREFERENCE }, 53.303 + { "AL_EAXREVERB_LFREFERENCE", AL_EAXREVERB_LFREFERENCE }, 53.304 + { "AL_EAXREVERB_ROOM_ROLLOFF_FACTOR", AL_EAXREVERB_ROOM_ROLLOFF_FACTOR }, 53.305 + { "AL_EAXREVERB_DECAY_HFLIMIT", AL_EAXREVERB_DECAY_HFLIMIT }, 53.306 + 53.307 + // Echo params 53.308 + { "AL_ECHO_DELAY", AL_ECHO_DELAY }, 53.309 + { "AL_ECHO_LRDELAY", AL_ECHO_LRDELAY }, 53.310 + { "AL_ECHO_DAMPING", AL_ECHO_DAMPING }, 53.311 + { "AL_ECHO_FEEDBACK", AL_ECHO_FEEDBACK }, 53.312 + { "AL_ECHO_SPREAD", AL_ECHO_SPREAD }, 53.313 + 53.314 + // Ring Modulator params 53.315 + { "AL_RING_MODULATOR_FREQUENCY", AL_RING_MODULATOR_FREQUENCY }, 53.316 + { "AL_RING_MODULATOR_HIGHPASS_CUTOFF", AL_RING_MODULATOR_HIGHPASS_CUTOFF }, 53.317 + { "AL_RING_MODULATOR_WAVEFORM", AL_RING_MODULATOR_WAVEFORM }, 53.318 + 53.319 + // Dedicated Dialogue/LFE params 53.320 + { "AL_DEDICATED_GAIN", AL_DEDICATED_GAIN }, 53.321 + 53.322 + 53.323 + // Default 53.324 + { NULL, (ALenum)0 } 53.325 +}; 53.326 + 53.327 + 53.328 +const struct EffectList EffectList[] = { 53.329 + { "eaxreverb", EAXREVERB, "AL_EFFECT_EAXREVERB", AL_EFFECT_EAXREVERB }, 53.330 + { "reverb", REVERB, "AL_EFFECT_REVERB", AL_EFFECT_REVERB }, 53.331 + { "echo", ECHO, "AL_EFFECT_ECHO", AL_EFFECT_ECHO }, 53.332 + { "modulator", MODULATOR, "AL_EFFECT_RING_MODULATOR", AL_EFFECT_RING_MODULATOR }, 53.333 + { "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT", AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT }, 53.334 + { "dedicated", DEDICATED, "AL_EFFECT_DEDICATED_DIALOGUE", AL_EFFECT_DEDICATED_DIALOGUE }, 53.335 + { NULL, 0, NULL, (ALenum)0 } 53.336 +}; 53.337 + 53.338 + 53.339 +AL_API ALboolean AL_APIENTRY alIsExtensionPresent(const ALchar *extName) 53.340 +{ 53.341 + ALboolean bIsSupported = AL_FALSE; 53.342 + ALCcontext *Context; 53.343 + const char *ptr; 53.344 + size_t len; 53.345 + 53.346 + Context = GetLockedContext(); 53.347 + if(!Context) return AL_FALSE; 53.348 + 53.349 + if(!extName) 53.350 + alSetError(Context, AL_INVALID_VALUE); 53.351 + else 53.352 + { 53.353 + len = strlen(extName); 53.354 + ptr = Context->ExtensionList; 53.355 + while(ptr && *ptr) 53.356 + { 53.357 + if(strncasecmp(ptr, extName, len) == 0 && 53.358 + (ptr[len] == '\0' || isspace(ptr[len]))) 53.359 + { 53.360 + bIsSupported = AL_TRUE; 53.361 + break; 53.362 + } 53.363 + if((ptr=strchr(ptr, ' ')) != NULL) 53.364 + { 53.365 + do { 53.366 + ++ptr; 53.367 + } while(isspace(*ptr)); 53.368 + } 53.369 + } 53.370 + } 53.371 + 53.372 + UnlockContext(Context); 53.373 + 53.374 + return bIsSupported; 53.375 +} 53.376 + 53.377 + 53.378 +AL_API ALvoid* AL_APIENTRY alGetProcAddress(const ALchar *funcName) 53.379 +{ 53.380 + if(!funcName) 53.381 + return NULL; 53.382 + return alcGetProcAddress(NULL, funcName); 53.383 +} 53.384 + 53.385 +AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) 53.386 +{ 53.387 + ALsizei i; 53.388 + 53.389 + for(i = 0;EffectList[i].ename;i++) 53.390 + { 53.391 + if(DisabledEffects[EffectList[i].type] && 53.392 + strcmp(EffectList[i].ename, enumName) == 0) 53.393 + return (ALenum)0; 53.394 + } 53.395 + 53.396 + i = 0; 53.397 + while(enumeration[i].enumName && 53.398 + strcmp(enumeration[i].enumName, enumName) != 0) 53.399 + i++; 53.400 + 53.401 + return enumeration[i].value; 53.402 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 54.2 +++ b/OpenAL32/alFilter.c Tue Oct 25 13:02:31 2011 -0700 54.3 @@ -0,0 +1,420 @@ 54.4 +/** 54.5 + * OpenAL cross platform audio library 54.6 + * Copyright (C) 1999-2007 by authors. 54.7 + * This library is free software; you can redistribute it and/or 54.8 + * modify it under the terms of the GNU Library General Public 54.9 + * License as published by the Free Software Foundation; either 54.10 + * version 2 of the License, or (at your option) any later version. 54.11 + * 54.12 + * This library is distributed in the hope that it will be useful, 54.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 54.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 54.15 + * Library General Public License for more details. 54.16 + * 54.17 + * You should have received a copy of the GNU Library General Public 54.18 + * License along with this library; if not, write to the 54.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 54.20 + * Boston, MA 02111-1307, USA. 54.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 54.22 + */ 54.23 + 54.24 +#include "config.h" 54.25 + 54.26 +#include <stdlib.h> 54.27 + 54.28 +#include "AL/al.h" 54.29 +#include "AL/alc.h" 54.30 +#include "alMain.h" 54.31 +#include "alFilter.h" 54.32 +#include "alThunk.h" 54.33 +#include "alError.h" 54.34 + 54.35 + 54.36 +static void InitFilterParams(ALfilter *filter, ALenum type); 54.37 + 54.38 +#define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k))) 54.39 + 54.40 +AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters) 54.41 +{ 54.42 + ALCcontext *Context; 54.43 + ALsizei i=0; 54.44 + 54.45 + Context = GetLockedContext(); 54.46 + if(!Context) return; 54.47 + 54.48 + if(n < 0 || IsBadWritePtr((void*)filters, n * sizeof(ALuint))) 54.49 + alSetError(Context, AL_INVALID_VALUE); 54.50 + else 54.51 + { 54.52 + ALCdevice *device = Context->Device; 54.53 + ALenum err; 54.54 + 54.55 + while(i < n) 54.56 + { 54.57 + ALfilter *filter = calloc(1, sizeof(ALfilter)); 54.58 + if(!filter) 54.59 + { 54.60 + alSetError(Context, AL_OUT_OF_MEMORY); 54.61 + alDeleteFilters(i, filters); 54.62 + break; 54.63 + } 54.64 + 54.65 + err = NewThunkEntry(&filter->filter); 54.66 + if(err == AL_NO_ERROR) 54.67 + err = InsertUIntMapEntry(&device->FilterMap, filter->filter, filter); 54.68 + if(err != AL_NO_ERROR) 54.69 + { 54.70 + FreeThunkEntry(filter->filter); 54.71 + memset(filter, 0, sizeof(ALfilter)); 54.72 + free(filter); 54.73 + 54.74 + alSetError(Context, err); 54.75 + alDeleteFilters(i, filters); 54.76 + break; 54.77 + } 54.78 + 54.79 + filters[i++] = filter->filter; 54.80 + InitFilterParams(filter, AL_FILTER_NULL); 54.81 + } 54.82 + } 54.83 + 54.84 + UnlockContext(Context); 54.85 +} 54.86 + 54.87 +AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters) 54.88 +{ 54.89 + ALCcontext *Context; 54.90 + ALCdevice *device; 54.91 + ALfilter *ALFilter; 54.92 + ALboolean Failed; 54.93 + ALsizei i; 54.94 + 54.95 + Context = GetLockedContext(); 54.96 + if(!Context) return; 54.97 + 54.98 + Failed = AL_TRUE; 54.99 + device = Context->Device; 54.100 + if(n < 0) 54.101 + alSetError(Context, AL_INVALID_VALUE); 54.102 + else 54.103 + { 54.104 + Failed = AL_FALSE; 54.105 + // Check that all filters are valid 54.106 + for(i = 0;i < n;i++) 54.107 + { 54.108 + if(!filters[i]) 54.109 + continue; 54.110 + 54.111 + if(LookupFilter(device->FilterMap, filters[i]) == NULL) 54.112 + { 54.113 + alSetError(Context, AL_INVALID_NAME); 54.114 + Failed = AL_TRUE; 54.115 + break; 54.116 + } 54.117 + } 54.118 + } 54.119 + 54.120 + if(!Failed) 54.121 + { 54.122 + // All filters are valid 54.123 + for(i = 0;i < n;i++) 54.124 + { 54.125 + // Recheck that the filter is valid, because there could be duplicated names 54.126 + if((ALFilter=LookupFilter(device->FilterMap, filters[i])) == NULL) 54.127 + continue; 54.128 + 54.129 + RemoveUIntMapKey(&device->FilterMap, ALFilter->filter); 54.130 + FreeThunkEntry(ALFilter->filter); 54.131 + 54.132 + memset(ALFilter, 0, sizeof(ALfilter)); 54.133 + free(ALFilter); 54.134 + } 54.135 + } 54.136 + 54.137 + UnlockContext(Context); 54.138 +} 54.139 + 54.140 +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter) 54.141 +{ 54.142 + ALCcontext *Context; 54.143 + ALboolean result; 54.144 + 54.145 + Context = GetLockedContext(); 54.146 + if(!Context) return AL_FALSE; 54.147 + 54.148 + result = ((!filter || LookupFilter(Context->Device->FilterMap, filter)) ? 54.149 + AL_TRUE : AL_FALSE); 54.150 + 54.151 + UnlockContext(Context); 54.152 + 54.153 + return result; 54.154 +} 54.155 + 54.156 +AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue) 54.157 +{ 54.158 + ALCcontext *Context; 54.159 + ALCdevice *Device; 54.160 + ALfilter *ALFilter; 54.161 + 54.162 + Context = GetLockedContext(); 54.163 + if(!Context) return; 54.164 + 54.165 + Device = Context->Device; 54.166 + if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL) 54.167 + { 54.168 + switch(param) 54.169 + { 54.170 + case AL_FILTER_TYPE: 54.171 + if(iValue == AL_FILTER_NULL || 54.172 + iValue == AL_FILTER_LOWPASS) 54.173 + InitFilterParams(ALFilter, iValue); 54.174 + else 54.175 + alSetError(Context, AL_INVALID_VALUE); 54.176 + break; 54.177 + 54.178 + default: 54.179 + alSetError(Context, AL_INVALID_ENUM); 54.180 + break; 54.181 + } 54.182 + } 54.183 + else 54.184 + alSetError(Context, AL_INVALID_NAME); 54.185 + 54.186 + UnlockContext(Context); 54.187 +} 54.188 + 54.189 +AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues) 54.190 +{ 54.191 + ALCcontext *Context; 54.192 + ALCdevice *Device; 54.193 + 54.194 + switch(param) 54.195 + { 54.196 + case AL_FILTER_TYPE: 54.197 + alFilteri(filter, param, piValues[0]); 54.198 + return; 54.199 + } 54.200 + 54.201 + Context = GetLockedContext(); 54.202 + if(!Context) return; 54.203 + 54.204 + Device = Context->Device; 54.205 + if(LookupFilter(Device->FilterMap, filter) != NULL) 54.206 + { 54.207 + switch(param) 54.208 + { 54.209 + default: 54.210 + alSetError(Context, AL_INVALID_ENUM); 54.211 + break; 54.212 + } 54.213 + } 54.214 + else 54.215 + alSetError(Context, AL_INVALID_NAME); 54.216 + 54.217 + UnlockContext(Context); 54.218 +} 54.219 + 54.220 +AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue) 54.221 +{ 54.222 + ALCcontext *Context; 54.223 + ALCdevice *Device; 54.224 + ALfilter *ALFilter; 54.225 + 54.226 + Context = GetLockedContext(); 54.227 + if(!Context) return; 54.228 + 54.229 + Device = Context->Device; 54.230 + if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL) 54.231 + { 54.232 + switch(ALFilter->type) 54.233 + { 54.234 + case AL_FILTER_LOWPASS: 54.235 + switch(param) 54.236 + { 54.237 + case AL_LOWPASS_GAIN: 54.238 + if(flValue >= AL_LOWPASS_MIN_GAIN && 54.239 + flValue <= AL_LOWPASS_MAX_GAIN) 54.240 + ALFilter->Gain = flValue; 54.241 + else 54.242 + alSetError(Context, AL_INVALID_VALUE); 54.243 + break; 54.244 + 54.245 + case AL_LOWPASS_GAINHF: 54.246 + if(flValue >= AL_LOWPASS_MIN_GAINHF && 54.247 + flValue <= AL_LOWPASS_MAX_GAINHF) 54.248 + ALFilter->GainHF = flValue; 54.249 + else 54.250 + alSetError(Context, AL_INVALID_VALUE); 54.251 + break; 54.252 + 54.253 + default: 54.254 + alSetError(Context, AL_INVALID_ENUM); 54.255 + break; 54.256 + } 54.257 + break; 54.258 + 54.259 + default: 54.260 + alSetError(Context, AL_INVALID_ENUM); 54.261 + break; 54.262 + } 54.263 + } 54.264 + else 54.265 + alSetError(Context, AL_INVALID_NAME); 54.266 + 54.267 + UnlockContext(Context); 54.268 +} 54.269 + 54.270 +AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues) 54.271 +{ 54.272 + /* There are currently no multi-value filter parameters */ 54.273 + alFilterf(filter, param, pflValues[0]); 54.274 +} 54.275 + 54.276 +AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue) 54.277 +{ 54.278 + ALCcontext *Context; 54.279 + ALCdevice *Device; 54.280 + ALfilter *ALFilter; 54.281 + 54.282 + Context = GetLockedContext(); 54.283 + if(!Context) return; 54.284 + 54.285 + Device = Context->Device; 54.286 + if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL) 54.287 + { 54.288 + switch(param) 54.289 + { 54.290 + case AL_FILTER_TYPE: 54.291 + *piValue = ALFilter->type; 54.292 + break; 54.293 + 54.294 + default: 54.295 + alSetError(Context, AL_INVALID_ENUM); 54.296 + break; 54.297 + } 54.298 + } 54.299 + else 54.300 + alSetError(Context, AL_INVALID_NAME); 54.301 + 54.302 + UnlockContext(Context); 54.303 +} 54.304 + 54.305 +AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues) 54.306 +{ 54.307 + ALCcontext *Context; 54.308 + ALCdevice *Device; 54.309 + 54.310 + switch(param) 54.311 + { 54.312 + case AL_FILTER_TYPE: 54.313 + alGetFilteri(filter, param, piValues); 54.314 + return; 54.315 + } 54.316 + 54.317 + Context = GetLockedContext(); 54.318 + if(!Context) return; 54.319 + 54.320 + Device = Context->Device; 54.321 + if(LookupFilter(Device->FilterMap, filter) != NULL) 54.322 + { 54.323 + switch(param) 54.324 + { 54.325 + default: 54.326 + alSetError(Context, AL_INVALID_ENUM); 54.327 + break; 54.328 + } 54.329 + } 54.330 + else 54.331 + alSetError(Context, AL_INVALID_NAME); 54.332 + 54.333 + UnlockContext(Context); 54.334 +} 54.335 + 54.336 +AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue) 54.337 +{ 54.338 + ALCcontext *Context; 54.339 + ALCdevice *Device; 54.340 + ALfilter *ALFilter; 54.341 + 54.342 + Context = GetLockedContext(); 54.343 + if(!Context) return; 54.344 + 54.345 + Device = Context->Device; 54.346 + if((ALFilter=LookupFilter(Device->FilterMap, filter)) != NULL) 54.347 + { 54.348 + switch(ALFilter->type) 54.349 + { 54.350 + case AL_FILTER_LOWPASS: 54.351 + switch(param) 54.352 + { 54.353 + case AL_LOWPASS_GAIN: 54.354 + *pflValue = ALFilter->Gain; 54.355 + break; 54.356 + 54.357 + case AL_LOWPASS_GAINHF: 54.358 + *pflValue = ALFilter->GainHF; 54.359 + break; 54.360 + 54.361 + default: 54.362 + alSetError(Context, AL_INVALID_ENUM); 54.363 + break; 54.364 + } 54.365 + break; 54.366 + 54.367 + default: 54.368 + alSetError(Context, AL_INVALID_ENUM); 54.369 + break; 54.370 + } 54.371 + } 54.372 + else 54.373 + alSetError(Context, AL_INVALID_NAME); 54.374 + 54.375 + UnlockContext(Context); 54.376 +} 54.377 + 54.378 +AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues) 54.379 +{ 54.380 + /* There are currently no multi-value filter parameters */ 54.381 + alGetFilterf(filter, param, pflValues); 54.382 +} 54.383 + 54.384 + 54.385 +ALfloat lpCoeffCalc(ALfloat g, ALfloat cw) 54.386 +{ 54.387 + ALfloat a = 0.0f; 54.388 + 54.389 + /* Be careful with gains < 0.01, as that causes the coefficient 54.390 + * head towards 1, which will flatten the signal */ 54.391 + if(g < 0.9999f) /* 1-epsilon */ 54.392 + { 54.393 + g = maxf(g, 0.01f); 54.394 + a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / 54.395 + (1 - g); 54.396 + } 54.397 + 54.398 + return a; 54.399 +} 54.400 + 54.401 +ALvoid ReleaseALFilters(ALCdevice *device) 54.402 +{ 54.403 + ALsizei i; 54.404 + for(i = 0;i < device->FilterMap.size;i++) 54.405 + { 54.406 + ALfilter *temp = device->FilterMap.array[i].value; 54.407 + device->FilterMap.array[i].value = NULL; 54.408 + 54.409 + // Release filter structure 54.410 + FreeThunkEntry(temp->filter); 54.411 + memset(temp, 0, sizeof(ALfilter)); 54.412 + free(temp); 54.413 + } 54.414 +} 54.415 + 54.416 + 54.417 +static void InitFilterParams(ALfilter *filter, ALenum type) 54.418 +{ 54.419 + filter->type = type; 54.420 + 54.421 + filter->Gain = AL_LOWPASS_DEFAULT_GAIN; 54.422 + filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF; 54.423 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 55.2 +++ b/OpenAL32/alListener.c Tue Oct 25 13:02:31 2011 -0700 55.3 @@ -0,0 +1,465 @@ 55.4 +/** 55.5 + * OpenAL cross platform audio library 55.6 + * Copyright (C) 1999-2000 by authors. 55.7 + * This library is free software; you can redistribute it and/or 55.8 + * modify it under the terms of the GNU Library General Public 55.9 + * License as published by the Free Software Foundation; either 55.10 + * version 2 of the License, or (at your option) any later version. 55.11 + * 55.12 + * This library is distributed in the hope that it will be useful, 55.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 55.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 55.15 + * Library General Public License for more details. 55.16 + * 55.17 + * You should have received a copy of the GNU Library General Public 55.18 + * License along with this library; if not, write to the 55.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 55.20 + * Boston, MA 02111-1307, USA. 55.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 55.22 + */ 55.23 + 55.24 +#include "config.h" 55.25 + 55.26 +#include "alMain.h" 55.27 +#include "AL/alc.h" 55.28 +#include "alError.h" 55.29 +#include "alListener.h" 55.30 +#include "alSource.h" 55.31 + 55.32 +AL_API ALvoid AL_APIENTRY alListenerf(ALenum eParam, ALfloat flValue) 55.33 +{ 55.34 + ALCcontext *pContext; 55.35 + 55.36 + pContext = GetLockedContext(); 55.37 + if(!pContext) return; 55.38 + 55.39 + switch(eParam) 55.40 + { 55.41 + case AL_GAIN: 55.42 + if(flValue >= 0.0f && isfinite(flValue)) 55.43 + { 55.44 + pContext->Listener.Gain = flValue; 55.45 + pContext->UpdateSources = AL_TRUE; 55.46 + } 55.47 + else 55.48 + alSetError(pContext, AL_INVALID_VALUE); 55.49 + break; 55.50 + 55.51 + case AL_METERS_PER_UNIT: 55.52 + if(flValue > 0.0f && isfinite(flValue)) 55.53 + { 55.54 + pContext->Listener.MetersPerUnit = flValue; 55.55 + pContext->UpdateSources = AL_TRUE; 55.56 + } 55.57 + else 55.58 + alSetError(pContext, AL_INVALID_VALUE); 55.59 + break; 55.60 + 55.61 + default: 55.62 + alSetError(pContext, AL_INVALID_ENUM); 55.63 + break; 55.64 + } 55.65 + 55.66 + UnlockContext(pContext); 55.67 +} 55.68 + 55.69 + 55.70 +AL_API ALvoid AL_APIENTRY alListener3f(ALenum eParam, ALfloat flValue1, ALfloat flValue2, ALfloat flValue3) 55.71 +{ 55.72 + ALCcontext *pContext; 55.73 + 55.74 + pContext = GetLockedContext(); 55.75 + if(!pContext) return; 55.76 + 55.77 + switch(eParam) 55.78 + { 55.79 + case AL_POSITION: 55.80 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 55.81 + { 55.82 + pContext->Listener.Position[0] = flValue1; 55.83 + pContext->Listener.Position[1] = flValue2; 55.84 + pContext->Listener.Position[2] = flValue3; 55.85 + pContext->UpdateSources = AL_TRUE; 55.86 + } 55.87 + else 55.88 + alSetError(pContext, AL_INVALID_VALUE); 55.89 + break; 55.90 + 55.91 + case AL_VELOCITY: 55.92 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 55.93 + { 55.94 + pContext->Listener.Velocity[0] = flValue1; 55.95 + pContext->Listener.Velocity[1] = flValue2; 55.96 + pContext->Listener.Velocity[2] = flValue3; 55.97 + pContext->UpdateSources = AL_TRUE; 55.98 + } 55.99 + else 55.100 + alSetError(pContext, AL_INVALID_VALUE); 55.101 + break; 55.102 + 55.103 + default: 55.104 + alSetError(pContext, AL_INVALID_ENUM); 55.105 + break; 55.106 + } 55.107 + 55.108 + UnlockContext(pContext); 55.109 +} 55.110 + 55.111 + 55.112 +AL_API ALvoid AL_APIENTRY alListenerfv(ALenum eParam, const ALfloat *pflValues) 55.113 +{ 55.114 + ALCcontext *pContext; 55.115 + 55.116 + if(pflValues) 55.117 + { 55.118 + switch(eParam) 55.119 + { 55.120 + case AL_GAIN: 55.121 + case AL_METERS_PER_UNIT: 55.122 + alListenerf(eParam, pflValues[0]); 55.123 + return; 55.124 + 55.125 + case AL_POSITION: 55.126 + case AL_VELOCITY: 55.127 + alListener3f(eParam, pflValues[0], pflValues[1], pflValues[2]); 55.128 + return; 55.129 + } 55.130 + } 55.131 + 55.132 + pContext = GetLockedContext(); 55.133 + if(!pContext) return; 55.134 + 55.135 + if(pflValues) 55.136 + { 55.137 + switch(eParam) 55.138 + { 55.139 + case AL_ORIENTATION: 55.140 + if(isfinite(pflValues[0]) && isfinite(pflValues[1]) && 55.141 + isfinite(pflValues[2]) && isfinite(pflValues[3]) && 55.142 + isfinite(pflValues[4]) && isfinite(pflValues[5])) 55.143 + { 55.144 + // AT then UP 55.145 + pContext->Listener.Forward[0] = pflValues[0]; 55.146 + pContext->Listener.Forward[1] = pflValues[1]; 55.147 + pContext->Listener.Forward[2] = pflValues[2]; 55.148 + pContext->Listener.Up[0] = pflValues[3]; 55.149 + pContext->Listener.Up[1] = pflValues[4]; 55.150 + pContext->Listener.Up[2] = pflValues[5]; 55.151 + pContext->UpdateSources = AL_TRUE; 55.152 + } 55.153 + else 55.154 + alSetError(pContext, AL_INVALID_VALUE); 55.155 + break; 55.156 + 55.157 + default: 55.158 + alSetError(pContext, AL_INVALID_ENUM); 55.159 + break; 55.160 + } 55.161 + } 55.162 + else 55.163 + alSetError(pContext, AL_INVALID_VALUE); 55.164 + 55.165 + UnlockContext(pContext); 55.166 +} 55.167 + 55.168 + 55.169 +AL_API ALvoid AL_APIENTRY alListeneri(ALenum eParam, ALint lValue) 55.170 +{ 55.171 + ALCcontext *pContext; 55.172 + 55.173 + (void)lValue; 55.174 + 55.175 + pContext = GetLockedContext(); 55.176 + if(!pContext) return; 55.177 + 55.178 + switch(eParam) 55.179 + { 55.180 + default: 55.181 + alSetError(pContext, AL_INVALID_ENUM); 55.182 + break; 55.183 + } 55.184 + 55.185 + UnlockContext(pContext); 55.186 +} 55.187 + 55.188 + 55.189 +AL_API void AL_APIENTRY alListener3i(ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3) 55.190 +{ 55.191 + ALCcontext *pContext; 55.192 + 55.193 + switch(eParam) 55.194 + { 55.195 + case AL_POSITION: 55.196 + case AL_VELOCITY: 55.197 + alListener3f(eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3); 55.198 + return; 55.199 + } 55.200 + 55.201 + pContext = GetLockedContext(); 55.202 + if(!pContext) return; 55.203 + 55.204 + switch(eParam) 55.205 + { 55.206 + default: 55.207 + alSetError(pContext, AL_INVALID_ENUM); 55.208 + break; 55.209 + } 55.210 + 55.211 + UnlockContext(pContext); 55.212 +} 55.213 + 55.214 + 55.215 +AL_API void AL_APIENTRY alListeneriv( ALenum eParam, const ALint* plValues ) 55.216 +{ 55.217 + ALCcontext *pContext; 55.218 + ALfloat flValues[6]; 55.219 + 55.220 + if(plValues) 55.221 + { 55.222 + switch(eParam) 55.223 + { 55.224 + case AL_POSITION: 55.225 + case AL_VELOCITY: 55.226 + alListener3f(eParam, plValues[0], plValues[1], plValues[2]); 55.227 + return; 55.228 + 55.229 + case AL_ORIENTATION: 55.230 + flValues[0] = (ALfloat)plValues[0]; 55.231 + flValues[1] = (ALfloat)plValues[1]; 55.232 + flValues[2] = (ALfloat)plValues[2]; 55.233 + flValues[3] = (ALfloat)plValues[3]; 55.234 + flValues[4] = (ALfloat)plValues[4]; 55.235 + flValues[5] = (ALfloat)plValues[5]; 55.236 + alListenerfv(eParam, flValues); 55.237 + return; 55.238 + } 55.239 + } 55.240 + 55.241 + pContext = GetLockedContext(); 55.242 + if(!pContext) return; 55.243 + 55.244 + if(plValues) 55.245 + { 55.246 + switch(eParam) 55.247 + { 55.248 + default: 55.249 + alSetError(pContext, AL_INVALID_ENUM); 55.250 + break; 55.251 + } 55.252 + } 55.253 + else 55.254 + alSetError(pContext, AL_INVALID_VALUE); 55.255 + 55.256 + UnlockContext(pContext); 55.257 +} 55.258 + 55.259 + 55.260 +AL_API ALvoid AL_APIENTRY alGetListenerf(ALenum eParam, ALfloat *pflValue) 55.261 +{ 55.262 + ALCcontext *pContext; 55.263 + 55.264 + pContext = GetLockedContext(); 55.265 + if(!pContext) return; 55.266 + 55.267 + if(pflValue) 55.268 + { 55.269 + switch(eParam) 55.270 + { 55.271 + case AL_GAIN: 55.272 + *pflValue = pContext->Listener.Gain; 55.273 + break; 55.274 + 55.275 + case AL_METERS_PER_UNIT: 55.276 + *pflValue = pContext->Listener.MetersPerUnit; 55.277 + break; 55.278 + 55.279 + default: 55.280 + alSetError(pContext, AL_INVALID_ENUM); 55.281 + break; 55.282 + } 55.283 + } 55.284 + else 55.285 + alSetError(pContext, AL_INVALID_VALUE); 55.286 + 55.287 + UnlockContext(pContext); 55.288 +} 55.289 + 55.290 + 55.291 +AL_API ALvoid AL_APIENTRY alGetListener3f(ALenum eParam, ALfloat *pflValue1, ALfloat *pflValue2, ALfloat *pflValue3) 55.292 +{ 55.293 + ALCcontext *pContext; 55.294 + 55.295 + pContext = GetLockedContext(); 55.296 + if(!pContext) return; 55.297 + 55.298 + if(pflValue1 && pflValue2 && pflValue3) 55.299 + { 55.300 + switch(eParam) 55.301 + { 55.302 + case AL_POSITION: 55.303 + *pflValue1 = pContext->Listener.Position[0]; 55.304 + *pflValue2 = pContext->Listener.Position[1]; 55.305 + *pflValue3 = pContext->Listener.Position[2]; 55.306 + break; 55.307 + 55.308 + case AL_VELOCITY: 55.309 + *pflValue1 = pContext->Listener.Velocity[0]; 55.310 + *pflValue2 = pContext->Listener.Velocity[1]; 55.311 + *pflValue3 = pContext->Listener.Velocity[2]; 55.312 + break; 55.313 + 55.314 + default: 55.315 + alSetError(pContext, AL_INVALID_ENUM); 55.316 + break; 55.317 + } 55.318 + } 55.319 + else 55.320 + alSetError(pContext, AL_INVALID_VALUE); 55.321 + 55.322 + UnlockContext(pContext); 55.323 +} 55.324 + 55.325 + 55.326 +AL_API ALvoid AL_APIENTRY alGetListenerfv(ALenum eParam, ALfloat *pflValues) 55.327 +{ 55.328 + ALCcontext *pContext; 55.329 + 55.330 + switch(eParam) 55.331 + { 55.332 + case AL_GAIN: 55.333 + case AL_METERS_PER_UNIT: 55.334 + alGetListenerf(eParam, pflValues); 55.335 + return; 55.336 + 55.337 + case AL_POSITION: 55.338 + case AL_VELOCITY: 55.339 + alGetListener3f(eParam, pflValues+0, pflValues+1, pflValues+2); 55.340 + return; 55.341 + } 55.342 + 55.343 + pContext = GetLockedContext(); 55.344 + if(!pContext) return; 55.345 + 55.346 + if(pflValues) 55.347 + { 55.348 + switch(eParam) 55.349 + { 55.350 + case AL_ORIENTATION: 55.351 + // AT then UP 55.352 + pflValues[0] = pContext->Listener.Forward[0]; 55.353 + pflValues[1] = pContext->Listener.Forward[1]; 55.354 + pflValues[2] = pContext->Listener.Forward[2]; 55.355 + pflValues[3] = pContext->Listener.Up[0]; 55.356 + pflValues[4] = pContext->Listener.Up[1]; 55.357 + pflValues[5] = pContext->Listener.Up[2]; 55.358 + break; 55.359 + 55.360 + default: 55.361 + alSetError(pContext, AL_INVALID_ENUM); 55.362 + break; 55.363 + } 55.364 + } 55.365 + else 55.366 + alSetError(pContext, AL_INVALID_VALUE); 55.367 + 55.368 + UnlockContext(pContext); 55.369 +} 55.370 + 55.371 + 55.372 +AL_API ALvoid AL_APIENTRY alGetListeneri(ALenum eParam, ALint *plValue) 55.373 +{ 55.374 + ALCcontext *pContext; 55.375 + 55.376 + pContext = GetLockedContext(); 55.377 + if(!pContext) return; 55.378 + 55.379 + if(plValue) 55.380 + { 55.381 + switch(eParam) 55.382 + { 55.383 + default: 55.384 + alSetError(pContext, AL_INVALID_ENUM); 55.385 + break; 55.386 + } 55.387 + } 55.388 + else 55.389 + alSetError(pContext, AL_INVALID_VALUE); 55.390 + 55.391 + UnlockContext(pContext); 55.392 +} 55.393 + 55.394 + 55.395 +AL_API void AL_APIENTRY alGetListener3i(ALenum eParam, ALint *plValue1, ALint *plValue2, ALint *plValue3) 55.396 +{ 55.397 + ALCcontext *pContext; 55.398 + 55.399 + pContext = GetLockedContext(); 55.400 + if(!pContext) return; 55.401 + 55.402 + if(plValue1 && plValue2 && plValue3) 55.403 + { 55.404 + switch (eParam) 55.405 + { 55.406 + case AL_POSITION: 55.407 + *plValue1 = (ALint)pContext->Listener.Position[0]; 55.408 + *plValue2 = (ALint)pContext->Listener.Position[1]; 55.409 + *plValue3 = (ALint)pContext->Listener.Position[2]; 55.410 + break; 55.411 + 55.412 + case AL_VELOCITY: 55.413 + *plValue1 = (ALint)pContext->Listener.Velocity[0]; 55.414 + *plValue2 = (ALint)pContext->Listener.Velocity[1]; 55.415 + *plValue3 = (ALint)pContext->Listener.Velocity[2]; 55.416 + break; 55.417 + 55.418 + default: 55.419 + alSetError(pContext, AL_INVALID_ENUM); 55.420 + break; 55.421 + } 55.422 + } 55.423 + else 55.424 + alSetError(pContext, AL_INVALID_VALUE); 55.425 + 55.426 + UnlockContext(pContext); 55.427 +} 55.428 + 55.429 + 55.430 +AL_API void AL_APIENTRY alGetListeneriv(ALenum eParam, ALint* plValues) 55.431 +{ 55.432 + ALCcontext *pContext; 55.433 + 55.434 + switch(eParam) 55.435 + { 55.436 + case AL_POSITION: 55.437 + case AL_VELOCITY: 55.438 + alGetListener3i(eParam, plValues+0, plValues+1, plValues+2); 55.439 + return; 55.440 + } 55.441 + 55.442 + pContext = GetLockedContext(); 55.443 + if(!pContext) return; 55.444 + 55.445 + if(plValues) 55.446 + { 55.447 + switch(eParam) 55.448 + { 55.449 + case AL_ORIENTATION: 55.450 + // AT then UP 55.451 + plValues[0] = (ALint)pContext->Listener.Forward[0]; 55.452 + plValues[1] = (ALint)pContext->Listener.Forward[1]; 55.453 + plValues[2] = (ALint)pContext->Listener.Forward[2]; 55.454 + plValues[3] = (ALint)pContext->Listener.Up[0]; 55.455 + plValues[4] = (ALint)pContext->Listener.Up[1]; 55.456 + plValues[5] = (ALint)pContext->Listener.Up[2]; 55.457 + break; 55.458 + 55.459 + default: 55.460 + alSetError(pContext, AL_INVALID_ENUM); 55.461 + break; 55.462 + } 55.463 + } 55.464 + else 55.465 + alSetError(pContext, AL_INVALID_VALUE); 55.466 + 55.467 + UnlockContext(pContext); 55.468 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 56.2 +++ b/OpenAL32/alSource.c Tue Oct 25 13:02:31 2011 -0700 56.3 @@ -0,0 +1,2172 @@ 56.4 +/** 56.5 + * OpenAL cross platform audio library 56.6 + * Copyright (C) 1999-2007 by authors. 56.7 + * This library is free software; you can redistribute it and/or 56.8 + * modify it under the terms of the GNU Library General Public 56.9 + * License as published by the Free Software Foundation; either 56.10 + * version 2 of the License, or (at your option) any later version. 56.11 + * 56.12 + * This library is distributed in the hope that it will be useful, 56.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 56.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 56.15 + * Library General Public License for more details. 56.16 + * 56.17 + * You should have received a copy of the GNU Library General Public 56.18 + * License along with this library; if not, write to the 56.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 56.20 + * Boston, MA 02111-1307, USA. 56.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 56.22 + */ 56.23 + 56.24 +#include "config.h" 56.25 + 56.26 +#include <stdlib.h> 56.27 +#include <math.h> 56.28 +#include <float.h> 56.29 +#include "alMain.h" 56.30 +#include "AL/al.h" 56.31 +#include "AL/alc.h" 56.32 +#include "alError.h" 56.33 +#include "alSource.h" 56.34 +#include "alBuffer.h" 56.35 +#include "alThunk.h" 56.36 +#include "alAuxEffectSlot.h" 56.37 + 56.38 + 56.39 +enum Resampler DefaultResampler; 56.40 +const ALsizei ResamplerPadding[RESAMPLER_MAX] = { 56.41 + 0, /* Point */ 56.42 + 1, /* Linear */ 56.43 + 2, /* Cubic */ 56.44 +}; 56.45 +const ALsizei ResamplerPrePadding[RESAMPLER_MAX] = { 56.46 + 0, /* Point */ 56.47 + 0, /* Linear */ 56.48 + 1, /* Cubic */ 56.49 +}; 56.50 + 56.51 + 56.52 +static ALvoid InitSourceParams(ALsource *Source); 56.53 +static ALvoid GetSourceOffset(ALsource *Source, ALenum eName, ALdouble *Offsets, ALdouble updateLen); 56.54 +static ALint GetByteOffset(ALsource *Source); 56.55 + 56.56 +#define LookupSource(m, k) ((ALsource*)LookupUIntMapKey(&(m), (k))) 56.57 +#define LookupBuffer(m, k) ((ALbuffer*)LookupUIntMapKey(&(m), (k))) 56.58 +#define LookupFilter(m, k) ((ALfilter*)LookupUIntMapKey(&(m), (k))) 56.59 +#define LookupEffectSlot(m, k) ((ALeffectslot*)LookupUIntMapKey(&(m), (k))) 56.60 + 56.61 +AL_API ALvoid AL_APIENTRY alGenSources(ALsizei n,ALuint *sources) 56.62 +{ 56.63 + ALCcontext *Context; 56.64 + ALCdevice *Device; 56.65 + 56.66 + Context = GetLockedContext(); 56.67 + if(!Context) return; 56.68 + 56.69 + Device = Context->Device; 56.70 + if(n < 0 || IsBadWritePtr((void*)sources, n * sizeof(ALuint))) 56.71 + alSetError(Context, AL_INVALID_VALUE); 56.72 + else if((ALuint)n > Device->MaxNoOfSources - Context->SourceMap.size) 56.73 + alSetError(Context, AL_INVALID_VALUE); 56.74 + else 56.75 + { 56.76 + ALenum err; 56.77 + ALsizei i; 56.78 + 56.79 + // Add additional sources to the list 56.80 + i = 0; 56.81 + while(i < n) 56.82 + { 56.83 + ALsource *source = calloc(1, sizeof(ALsource)); 56.84 + if(!source) 56.85 + { 56.86 + alSetError(Context, AL_OUT_OF_MEMORY); 56.87 + alDeleteSources(i, sources); 56.88 + break; 56.89 + } 56.90 + 56.91 + err = NewThunkEntry(&source->source); 56.92 + if(err == AL_NO_ERROR) 56.93 + err = InsertUIntMapEntry(&Context->SourceMap, source->source, source); 56.94 + if(err != AL_NO_ERROR) 56.95 + { 56.96 + FreeThunkEntry(source->source); 56.97 + memset(source, 0, sizeof(ALsource)); 56.98 + free(source); 56.99 + 56.100 + alSetError(Context, err); 56.101 + alDeleteSources(i, sources); 56.102 + break; 56.103 + } 56.104 + 56.105 + sources[i++] = source->source; 56.106 + InitSourceParams(source); 56.107 + } 56.108 + } 56.109 + 56.110 + UnlockContext(Context); 56.111 +} 56.112 + 56.113 + 56.114 +AL_API ALvoid AL_APIENTRY alDeleteSources(ALsizei n, const ALuint *sources) 56.115 +{ 56.116 + ALCcontext *Context; 56.117 + ALsource *Source; 56.118 + ALsizei i, j; 56.119 + ALbufferlistitem *BufferList; 56.120 + ALboolean SourcesValid = AL_FALSE; 56.121 + 56.122 + Context = GetLockedContext(); 56.123 + if(!Context) return; 56.124 + 56.125 + if(n < 0) 56.126 + alSetError(Context, AL_INVALID_VALUE); 56.127 + else 56.128 + { 56.129 + SourcesValid = AL_TRUE; 56.130 + // Check that all Sources are valid (and can therefore be deleted) 56.131 + for(i = 0;i < n;i++) 56.132 + { 56.133 + if(LookupSource(Context->SourceMap, sources[i]) == NULL) 56.134 + { 56.135 + alSetError(Context, AL_INVALID_NAME); 56.136 + SourcesValid = AL_FALSE; 56.137 + break; 56.138 + } 56.139 + } 56.140 + } 56.141 + 56.142 + if(SourcesValid) 56.143 + { 56.144 + // All Sources are valid, and can be deleted 56.145 + for(i = 0;i < n;i++) 56.146 + { 56.147 + // Recheck that the Source is valid, because there could be duplicated Source names 56.148 + if((Source=LookupSource(Context->SourceMap, sources[i])) == NULL) 56.149 + continue; 56.150 + 56.151 + for(j = 0;j < Context->ActiveSourceCount;j++) 56.152 + { 56.153 + if(Context->ActiveSources[j] == Source) 56.154 + { 56.155 + ALsizei end = --(Context->ActiveSourceCount); 56.156 + Context->ActiveSources[j] = Context->ActiveSources[end]; 56.157 + break; 56.158 + } 56.159 + } 56.160 + 56.161 + // For each buffer in the source's queue... 56.162 + while(Source->queue != NULL) 56.163 + { 56.164 + BufferList = Source->queue; 56.165 + Source->queue = BufferList->next; 56.166 + 56.167 + if(BufferList->buffer != NULL) 56.168 + BufferList->buffer->refcount--; 56.169 + free(BufferList); 56.170 + } 56.171 + 56.172 + for(j = 0;j < MAX_SENDS;++j) 56.173 + { 56.174 + if(Source->Send[j].Slot) 56.175 + Source->Send[j].Slot->refcount--; 56.176 + Source->Send[j].Slot = NULL; 56.177 + } 56.178 + 56.179 + // Remove Source from list of Sources 56.180 + RemoveUIntMapKey(&Context->SourceMap, Source->source); 56.181 + FreeThunkEntry(Source->source); 56.182 + 56.183 + memset(Source,0,sizeof(ALsource)); 56.184 + free(Source); 56.185 + } 56.186 + } 56.187 + 56.188 + UnlockContext(Context); 56.189 +} 56.190 + 56.191 + 56.192 +AL_API ALboolean AL_APIENTRY alIsSource(ALuint source) 56.193 +{ 56.194 + ALCcontext *Context; 56.195 + ALboolean result; 56.196 + 56.197 + Context = GetLockedContext(); 56.198 + if(!Context) return AL_FALSE; 56.199 + 56.200 + result = (LookupSource(Context->SourceMap, source) ? AL_TRUE : AL_FALSE); 56.201 + 56.202 + UnlockContext(Context); 56.203 + 56.204 + return result; 56.205 +} 56.206 + 56.207 + 56.208 +AL_API ALvoid AL_APIENTRY alSourcef(ALuint source, ALenum eParam, ALfloat flValue) 56.209 +{ 56.210 + ALCcontext *pContext; 56.211 + ALsource *Source; 56.212 + 56.213 + pContext = GetLockedContext(); 56.214 + if(!pContext) return; 56.215 + 56.216 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.217 + { 56.218 + switch(eParam) 56.219 + { 56.220 + case AL_PITCH: 56.221 + if(flValue >= 0.0f) 56.222 + { 56.223 + Source->flPitch = flValue; 56.224 + Source->NeedsUpdate = AL_TRUE; 56.225 + } 56.226 + else 56.227 + alSetError(pContext, AL_INVALID_VALUE); 56.228 + break; 56.229 + 56.230 + case AL_CONE_INNER_ANGLE: 56.231 + if(flValue >= 0.0f && flValue <= 360.0f) 56.232 + { 56.233 + Source->flInnerAngle = flValue; 56.234 + Source->NeedsUpdate = AL_TRUE; 56.235 + } 56.236 + else 56.237 + alSetError(pContext, AL_INVALID_VALUE); 56.238 + break; 56.239 + 56.240 + case AL_CONE_OUTER_ANGLE: 56.241 + if(flValue >= 0.0f && flValue <= 360.0f) 56.242 + { 56.243 + Source->flOuterAngle = flValue; 56.244 + Source->NeedsUpdate = AL_TRUE; 56.245 + } 56.246 + else 56.247 + alSetError(pContext, AL_INVALID_VALUE); 56.248 + break; 56.249 + 56.250 + case AL_GAIN: 56.251 + if(flValue >= 0.0f) 56.252 + { 56.253 + Source->flGain = flValue; 56.254 + Source->NeedsUpdate = AL_TRUE; 56.255 + } 56.256 + else 56.257 + alSetError(pContext, AL_INVALID_VALUE); 56.258 + break; 56.259 + 56.260 + case AL_MAX_DISTANCE: 56.261 + if(flValue >= 0.0f) 56.262 + { 56.263 + Source->flMaxDistance = flValue; 56.264 + Source->NeedsUpdate = AL_TRUE; 56.265 + } 56.266 + else 56.267 + alSetError(pContext, AL_INVALID_VALUE); 56.268 + break; 56.269 + 56.270 + case AL_ROLLOFF_FACTOR: 56.271 + if(flValue >= 0.0f) 56.272 + { 56.273 + Source->flRollOffFactor = flValue; 56.274 + Source->NeedsUpdate = AL_TRUE; 56.275 + } 56.276 + else 56.277 + alSetError(pContext, AL_INVALID_VALUE); 56.278 + break; 56.279 + 56.280 + case AL_REFERENCE_DISTANCE: 56.281 + if(flValue >= 0.0f) 56.282 + { 56.283 + Source->flRefDistance = flValue; 56.284 + Source->NeedsUpdate = AL_TRUE; 56.285 + } 56.286 + else 56.287 + alSetError(pContext, AL_INVALID_VALUE); 56.288 + break; 56.289 + 56.290 + case AL_MIN_GAIN: 56.291 + if(flValue >= 0.0f && flValue <= 1.0f) 56.292 + { 56.293 + Source->flMinGain = flValue; 56.294 + Source->NeedsUpdate = AL_TRUE; 56.295 + } 56.296 + else 56.297 + alSetError(pContext, AL_INVALID_VALUE); 56.298 + break; 56.299 + 56.300 + case AL_MAX_GAIN: 56.301 + if(flValue >= 0.0f && flValue <= 1.0f) 56.302 + { 56.303 + Source->flMaxGain = flValue; 56.304 + Source->NeedsUpdate = AL_TRUE; 56.305 + } 56.306 + else 56.307 + alSetError(pContext, AL_INVALID_VALUE); 56.308 + break; 56.309 + 56.310 + case AL_CONE_OUTER_GAIN: 56.311 + if(flValue >= 0.0f && flValue <= 1.0f) 56.312 + { 56.313 + Source->flOuterGain = flValue; 56.314 + Source->NeedsUpdate = AL_TRUE; 56.315 + } 56.316 + else 56.317 + alSetError(pContext, AL_INVALID_VALUE); 56.318 + break; 56.319 + 56.320 + case AL_CONE_OUTER_GAINHF: 56.321 + if(flValue >= 0.0f && flValue <= 1.0f) 56.322 + { 56.323 + Source->OuterGainHF = flValue; 56.324 + Source->NeedsUpdate = AL_TRUE; 56.325 + } 56.326 + else 56.327 + alSetError(pContext, AL_INVALID_VALUE); 56.328 + break; 56.329 + 56.330 + case AL_AIR_ABSORPTION_FACTOR: 56.331 + if(flValue >= 0.0f && flValue <= 10.0f) 56.332 + { 56.333 + Source->AirAbsorptionFactor = flValue; 56.334 + Source->NeedsUpdate = AL_TRUE; 56.335 + } 56.336 + else 56.337 + alSetError(pContext, AL_INVALID_VALUE); 56.338 + break; 56.339 + 56.340 + case AL_ROOM_ROLLOFF_FACTOR: 56.341 + if(flValue >= 0.0f && flValue <= 10.0f) 56.342 + { 56.343 + Source->RoomRolloffFactor = flValue; 56.344 + Source->NeedsUpdate = AL_TRUE; 56.345 + } 56.346 + else 56.347 + alSetError(pContext, AL_INVALID_VALUE); 56.348 + break; 56.349 + 56.350 + case AL_DOPPLER_FACTOR: 56.351 + if(flValue >= 0.0f && flValue <= 1.0f) 56.352 + { 56.353 + Source->DopplerFactor = flValue; 56.354 + Source->NeedsUpdate = AL_TRUE; 56.355 + } 56.356 + else 56.357 + alSetError(pContext, AL_INVALID_VALUE); 56.358 + break; 56.359 + 56.360 + case AL_SEC_OFFSET: 56.361 + case AL_SAMPLE_OFFSET: 56.362 + case AL_BYTE_OFFSET: 56.363 + if(flValue >= 0.0f) 56.364 + { 56.365 + Source->lOffsetType = eParam; 56.366 + 56.367 + // Store Offset (convert Seconds into Milliseconds) 56.368 + if(eParam == AL_SEC_OFFSET) 56.369 + Source->lOffset = (ALint)(flValue * 1000.0f); 56.370 + else 56.371 + Source->lOffset = (ALint)flValue; 56.372 + 56.373 + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && 56.374 + !pContext->DeferUpdates) 56.375 + { 56.376 + if(ApplyOffset(Source) == AL_FALSE) 56.377 + alSetError(pContext, AL_INVALID_VALUE); 56.378 + } 56.379 + } 56.380 + else 56.381 + alSetError(pContext, AL_INVALID_VALUE); 56.382 + break; 56.383 + 56.384 + default: 56.385 + alSetError(pContext, AL_INVALID_ENUM); 56.386 + break; 56.387 + } 56.388 + } 56.389 + else 56.390 + { 56.391 + // Invalid Source Name 56.392 + alSetError(pContext, AL_INVALID_NAME); 56.393 + } 56.394 + 56.395 + UnlockContext(pContext); 56.396 +} 56.397 + 56.398 + 56.399 +AL_API ALvoid AL_APIENTRY alSource3f(ALuint source, ALenum eParam, ALfloat flValue1,ALfloat flValue2,ALfloat flValue3) 56.400 +{ 56.401 + ALCcontext *pContext; 56.402 + ALsource *Source; 56.403 + 56.404 + pContext = GetLockedContext(); 56.405 + if(!pContext) return; 56.406 + 56.407 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.408 + { 56.409 + switch(eParam) 56.410 + { 56.411 + case AL_POSITION: 56.412 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 56.413 + { 56.414 + Source->vPosition[0] = flValue1; 56.415 + Source->vPosition[1] = flValue2; 56.416 + Source->vPosition[2] = flValue3; 56.417 + Source->NeedsUpdate = AL_TRUE; 56.418 + } 56.419 + else 56.420 + alSetError(pContext, AL_INVALID_VALUE); 56.421 + break; 56.422 + 56.423 + case AL_VELOCITY: 56.424 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 56.425 + { 56.426 + Source->vVelocity[0] = flValue1; 56.427 + Source->vVelocity[1] = flValue2; 56.428 + Source->vVelocity[2] = flValue3; 56.429 + Source->NeedsUpdate = AL_TRUE; 56.430 + } 56.431 + else 56.432 + alSetError(pContext, AL_INVALID_VALUE); 56.433 + break; 56.434 + 56.435 + case AL_DIRECTION: 56.436 + if(isfinite(flValue1) && isfinite(flValue2) && isfinite(flValue3)) 56.437 + { 56.438 + Source->vOrientation[0] = flValue1; 56.439 + Source->vOrientation[1] = flValue2; 56.440 + Source->vOrientation[2] = flValue3; 56.441 + Source->NeedsUpdate = AL_TRUE; 56.442 + } 56.443 + else 56.444 + alSetError(pContext, AL_INVALID_VALUE); 56.445 + break; 56.446 + 56.447 + default: 56.448 + alSetError(pContext, AL_INVALID_ENUM); 56.449 + break; 56.450 + } 56.451 + } 56.452 + else 56.453 + alSetError(pContext, AL_INVALID_NAME); 56.454 + 56.455 + UnlockContext(pContext); 56.456 +} 56.457 + 56.458 + 56.459 +AL_API ALvoid AL_APIENTRY alSourcefv(ALuint source, ALenum eParam, const ALfloat *pflValues) 56.460 +{ 56.461 + ALCcontext *pContext; 56.462 + 56.463 + if(pflValues) 56.464 + { 56.465 + switch(eParam) 56.466 + { 56.467 + case AL_PITCH: 56.468 + case AL_CONE_INNER_ANGLE: 56.469 + case AL_CONE_OUTER_ANGLE: 56.470 + case AL_GAIN: 56.471 + case AL_MAX_DISTANCE: 56.472 + case AL_ROLLOFF_FACTOR: 56.473 + case AL_REFERENCE_DISTANCE: 56.474 + case AL_MIN_GAIN: 56.475 + case AL_MAX_GAIN: 56.476 + case AL_CONE_OUTER_GAIN: 56.477 + case AL_CONE_OUTER_GAINHF: 56.478 + case AL_SEC_OFFSET: 56.479 + case AL_SAMPLE_OFFSET: 56.480 + case AL_BYTE_OFFSET: 56.481 + case AL_AIR_ABSORPTION_FACTOR: 56.482 + case AL_ROOM_ROLLOFF_FACTOR: 56.483 + alSourcef(source, eParam, pflValues[0]); 56.484 + return; 56.485 + 56.486 + case AL_POSITION: 56.487 + case AL_VELOCITY: 56.488 + case AL_DIRECTION: 56.489 + alSource3f(source, eParam, pflValues[0], pflValues[1], pflValues[2]); 56.490 + return; 56.491 + } 56.492 + } 56.493 + 56.494 + pContext = GetLockedContext(); 56.495 + if(!pContext) return; 56.496 + 56.497 + if(pflValues) 56.498 + { 56.499 + if(LookupSource(pContext->SourceMap, source) != NULL) 56.500 + { 56.501 + switch(eParam) 56.502 + { 56.503 + default: 56.504 + alSetError(pContext, AL_INVALID_ENUM); 56.505 + break; 56.506 + } 56.507 + } 56.508 + else 56.509 + alSetError(pContext, AL_INVALID_NAME); 56.510 + } 56.511 + else 56.512 + alSetError(pContext, AL_INVALID_VALUE); 56.513 + 56.514 + UnlockContext(pContext); 56.515 +} 56.516 + 56.517 + 56.518 +AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue) 56.519 +{ 56.520 + ALCcontext *pContext; 56.521 + ALsource *Source; 56.522 + ALbufferlistitem *BufferListItem; 56.523 + 56.524 + switch(eParam) 56.525 + { 56.526 + case AL_MAX_DISTANCE: 56.527 + case AL_ROLLOFF_FACTOR: 56.528 + case AL_CONE_INNER_ANGLE: 56.529 + case AL_CONE_OUTER_ANGLE: 56.530 + case AL_REFERENCE_DISTANCE: 56.531 + alSourcef(source, eParam, (ALfloat)lValue); 56.532 + return; 56.533 + } 56.534 + 56.535 + pContext = GetLockedContext(); 56.536 + if(!pContext) return; 56.537 + 56.538 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.539 + { 56.540 + ALCdevice *device = pContext->Device; 56.541 + 56.542 + switch(eParam) 56.543 + { 56.544 + case AL_SOURCE_RELATIVE: 56.545 + if(lValue == AL_FALSE || lValue == AL_TRUE) 56.546 + { 56.547 + Source->bHeadRelative = (ALboolean)lValue; 56.548 + Source->NeedsUpdate = AL_TRUE; 56.549 + } 56.550 + else 56.551 + alSetError(pContext, AL_INVALID_VALUE); 56.552 + break; 56.553 + 56.554 + case AL_LOOPING: 56.555 + if(lValue == AL_FALSE || lValue == AL_TRUE) 56.556 + Source->bLooping = (ALboolean)lValue; 56.557 + else 56.558 + alSetError(pContext, AL_INVALID_VALUE); 56.559 + break; 56.560 + 56.561 + case AL_BUFFER: 56.562 + if(Source->state == AL_STOPPED || Source->state == AL_INITIAL) 56.563 + { 56.564 + ALbuffer *buffer = NULL; 56.565 + 56.566 + if(lValue == 0 || 56.567 + (buffer=LookupBuffer(device->BufferMap, lValue)) != NULL) 56.568 + { 56.569 + // Remove all elements in the queue 56.570 + while(Source->queue != NULL) 56.571 + { 56.572 + BufferListItem = Source->queue; 56.573 + Source->queue = BufferListItem->next; 56.574 + 56.575 + if(BufferListItem->buffer) 56.576 + BufferListItem->buffer->refcount--; 56.577 + free(BufferListItem); 56.578 + } 56.579 + Source->BuffersInQueue = 0; 56.580 + 56.581 + // Add the buffer to the queue (as long as it is NOT the NULL buffer) 56.582 + if(buffer != NULL) 56.583 + { 56.584 + // Source is now in STATIC mode 56.585 + Source->lSourceType = AL_STATIC; 56.586 + 56.587 + // Add the selected buffer to the queue 56.588 + BufferListItem = malloc(sizeof(ALbufferlistitem)); 56.589 + BufferListItem->buffer = buffer; 56.590 + BufferListItem->next = NULL; 56.591 + BufferListItem->prev = NULL; 56.592 + 56.593 + Source->queue = BufferListItem; 56.594 + Source->BuffersInQueue = 1; 56.595 + 56.596 + Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); 56.597 + Source->SampleSize = BytesFromFmt(buffer->FmtType); 56.598 + if(buffer->FmtChannels == FmtMono) 56.599 + Source->Update = CalcSourceParams; 56.600 + else 56.601 + Source->Update = CalcNonAttnSourceParams; 56.602 + 56.603 + // Increment reference counter for buffer 56.604 + buffer->refcount++; 56.605 + } 56.606 + else 56.607 + { 56.608 + // Source is now in UNDETERMINED mode 56.609 + Source->lSourceType = AL_UNDETERMINED; 56.610 + } 56.611 + Source->BuffersPlayed = 0; 56.612 + 56.613 + // Update AL_BUFFER parameter 56.614 + Source->Buffer = buffer; 56.615 + Source->NeedsUpdate = AL_TRUE; 56.616 + } 56.617 + else 56.618 + alSetError(pContext, AL_INVALID_VALUE); 56.619 + } 56.620 + else 56.621 + alSetError(pContext, AL_INVALID_OPERATION); 56.622 + break; 56.623 + 56.624 + case AL_SOURCE_STATE: 56.625 + // Query only 56.626 + alSetError(pContext, AL_INVALID_OPERATION); 56.627 + break; 56.628 + 56.629 + case AL_SEC_OFFSET: 56.630 + case AL_SAMPLE_OFFSET: 56.631 + case AL_BYTE_OFFSET: 56.632 + if(lValue >= 0) 56.633 + { 56.634 + Source->lOffsetType = eParam; 56.635 + 56.636 + // Store Offset (convert Seconds into Milliseconds) 56.637 + if(eParam == AL_SEC_OFFSET) 56.638 + Source->lOffset = lValue * 1000; 56.639 + else 56.640 + Source->lOffset = lValue; 56.641 + 56.642 + if((Source->state == AL_PLAYING || Source->state == AL_PAUSED) && 56.643 + !pContext->DeferUpdates) 56.644 + { 56.645 + if(ApplyOffset(Source) == AL_FALSE) 56.646 + alSetError(pContext, AL_INVALID_VALUE); 56.647 + } 56.648 + } 56.649 + else 56.650 + alSetError(pContext, AL_INVALID_VALUE); 56.651 + break; 56.652 + 56.653 + case AL_DIRECT_FILTER: { 56.654 + ALfilter *filter = NULL; 56.655 + 56.656 + if(lValue == 0 || 56.657 + (filter=LookupFilter(pContext->Device->FilterMap, lValue)) != NULL) 56.658 + { 56.659 + if(!filter) 56.660 + { 56.661 + Source->DirectFilter.type = AL_FILTER_NULL; 56.662 + Source->DirectFilter.filter = 0; 56.663 + } 56.664 + else 56.665 + memcpy(&Source->DirectFilter, filter, sizeof(*filter)); 56.666 + Source->NeedsUpdate = AL_TRUE; 56.667 + } 56.668 + else 56.669 + alSetError(pContext, AL_INVALID_VALUE); 56.670 + } break; 56.671 + 56.672 + case AL_DIRECT_FILTER_GAINHF_AUTO: 56.673 + if(lValue == AL_TRUE || lValue == AL_FALSE) 56.674 + { 56.675 + Source->DryGainHFAuto = lValue; 56.676 + Source->NeedsUpdate = AL_TRUE; 56.677 + } 56.678 + else 56.679 + alSetError(pContext, AL_INVALID_VALUE); 56.680 + break; 56.681 + 56.682 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 56.683 + if(lValue == AL_TRUE || lValue == AL_FALSE) 56.684 + { 56.685 + Source->WetGainAuto = lValue; 56.686 + Source->NeedsUpdate = AL_TRUE; 56.687 + } 56.688 + else 56.689 + alSetError(pContext, AL_INVALID_VALUE); 56.690 + break; 56.691 + 56.692 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 56.693 + if(lValue == AL_TRUE || lValue == AL_FALSE) 56.694 + { 56.695 + Source->WetGainHFAuto = lValue; 56.696 + Source->NeedsUpdate = AL_TRUE; 56.697 + } 56.698 + else 56.699 + alSetError(pContext, AL_INVALID_VALUE); 56.700 + break; 56.701 + 56.702 + case AL_VIRTUAL_CHANNELS_SOFT: 56.703 + if(lValue == AL_TRUE || lValue == AL_FALSE) 56.704 + { 56.705 + Source->VirtualChannels = lValue; 56.706 + Source->NeedsUpdate = AL_TRUE; 56.707 + } 56.708 + else 56.709 + alSetError(pContext, AL_INVALID_VALUE); 56.710 + break; 56.711 + 56.712 + case AL_DISTANCE_MODEL: 56.713 + if(lValue == AL_NONE || 56.714 + lValue == AL_INVERSE_DISTANCE || 56.715 + lValue == AL_INVERSE_DISTANCE_CLAMPED || 56.716 + lValue == AL_LINEAR_DISTANCE || 56.717 + lValue == AL_LINEAR_DISTANCE_CLAMPED || 56.718 + lValue == AL_EXPONENT_DISTANCE || 56.719 + lValue == AL_EXPONENT_DISTANCE_CLAMPED) 56.720 + { 56.721 + Source->DistanceModel = lValue; 56.722 + if(pContext->SourceDistanceModel) 56.723 + Source->NeedsUpdate = AL_TRUE; 56.724 + } 56.725 + else 56.726 + alSetError(pContext, AL_INVALID_VALUE); 56.727 + break; 56.728 + 56.729 + default: 56.730 + alSetError(pContext, AL_INVALID_ENUM); 56.731 + break; 56.732 + } 56.733 + } 56.734 + else 56.735 + alSetError(pContext, AL_INVALID_NAME); 56.736 + 56.737 + UnlockContext(pContext); 56.738 +} 56.739 + 56.740 + 56.741 +AL_API void AL_APIENTRY alSource3i(ALuint source, ALenum eParam, ALint lValue1, ALint lValue2, ALint lValue3) 56.742 +{ 56.743 + ALCcontext *pContext; 56.744 + ALsource *Source; 56.745 + 56.746 + switch(eParam) 56.747 + { 56.748 + case AL_POSITION: 56.749 + case AL_VELOCITY: 56.750 + case AL_DIRECTION: 56.751 + alSource3f(source, eParam, (ALfloat)lValue1, (ALfloat)lValue2, (ALfloat)lValue3); 56.752 + return; 56.753 + } 56.754 + 56.755 + pContext = GetLockedContext(); 56.756 + if(!pContext) return; 56.757 + 56.758 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.759 + { 56.760 + ALCdevice *device = pContext->Device; 56.761 + 56.762 + switch(eParam) 56.763 + { 56.764 + case AL_AUXILIARY_SEND_FILTER: { 56.765 + ALeffectslot *ALEffectSlot = NULL; 56.766 + ALfilter *ALFilter = NULL; 56.767 + 56.768 + if((ALuint)lValue2 < device->NumAuxSends && 56.769 + (lValue1 == 0 || 56.770 + (ALEffectSlot=LookupEffectSlot(pContext->EffectSlotMap, lValue1)) != NULL) && 56.771 + (lValue3 == 0 || 56.772 + (ALFilter=LookupFilter(device->FilterMap, lValue3)) != NULL)) 56.773 + { 56.774 + /* Release refcount on the previous slot, and add one for 56.775 + * the new slot */ 56.776 + if(Source->Send[lValue2].Slot) 56.777 + Source->Send[lValue2].Slot->refcount--; 56.778 + Source->Send[lValue2].Slot = ALEffectSlot; 56.779 + if(Source->Send[lValue2].Slot) 56.780 + Source->Send[lValue2].Slot->refcount++; 56.781 + 56.782 + if(!ALFilter) 56.783 + { 56.784 + /* Disable filter */ 56.785 + Source->Send[lValue2].WetFilter.type = 0; 56.786 + Source->Send[lValue2].WetFilter.filter = 0; 56.787 + } 56.788 + else 56.789 + memcpy(&Source->Send[lValue2].WetFilter, ALFilter, sizeof(*ALFilter)); 56.790 + Source->NeedsUpdate = AL_TRUE; 56.791 + } 56.792 + else 56.793 + alSetError(pContext, AL_INVALID_VALUE); 56.794 + } break; 56.795 + 56.796 + default: 56.797 + alSetError(pContext, AL_INVALID_ENUM); 56.798 + break; 56.799 + } 56.800 + } 56.801 + else 56.802 + alSetError(pContext, AL_INVALID_NAME); 56.803 + 56.804 + UnlockContext(pContext); 56.805 +} 56.806 + 56.807 + 56.808 +AL_API void AL_APIENTRY alSourceiv(ALuint source, ALenum eParam, const ALint* plValues) 56.809 +{ 56.810 + ALCcontext *pContext; 56.811 + 56.812 + if(plValues) 56.813 + { 56.814 + switch(eParam) 56.815 + { 56.816 + case AL_SOURCE_RELATIVE: 56.817 + case AL_CONE_INNER_ANGLE: 56.818 + case AL_CONE_OUTER_ANGLE: 56.819 + case AL_LOOPING: 56.820 + case AL_BUFFER: 56.821 + case AL_SOURCE_STATE: 56.822 + case AL_SEC_OFFSET: 56.823 + case AL_SAMPLE_OFFSET: 56.824 + case AL_BYTE_OFFSET: 56.825 + case AL_MAX_DISTANCE: 56.826 + case AL_ROLLOFF_FACTOR: 56.827 + case AL_REFERENCE_DISTANCE: 56.828 + case AL_DIRECT_FILTER: 56.829 + case AL_DIRECT_FILTER_GAINHF_AUTO: 56.830 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 56.831 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 56.832 + case AL_DISTANCE_MODEL: 56.833 + case AL_VIRTUAL_CHANNELS_SOFT: 56.834 + alSourcei(source, eParam, plValues[0]); 56.835 + return; 56.836 + 56.837 + case AL_POSITION: 56.838 + case AL_VELOCITY: 56.839 + case AL_DIRECTION: 56.840 + case AL_AUXILIARY_SEND_FILTER: 56.841 + alSource3i(source, eParam, plValues[0], plValues[1], plValues[2]); 56.842 + return; 56.843 + } 56.844 + } 56.845 + 56.846 + pContext = GetLockedContext(); 56.847 + if(!pContext) return; 56.848 + 56.849 + if(plValues) 56.850 + { 56.851 + if(LookupSource(pContext->SourceMap, source) != NULL) 56.852 + { 56.853 + switch(eParam) 56.854 + { 56.855 + default: 56.856 + alSetError(pContext, AL_INVALID_ENUM); 56.857 + break; 56.858 + } 56.859 + } 56.860 + else 56.861 + alSetError(pContext, AL_INVALID_NAME); 56.862 + } 56.863 + else 56.864 + alSetError(pContext, AL_INVALID_VALUE); 56.865 + 56.866 + UnlockContext(pContext); 56.867 +} 56.868 + 56.869 + 56.870 +AL_API ALvoid AL_APIENTRY alGetSourcef(ALuint source, ALenum eParam, ALfloat *pflValue) 56.871 +{ 56.872 + ALCcontext *pContext; 56.873 + ALsource *Source; 56.874 + ALdouble Offsets[2]; 56.875 + ALdouble updateLen; 56.876 + 56.877 + pContext = GetLockedContext(); 56.878 + if(!pContext) return; 56.879 + 56.880 + if(pflValue) 56.881 + { 56.882 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.883 + { 56.884 + switch(eParam) 56.885 + { 56.886 + case AL_PITCH: 56.887 + *pflValue = Source->flPitch; 56.888 + break; 56.889 + 56.890 + case AL_GAIN: 56.891 + *pflValue = Source->flGain; 56.892 + break; 56.893 + 56.894 + case AL_MIN_GAIN: 56.895 + *pflValue = Source->flMinGain; 56.896 + break; 56.897 + 56.898 + case AL_MAX_GAIN: 56.899 + *pflValue = Source->flMaxGain; 56.900 + break; 56.901 + 56.902 + case AL_MAX_DISTANCE: 56.903 + *pflValue = Source->flMaxDistance; 56.904 + break; 56.905 + 56.906 + case AL_ROLLOFF_FACTOR: 56.907 + *pflValue = Source->flRollOffFactor; 56.908 + break; 56.909 + 56.910 + case AL_CONE_OUTER_GAIN: 56.911 + *pflValue = Source->flOuterGain; 56.912 + break; 56.913 + 56.914 + case AL_CONE_OUTER_GAINHF: 56.915 + *pflValue = Source->OuterGainHF; 56.916 + break; 56.917 + 56.918 + case AL_SEC_OFFSET: 56.919 + case AL_SAMPLE_OFFSET: 56.920 + case AL_BYTE_OFFSET: 56.921 + updateLen = (ALdouble)pContext->Device->UpdateSize / 56.922 + pContext->Device->Frequency; 56.923 + GetSourceOffset(Source, eParam, Offsets, updateLen); 56.924 + *pflValue = Offsets[0]; 56.925 + break; 56.926 + 56.927 + case AL_CONE_INNER_ANGLE: 56.928 + *pflValue = Source->flInnerAngle; 56.929 + break; 56.930 + 56.931 + case AL_CONE_OUTER_ANGLE: 56.932 + *pflValue = Source->flOuterAngle; 56.933 + break; 56.934 + 56.935 + case AL_REFERENCE_DISTANCE: 56.936 + *pflValue = Source->flRefDistance; 56.937 + break; 56.938 + 56.939 + case AL_AIR_ABSORPTION_FACTOR: 56.940 + *pflValue = Source->AirAbsorptionFactor; 56.941 + break; 56.942 + 56.943 + case AL_ROOM_ROLLOFF_FACTOR: 56.944 + *pflValue = Source->RoomRolloffFactor; 56.945 + break; 56.946 + 56.947 + case AL_DOPPLER_FACTOR: 56.948 + *pflValue = Source->DopplerFactor; 56.949 + break; 56.950 + 56.951 + default: 56.952 + alSetError(pContext, AL_INVALID_ENUM); 56.953 + break; 56.954 + } 56.955 + } 56.956 + else 56.957 + alSetError(pContext, AL_INVALID_NAME); 56.958 + } 56.959 + else 56.960 + alSetError(pContext, AL_INVALID_VALUE); 56.961 + 56.962 + UnlockContext(pContext); 56.963 +} 56.964 + 56.965 + 56.966 +AL_API ALvoid AL_APIENTRY alGetSource3f(ALuint source, ALenum eParam, ALfloat* pflValue1, ALfloat* pflValue2, ALfloat* pflValue3) 56.967 +{ 56.968 + ALCcontext *pContext; 56.969 + ALsource *Source; 56.970 + 56.971 + pContext = GetLockedContext(); 56.972 + if(!pContext) return; 56.973 + 56.974 + if(pflValue1 && pflValue2 && pflValue3) 56.975 + { 56.976 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.977 + { 56.978 + switch(eParam) 56.979 + { 56.980 + case AL_POSITION: 56.981 + *pflValue1 = Source->vPosition[0]; 56.982 + *pflValue2 = Source->vPosition[1]; 56.983 + *pflValue3 = Source->vPosition[2]; 56.984 + break; 56.985 + 56.986 + case AL_VELOCITY: 56.987 + *pflValue1 = Source->vVelocity[0]; 56.988 + *pflValue2 = Source->vVelocity[1]; 56.989 + *pflValue3 = Source->vVelocity[2]; 56.990 + break; 56.991 + 56.992 + case AL_DIRECTION: 56.993 + *pflValue1 = Source->vOrientation[0]; 56.994 + *pflValue2 = Source->vOrientation[1]; 56.995 + *pflValue3 = Source->vOrientation[2]; 56.996 + break; 56.997 + 56.998 + default: 56.999 + alSetError(pContext, AL_INVALID_ENUM); 56.1000 + break; 56.1001 + } 56.1002 + } 56.1003 + else 56.1004 + alSetError(pContext, AL_INVALID_NAME); 56.1005 + } 56.1006 + else 56.1007 + alSetError(pContext, AL_INVALID_VALUE); 56.1008 + 56.1009 + UnlockContext(pContext); 56.1010 +} 56.1011 + 56.1012 + 56.1013 +AL_API ALvoid AL_APIENTRY alGetSourcefv(ALuint source, ALenum eParam, ALfloat *pflValues) 56.1014 +{ 56.1015 + ALCcontext *pContext; 56.1016 + ALsource *Source; 56.1017 + ALdouble Offsets[2]; 56.1018 + ALdouble updateLen; 56.1019 + 56.1020 + switch(eParam) 56.1021 + { 56.1022 + case AL_PITCH: 56.1023 + case AL_GAIN: 56.1024 + case AL_MIN_GAIN: 56.1025 + case AL_MAX_GAIN: 56.1026 + case AL_MAX_DISTANCE: 56.1027 + case AL_ROLLOFF_FACTOR: 56.1028 + case AL_DOPPLER_FACTOR: 56.1029 + case AL_CONE_OUTER_GAIN: 56.1030 + case AL_SEC_OFFSET: 56.1031 + case AL_SAMPLE_OFFSET: 56.1032 + case AL_BYTE_OFFSET: 56.1033 + case AL_CONE_INNER_ANGLE: 56.1034 + case AL_CONE_OUTER_ANGLE: 56.1035 + case AL_REFERENCE_DISTANCE: 56.1036 + case AL_CONE_OUTER_GAINHF: 56.1037 + case AL_AIR_ABSORPTION_FACTOR: 56.1038 + case AL_ROOM_ROLLOFF_FACTOR: 56.1039 + alGetSourcef(source, eParam, pflValues); 56.1040 + return; 56.1041 + 56.1042 + case AL_POSITION: 56.1043 + case AL_VELOCITY: 56.1044 + case AL_DIRECTION: 56.1045 + alGetSource3f(source, eParam, pflValues+0, pflValues+1, pflValues+2); 56.1046 + return; 56.1047 + } 56.1048 + 56.1049 + pContext = GetLockedContext(); 56.1050 + if(!pContext) return; 56.1051 + 56.1052 + if(pflValues) 56.1053 + { 56.1054 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.1055 + { 56.1056 + switch(eParam) 56.1057 + { 56.1058 + case AL_SAMPLE_RW_OFFSETS_SOFT: 56.1059 + case AL_BYTE_RW_OFFSETS_SOFT: 56.1060 + updateLen = (ALdouble)pContext->Device->UpdateSize / 56.1061 + pContext->Device->Frequency; 56.1062 + GetSourceOffset(Source, eParam, Offsets, updateLen); 56.1063 + pflValues[0] = Offsets[0]; 56.1064 + pflValues[1] = Offsets[1]; 56.1065 + break; 56.1066 + 56.1067 + default: 56.1068 + alSetError(pContext, AL_INVALID_ENUM); 56.1069 + break; 56.1070 + } 56.1071 + } 56.1072 + else 56.1073 + alSetError(pContext, AL_INVALID_NAME); 56.1074 + } 56.1075 + else 56.1076 + alSetError(pContext, AL_INVALID_VALUE); 56.1077 + 56.1078 + UnlockContext(pContext); 56.1079 +} 56.1080 + 56.1081 + 56.1082 +AL_API ALvoid AL_APIENTRY alGetSourcei(ALuint source, ALenum eParam, ALint *plValue) 56.1083 +{ 56.1084 + ALCcontext *pContext; 56.1085 + ALsource *Source; 56.1086 + ALdouble Offsets[2]; 56.1087 + ALdouble updateLen; 56.1088 + 56.1089 + pContext = GetLockedContext(); 56.1090 + if(!pContext) return; 56.1091 + 56.1092 + if(plValue) 56.1093 + { 56.1094 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.1095 + { 56.1096 + switch(eParam) 56.1097 + { 56.1098 + case AL_MAX_DISTANCE: 56.1099 + *plValue = (ALint)Source->flMaxDistance; 56.1100 + break; 56.1101 + 56.1102 + case AL_ROLLOFF_FACTOR: 56.1103 + *plValue = (ALint)Source->flRollOffFactor; 56.1104 + break; 56.1105 + 56.1106 + case AL_REFERENCE_DISTANCE: 56.1107 + *plValue = (ALint)Source->flRefDistance; 56.1108 + break; 56.1109 + 56.1110 + case AL_SOURCE_RELATIVE: 56.1111 + *plValue = Source->bHeadRelative; 56.1112 + break; 56.1113 + 56.1114 + case AL_CONE_INNER_ANGLE: 56.1115 + *plValue = (ALint)Source->flInnerAngle; 56.1116 + break; 56.1117 + 56.1118 + case AL_CONE_OUTER_ANGLE: 56.1119 + *plValue = (ALint)Source->flOuterAngle; 56.1120 + break; 56.1121 + 56.1122 + case AL_LOOPING: 56.1123 + *plValue = Source->bLooping; 56.1124 + break; 56.1125 + 56.1126 + case AL_BUFFER: 56.1127 + *plValue = (Source->Buffer ? Source->Buffer->buffer : 0); 56.1128 + break; 56.1129 + 56.1130 + case AL_SOURCE_STATE: 56.1131 + *plValue = Source->state; 56.1132 + break; 56.1133 + 56.1134 + case AL_BUFFERS_QUEUED: 56.1135 + *plValue = Source->BuffersInQueue; 56.1136 + break; 56.1137 + 56.1138 + case AL_BUFFERS_PROCESSED: 56.1139 + if(Source->bLooping || Source->lSourceType != AL_STREAMING) 56.1140 + { 56.1141 + /* Buffers on a looping source are in a perpetual state 56.1142 + * of PENDING, so don't report any as PROCESSED */ 56.1143 + *plValue = 0; 56.1144 + } 56.1145 + else 56.1146 + *plValue = Source->BuffersPlayed; 56.1147 + break; 56.1148 + 56.1149 + case AL_SOURCE_TYPE: 56.1150 + *plValue = Source->lSourceType; 56.1151 + break; 56.1152 + 56.1153 + case AL_SEC_OFFSET: 56.1154 + case AL_SAMPLE_OFFSET: 56.1155 + case AL_BYTE_OFFSET: 56.1156 + updateLen = (ALdouble)pContext->Device->UpdateSize / 56.1157 + pContext->Device->Frequency; 56.1158 + GetSourceOffset(Source, eParam, Offsets, updateLen); 56.1159 + *plValue = (ALint)Offsets[0]; 56.1160 + break; 56.1161 + 56.1162 + case AL_DIRECT_FILTER: 56.1163 + *plValue = Source->DirectFilter.filter; 56.1164 + break; 56.1165 + 56.1166 + case AL_DIRECT_FILTER_GAINHF_AUTO: 56.1167 + *plValue = Source->DryGainHFAuto; 56.1168 + break; 56.1169 + 56.1170 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 56.1171 + *plValue = Source->WetGainAuto; 56.1172 + break; 56.1173 + 56.1174 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 56.1175 + *plValue = Source->WetGainHFAuto; 56.1176 + break; 56.1177 + 56.1178 + case AL_DOPPLER_FACTOR: 56.1179 + *plValue = (ALint)Source->DopplerFactor; 56.1180 + break; 56.1181 + 56.1182 + case AL_VIRTUAL_CHANNELS_SOFT: 56.1183 + *plValue = Source->VirtualChannels; 56.1184 + break; 56.1185 + 56.1186 + case AL_DISTANCE_MODEL: 56.1187 + *plValue = Source->DistanceModel; 56.1188 + break; 56.1189 + 56.1190 + default: 56.1191 + alSetError(pContext, AL_INVALID_ENUM); 56.1192 + break; 56.1193 + } 56.1194 + } 56.1195 + else 56.1196 + alSetError(pContext, AL_INVALID_NAME); 56.1197 + } 56.1198 + else 56.1199 + alSetError(pContext, AL_INVALID_VALUE); 56.1200 + 56.1201 + UnlockContext(pContext); 56.1202 +} 56.1203 + 56.1204 + 56.1205 +AL_API void AL_APIENTRY alGetSource3i(ALuint source, ALenum eParam, ALint* plValue1, ALint* plValue2, ALint* plValue3) 56.1206 +{ 56.1207 + ALCcontext *pContext; 56.1208 + ALsource *Source; 56.1209 + 56.1210 + pContext = GetLockedContext(); 56.1211 + if(!pContext) return; 56.1212 + 56.1213 + if(plValue1 && plValue2 && plValue3) 56.1214 + { 56.1215 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.1216 + { 56.1217 + switch(eParam) 56.1218 + { 56.1219 + case AL_POSITION: 56.1220 + *plValue1 = (ALint)Source->vPosition[0]; 56.1221 + *plValue2 = (ALint)Source->vPosition[1]; 56.1222 + *plValue3 = (ALint)Source->vPosition[2]; 56.1223 + break; 56.1224 + 56.1225 + case AL_VELOCITY: 56.1226 + *plValue1 = (ALint)Source->vVelocity[0]; 56.1227 + *plValue2 = (ALint)Source->vVelocity[1]; 56.1228 + *plValue3 = (ALint)Source->vVelocity[2]; 56.1229 + break; 56.1230 + 56.1231 + case AL_DIRECTION: 56.1232 + *plValue1 = (ALint)Source->vOrientation[0]; 56.1233 + *plValue2 = (ALint)Source->vOrientation[1]; 56.1234 + *plValue3 = (ALint)Source->vOrientation[2]; 56.1235 + break; 56.1236 + 56.1237 + default: 56.1238 + alSetError(pContext, AL_INVALID_ENUM); 56.1239 + break; 56.1240 + } 56.1241 + } 56.1242 + else 56.1243 + alSetError(pContext, AL_INVALID_NAME); 56.1244 + } 56.1245 + else 56.1246 + alSetError(pContext, AL_INVALID_VALUE); 56.1247 + 56.1248 + UnlockContext(pContext); 56.1249 +} 56.1250 + 56.1251 + 56.1252 +AL_API void AL_APIENTRY alGetSourceiv(ALuint source, ALenum eParam, ALint* plValues) 56.1253 +{ 56.1254 + ALCcontext *pContext; 56.1255 + ALsource *Source; 56.1256 + ALdouble Offsets[2]; 56.1257 + ALdouble updateLen; 56.1258 + 56.1259 + switch(eParam) 56.1260 + { 56.1261 + case AL_SOURCE_RELATIVE: 56.1262 + case AL_CONE_INNER_ANGLE: 56.1263 + case AL_CONE_OUTER_ANGLE: 56.1264 + case AL_LOOPING: 56.1265 + case AL_BUFFER: 56.1266 + case AL_SOURCE_STATE: 56.1267 + case AL_BUFFERS_QUEUED: 56.1268 + case AL_BUFFERS_PROCESSED: 56.1269 + case AL_SEC_OFFSET: 56.1270 + case AL_SAMPLE_OFFSET: 56.1271 + case AL_BYTE_OFFSET: 56.1272 + case AL_MAX_DISTANCE: 56.1273 + case AL_ROLLOFF_FACTOR: 56.1274 + case AL_DOPPLER_FACTOR: 56.1275 + case AL_REFERENCE_DISTANCE: 56.1276 + case AL_SOURCE_TYPE: 56.1277 + case AL_DIRECT_FILTER: 56.1278 + case AL_DIRECT_FILTER_GAINHF_AUTO: 56.1279 + case AL_AUXILIARY_SEND_FILTER_GAIN_AUTO: 56.1280 + case AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO: 56.1281 + case AL_DISTANCE_MODEL: 56.1282 + case AL_VIRTUAL_CHANNELS_SOFT: 56.1283 + alGetSourcei(source, eParam, plValues); 56.1284 + return; 56.1285 + 56.1286 + case AL_POSITION: 56.1287 + case AL_VELOCITY: 56.1288 + case AL_DIRECTION: 56.1289 + alGetSource3i(source, eParam, plValues+0, plValues+1, plValues+2); 56.1290 + return; 56.1291 + } 56.1292 + 56.1293 + pContext = GetLockedContext(); 56.1294 + if(!pContext) return; 56.1295 + 56.1296 + if(plValues) 56.1297 + { 56.1298 + if((Source=LookupSource(pContext->SourceMap, source)) != NULL) 56.1299 + { 56.1300 + switch(eParam) 56.1301 + { 56.1302 + case AL_SAMPLE_RW_OFFSETS_SOFT: 56.1303 + case AL_BYTE_RW_OFFSETS_SOFT: 56.1304 + updateLen = (ALdouble)pContext->Device->UpdateSize / 56.1305 + pContext->Device->Frequency; 56.1306 + GetSourceOffset(Source, eParam, Offsets, updateLen); 56.1307 + plValues[0] = (ALint)Offsets[0]; 56.1308 + plValues[1] = (ALint)Offsets[1]; 56.1309 + break; 56.1310 + 56.1311 + default: 56.1312 + alSetError(pContext, AL_INVALID_ENUM); 56.1313 + break; 56.1314 + } 56.1315 + } 56.1316 + else 56.1317 + alSetError(pContext, AL_INVALID_NAME); 56.1318 + } 56.1319 + else 56.1320 + alSetError(pContext, AL_INVALID_VALUE); 56.1321 + 56.1322 + UnlockContext(pContext); 56.1323 +} 56.1324 + 56.1325 + 56.1326 +AL_API ALvoid AL_APIENTRY alSourcePlay(ALuint source) 56.1327 +{ 56.1328 + alSourcePlayv(1, &source); 56.1329 +} 56.1330 + 56.1331 +AL_API ALvoid AL_APIENTRY alSourcePlayv(ALsizei n, const ALuint *sources) 56.1332 +{ 56.1333 + ALCcontext *Context; 56.1334 + ALsource *Source; 56.1335 + ALsizei i; 56.1336 + 56.1337 + Context = GetLockedContext(); 56.1338 + if(!Context) return; 56.1339 + 56.1340 + if(n < 0) 56.1341 + { 56.1342 + alSetError(Context, AL_INVALID_VALUE); 56.1343 + goto done; 56.1344 + } 56.1345 + if(n > 0 && !sources) 56.1346 + { 56.1347 + alSetError(Context, AL_INVALID_VALUE); 56.1348 + goto done; 56.1349 + } 56.1350 + 56.1351 + // Check that all the Sources are valid 56.1352 + for(i = 0;i < n;i++) 56.1353 + { 56.1354 + if(!LookupSource(Context->SourceMap, sources[i])) 56.1355 + { 56.1356 + alSetError(Context, AL_INVALID_NAME); 56.1357 + goto done; 56.1358 + } 56.1359 + } 56.1360 + 56.1361 + while(Context->MaxActiveSources-Context->ActiveSourceCount < n) 56.1362 + { 56.1363 + void *temp = NULL; 56.1364 + ALsizei newcount; 56.1365 + 56.1366 + newcount = Context->MaxActiveSources << 1; 56.1367 + if(newcount > 0) 56.1368 + temp = realloc(Context->ActiveSources, 56.1369 + sizeof(*Context->ActiveSources) * newcount); 56.1370 + if(!temp) 56.1371 + { 56.1372 + alSetError(Context, AL_OUT_OF_MEMORY); 56.1373 + goto done; 56.1374 + } 56.1375 + 56.1376 + Context->ActiveSources = temp; 56.1377 + Context->MaxActiveSources = newcount; 56.1378 + } 56.1379 + 56.1380 + for(i = 0;i < n;i++) 56.1381 + { 56.1382 + Source = LookupSource(Context->SourceMap, sources[i]); 56.1383 + if(Context->DeferUpdates) Source->new_state = AL_PLAYING; 56.1384 + else SetSourceState(Source, Context, AL_PLAYING); 56.1385 + } 56.1386 + 56.1387 +done: 56.1388 + UnlockContext(Context); 56.1389 +} 56.1390 + 56.1391 +AL_API ALvoid AL_APIENTRY alSourcePause(ALuint source) 56.1392 +{ 56.1393 + alSourcePausev(1, &source); 56.1394 +} 56.1395 + 56.1396 +AL_API ALvoid AL_APIENTRY alSourcePausev(ALsizei n, const ALuint *sources) 56.1397 +{ 56.1398 + ALCcontext *Context; 56.1399 + ALsource *Source; 56.1400 + ALsizei i; 56.1401 + 56.1402 + Context = GetLockedContext(); 56.1403 + if(!Context) return; 56.1404 + 56.1405 + if(n < 0) 56.1406 + { 56.1407 + alSetError(Context, AL_INVALID_VALUE); 56.1408 + goto done; 56.1409 + } 56.1410 + if(n > 0 && !sources) 56.1411 + { 56.1412 + alSetError(Context, AL_INVALID_VALUE); 56.1413 + goto done; 56.1414 + } 56.1415 + 56.1416 + // Check all the Sources are valid 56.1417 + for(i = 0;i < n;i++) 56.1418 + { 56.1419 + if(!LookupSource(Context->SourceMap, sources[i])) 56.1420 + { 56.1421 + alSetError(Context, AL_INVALID_NAME); 56.1422 + goto done; 56.1423 + } 56.1424 + } 56.1425 + 56.1426 + for(i = 0;i < n;i++) 56.1427 + { 56.1428 + Source = LookupSource(Context->SourceMap, sources[i]); 56.1429 + if(Context->DeferUpdates) Source->new_state = AL_PAUSED; 56.1430 + else SetSourceState(Source, Context, AL_PAUSED); 56.1431 + } 56.1432 + 56.1433 +done: 56.1434 + UnlockContext(Context); 56.1435 +} 56.1436 + 56.1437 +AL_API ALvoid AL_APIENTRY alSourceStop(ALuint source) 56.1438 +{ 56.1439 + alSourceStopv(1, &source); 56.1440 +} 56.1441 + 56.1442 +AL_API ALvoid AL_APIENTRY alSourceStopv(ALsizei n, const ALuint *sources) 56.1443 +{ 56.1444 + ALCcontext *Context; 56.1445 + ALsource *Source; 56.1446 + ALsizei i; 56.1447 + 56.1448 + Context = GetLockedContext(); 56.1449 + if(!Context) return; 56.1450 + 56.1451 + if(n < 0) 56.1452 + { 56.1453 + alSetError(Context, AL_INVALID_VALUE); 56.1454 + goto done; 56.1455 + } 56.1456 + if(n > 0 && !sources) 56.1457 + { 56.1458 + alSetError(Context, AL_INVALID_VALUE); 56.1459 + goto done; 56.1460 + } 56.1461 + 56.1462 + // Check all the Sources are valid 56.1463 + for(i = 0;i < n;i++) 56.1464 + { 56.1465 + if(!LookupSource(Context->SourceMap, sources[i])) 56.1466 + { 56.1467 + alSetError(Context, AL_INVALID_NAME); 56.1468 + goto done; 56.1469 + } 56.1470 + } 56.1471 + 56.1472 + for(i = 0;i < n;i++) 56.1473 + { 56.1474 + Source = LookupSource(Context->SourceMap, sources[i]); 56.1475 + if(Context->DeferUpdates) Source->new_state = AL_STOPPED; 56.1476 + else SetSourceState(Source, Context, AL_STOPPED); 56.1477 + } 56.1478 + 56.1479 +done: 56.1480 + UnlockContext(Context); 56.1481 +} 56.1482 + 56.1483 +AL_API ALvoid AL_APIENTRY alSourceRewind(ALuint source) 56.1484 +{ 56.1485 + alSourceRewindv(1, &source); 56.1486 +} 56.1487 + 56.1488 +AL_API ALvoid AL_APIENTRY alSourceRewindv(ALsizei n, const ALuint *sources) 56.1489 +{ 56.1490 + ALCcontext *Context; 56.1491 + ALsource *Source; 56.1492 + ALsizei i; 56.1493 + 56.1494 + Context = GetLockedContext(); 56.1495 + if(!Context) return; 56.1496 + 56.1497 + if(n < 0) 56.1498 + { 56.1499 + alSetError(Context, AL_INVALID_VALUE); 56.1500 + goto done; 56.1501 + } 56.1502 + if(n > 0 && !sources) 56.1503 + { 56.1504 + alSetError(Context, AL_INVALID_VALUE); 56.1505 + goto done; 56.1506 + } 56.1507 + 56.1508 + // Check all the Sources are valid 56.1509 + for(i = 0;i < n;i++) 56.1510 + { 56.1511 + if(!LookupSource(Context->SourceMap, sources[i])) 56.1512 + { 56.1513 + alSetError(Context, AL_INVALID_NAME); 56.1514 + goto done; 56.1515 + } 56.1516 + } 56.1517 + 56.1518 + for(i = 0;i < n;i++) 56.1519 + { 56.1520 + Source = LookupSource(Context->SourceMap, sources[i]); 56.1521 + if(Context->DeferUpdates) Source->new_state = AL_INITIAL; 56.1522 + else SetSourceState(Source, Context, AL_INITIAL); 56.1523 + } 56.1524 + 56.1525 +done: 56.1526 + UnlockContext(Context); 56.1527 +} 56.1528 + 56.1529 + 56.1530 +AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const ALuint *buffers) 56.1531 +{ 56.1532 + ALCcontext *Context; 56.1533 + ALCdevice *device; 56.1534 + ALsource *Source; 56.1535 + ALbuffer *buffer; 56.1536 + ALsizei i; 56.1537 + ALbufferlistitem *BufferListStart; 56.1538 + ALbufferlistitem *BufferList; 56.1539 + ALbuffer *BufferFmt; 56.1540 + 56.1541 + if(n == 0) 56.1542 + return; 56.1543 + 56.1544 + Context = GetLockedContext(); 56.1545 + if(!Context) return; 56.1546 + 56.1547 + if(n < 0) 56.1548 + { 56.1549 + alSetError(Context, AL_INVALID_VALUE); 56.1550 + goto done; 56.1551 + } 56.1552 + 56.1553 + // Check that all buffers are valid or zero and that the source is valid 56.1554 + 56.1555 + // Check that this is a valid source 56.1556 + if((Source=LookupSource(Context->SourceMap, source)) == NULL) 56.1557 + { 56.1558 + alSetError(Context, AL_INVALID_NAME); 56.1559 + goto done; 56.1560 + } 56.1561 + 56.1562 + // Check that this is not a STATIC Source 56.1563 + if(Source->lSourceType == AL_STATIC) 56.1564 + { 56.1565 + // Invalid Source Type (can't queue on a Static Source) 56.1566 + alSetError(Context, AL_INVALID_OPERATION); 56.1567 + goto done; 56.1568 + } 56.1569 + 56.1570 + device = Context->Device; 56.1571 + 56.1572 + BufferFmt = NULL; 56.1573 + 56.1574 + // Check existing Queue (if any) for a valid Buffers and get its frequency and format 56.1575 + BufferList = Source->queue; 56.1576 + while(BufferList) 56.1577 + { 56.1578 + if(BufferList->buffer) 56.1579 + { 56.1580 + BufferFmt = BufferList->buffer; 56.1581 + break; 56.1582 + } 56.1583 + BufferList = BufferList->next; 56.1584 + } 56.1585 + 56.1586 + for(i = 0;i < n;i++) 56.1587 + { 56.1588 + if(!buffers[i]) 56.1589 + continue; 56.1590 + 56.1591 + if((buffer=LookupBuffer(device->BufferMap, buffers[i])) == NULL) 56.1592 + { 56.1593 + alSetError(Context, AL_INVALID_NAME); 56.1594 + goto done; 56.1595 + } 56.1596 + 56.1597 + if(BufferFmt == NULL) 56.1598 + { 56.1599 + BufferFmt = buffer; 56.1600 + 56.1601 + Source->NumChannels = ChannelsFromFmt(buffer->FmtChannels); 56.1602 + Source->SampleSize = BytesFromFmt(buffer->FmtType); 56.1603 + if(buffer->FmtChannels == FmtMono) 56.1604 + Source->Update = CalcSourceParams; 56.1605 + else 56.1606 + Source->Update = CalcNonAttnSourceParams; 56.1607 + 56.1608 + Source->NeedsUpdate = AL_TRUE; 56.1609 + } 56.1610 + else if(BufferFmt->Frequency != buffer->Frequency || 56.1611 + BufferFmt->OriginalChannels != buffer->OriginalChannels || 56.1612 + BufferFmt->OriginalType != buffer->OriginalType) 56.1613 + { 56.1614 + alSetError(Context, AL_INVALID_OPERATION); 56.1615 + goto done; 56.1616 + } 56.1617 + } 56.1618 + 56.1619 + // Change Source Type 56.1620 + Source->lSourceType = AL_STREAMING; 56.1621 + 56.1622 + buffer = LookupBuffer(device->BufferMap, buffers[0]); 56.1623 + 56.1624 + // All buffers are valid - so add them to the list 56.1625 + BufferListStart = malloc(sizeof(ALbufferlistitem)); 56.1626 + BufferListStart->buffer = buffer; 56.1627 + BufferListStart->next = NULL; 56.1628 + BufferListStart->prev = NULL; 56.1629 + 56.1630 + // Increment reference counter for buffer 56.1631 + if(buffer) buffer->refcount++; 56.1632 + 56.1633 + BufferList = BufferListStart; 56.1634 + 56.1635 + for(i = 1;i < n;i++) 56.1636 + { 56.1637 + buffer = LookupBuffer(device->BufferMap, buffers[i]); 56.1638 + 56.1639 + BufferList->next = malloc(sizeof(ALbufferlistitem)); 56.1640 + BufferList->next->buffer = buffer; 56.1641 + BufferList->next->next = NULL; 56.1642 + BufferList->next->prev = BufferList; 56.1643 + 56.1644 + // Increment reference counter for buffer 56.1645 + if(buffer) buffer->refcount++; 56.1646 + 56.1647 + BufferList = BufferList->next; 56.1648 + } 56.1649 + 56.1650 + if(Source->queue == NULL) 56.1651 + { 56.1652 + Source->queue = BufferListStart; 56.1653 + // Update Current Buffer 56.1654 + Source->Buffer = BufferListStart->buffer; 56.1655 + } 56.1656 + else 56.1657 + { 56.1658 + // Find end of queue 56.1659 + BufferList = Source->queue; 56.1660 + while(BufferList->next != NULL) 56.1661 + BufferList = BufferList->next; 56.1662 + 56.1663 + BufferList->next = BufferListStart; 56.1664 + BufferList->next->prev = BufferList; 56.1665 + } 56.1666 + 56.1667 + // Update number of buffers in queue 56.1668 + Source->BuffersInQueue += n; 56.1669 + 56.1670 +done: 56.1671 + UnlockContext(Context); 56.1672 +} 56.1673 + 56.1674 + 56.1675 +// Implementation assumes that n is the number of buffers to be removed from the queue and buffers is 56.1676 +// an array of buffer IDs that are to be filled with the names of the buffers removed 56.1677 +AL_API ALvoid AL_APIENTRY alSourceUnqueueBuffers( ALuint source, ALsizei n, ALuint* buffers ) 56.1678 +{ 56.1679 + ALCcontext *Context; 56.1680 + ALsource *Source; 56.1681 + ALsizei i; 56.1682 + ALbufferlistitem *BufferList; 56.1683 + 56.1684 + if(n == 0) 56.1685 + return; 56.1686 + 56.1687 + Context = GetLockedContext(); 56.1688 + if(!Context) return; 56.1689 + 56.1690 + if(n < 0) 56.1691 + { 56.1692 + alSetError(Context, AL_INVALID_VALUE); 56.1693 + goto done; 56.1694 + } 56.1695 + 56.1696 + if((Source=LookupSource(Context->SourceMap, source)) == NULL) 56.1697 + { 56.1698 + alSetError(Context, AL_INVALID_NAME); 56.1699 + goto done; 56.1700 + } 56.1701 + 56.1702 + if(Source->bLooping || Source->lSourceType != AL_STREAMING || 56.1703 + (ALuint)n > Source->BuffersPlayed) 56.1704 + { 56.1705 + // Some buffers can't be unqueue because they have not been processed 56.1706 + alSetError(Context, AL_INVALID_VALUE); 56.1707 + goto done; 56.1708 + } 56.1709 + 56.1710 + for(i = 0;i < n;i++) 56.1711 + { 56.1712 + BufferList = Source->queue; 56.1713 + Source->queue = BufferList->next; 56.1714 + 56.1715 + if(BufferList->buffer) 56.1716 + { 56.1717 + // Record name of buffer 56.1718 + buffers[i] = BufferList->buffer->buffer; 56.1719 + // Decrement buffer reference counter 56.1720 + BufferList->buffer->refcount--; 56.1721 + } 56.1722 + else 56.1723 + buffers[i] = 0; 56.1724 + 56.1725 + // Release memory for buffer list item 56.1726 + free(BufferList); 56.1727 + Source->BuffersInQueue--; 56.1728 + } 56.1729 + if(Source->queue) 56.1730 + Source->queue->prev = NULL; 56.1731 + 56.1732 + if(Source->state != AL_PLAYING) 56.1733 + { 56.1734 + if(Source->queue) 56.1735 + Source->Buffer = Source->queue->buffer; 56.1736 + else 56.1737 + Source->Buffer = NULL; 56.1738 + } 56.1739 + Source->BuffersPlayed -= n; 56.1740 + 56.1741 +done: 56.1742 + UnlockContext(Context); 56.1743 +} 56.1744 + 56.1745 + 56.1746 +static ALvoid InitSourceParams(ALsource *Source) 56.1747 +{ 56.1748 + Source->flInnerAngle = 360.0f; 56.1749 + Source->flOuterAngle = 360.0f; 56.1750 + Source->flPitch = 1.0f; 56.1751 + Source->vPosition[0] = 0.0f; 56.1752 + Source->vPosition[1] = 0.0f; 56.1753 + Source->vPosition[2] = 0.0f; 56.1754 + Source->vOrientation[0] = 0.0f; 56.1755 + Source->vOrientation[1] = 0.0f; 56.1756 + Source->vOrientation[2] = 0.0f; 56.1757 + Source->vVelocity[0] = 0.0f; 56.1758 + Source->vVelocity[1] = 0.0f; 56.1759 + Source->vVelocity[2] = 0.0f; 56.1760 + Source->flRefDistance = 1.0f; 56.1761 + Source->flMaxDistance = FLT_MAX; 56.1762 + Source->flRollOffFactor = 1.0f; 56.1763 + Source->bLooping = AL_FALSE; 56.1764 + Source->flGain = 1.0f; 56.1765 + Source->flMinGain = 0.0f; 56.1766 + Source->flMaxGain = 1.0f; 56.1767 + Source->flOuterGain = 0.0f; 56.1768 + Source->OuterGainHF = 1.0f; 56.1769 + 56.1770 + Source->DryGainHFAuto = AL_TRUE; 56.1771 + Source->WetGainAuto = AL_TRUE; 56.1772 + Source->WetGainHFAuto = AL_TRUE; 56.1773 + Source->AirAbsorptionFactor = 0.0f; 56.1774 + Source->RoomRolloffFactor = 0.0f; 56.1775 + Source->DopplerFactor = 1.0f; 56.1776 + Source->VirtualChannels = AL_TRUE; 56.1777 + 56.1778 + Source->DistanceModel = AL_INVERSE_DISTANCE_CLAMPED; 56.1779 + 56.1780 + Source->Resampler = DefaultResampler; 56.1781 + 56.1782 + Source->state = AL_INITIAL; 56.1783 + Source->new_state = AL_NONE; 56.1784 + Source->lSourceType = AL_UNDETERMINED; 56.1785 + Source->lOffset = -1; 56.1786 + 56.1787 + Source->NeedsUpdate = AL_TRUE; 56.1788 + 56.1789 + Source->Buffer = NULL; 56.1790 + 56.1791 + Source->HrtfMoving = AL_FALSE; 56.1792 + Source->HrtfCounter = 0; 56.1793 +} 56.1794 + 56.1795 + 56.1796 +/* 56.1797 + * SetSourceState 56.1798 + * 56.1799 + * Sets the source's new play state given its current state 56.1800 + */ 56.1801 +ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state) 56.1802 +{ 56.1803 + if(state == AL_PLAYING) 56.1804 + { 56.1805 + ALbufferlistitem *BufferList; 56.1806 + ALsizei j, k; 56.1807 + 56.1808 + /* Check that there is a queue containing at least one non-null, non zero length AL Buffer */ 56.1809 + BufferList = Source->queue; 56.1810 + while(BufferList) 56.1811 + { 56.1812 + if(BufferList->buffer != NULL && BufferList->buffer->size) 56.1813 + break; 56.1814 + BufferList = BufferList->next; 56.1815 + } 56.1816 + 56.1817 + /* If there's nothing to play, or device is disconnected, go right to 56.1818 + * stopped */ 56.1819 + if(!BufferList || !Context->Device->Connected) 56.1820 + { 56.1821 + SetSourceState(Source, Context, AL_STOPPED); 56.1822 + return; 56.1823 + } 56.1824 + 56.1825 + if(Source->state != AL_PLAYING) 56.1826 + { 56.1827 + for(j = 0;j < MAXCHANNELS;j++) 56.1828 + { 56.1829 + for(k = 0;k < SRC_HISTORY_LENGTH;k++) 56.1830 + Source->HrtfHistory[j][k] = 0.0f; 56.1831 + for(k = 0;k < HRIR_LENGTH;k++) 56.1832 + { 56.1833 + Source->HrtfValues[j][k][0] = 0.0f; 56.1834 + Source->HrtfValues[j][k][1] = 0.0f; 56.1835 + } 56.1836 + } 56.1837 + } 56.1838 + 56.1839 + if(Source->state != AL_PAUSED) 56.1840 + { 56.1841 + Source->state = AL_PLAYING; 56.1842 + Source->position = 0; 56.1843 + Source->position_fraction = 0; 56.1844 + Source->BuffersPlayed = 0; 56.1845 + 56.1846 + Source->Buffer = Source->queue->buffer; 56.1847 + } 56.1848 + else 56.1849 + Source->state = AL_PLAYING; 56.1850 + 56.1851 + // Check if an Offset has been set 56.1852 + if(Source->lOffset != -1) 56.1853 + ApplyOffset(Source); 56.1854 + 56.1855 + for(j = 0;j < Context->ActiveSourceCount;j++) 56.1856 + { 56.1857 + if(Context->ActiveSources[j] == Source) 56.1858 + break; 56.1859 + } 56.1860 + if(j == Context->ActiveSourceCount) 56.1861 + Context->ActiveSources[Context->ActiveSourceCount++] = Source; 56.1862 + } 56.1863 + else if(state == AL_PAUSED) 56.1864 + { 56.1865 + if(Source->state == AL_PLAYING) 56.1866 + { 56.1867 + Source->state = AL_PAUSED; 56.1868 + Source->HrtfMoving = AL_FALSE; 56.1869 + Source->HrtfCounter = 0; 56.1870 + } 56.1871 + } 56.1872 + else if(state == AL_STOPPED) 56.1873 + { 56.1874 + if(Source->state != AL_INITIAL) 56.1875 + { 56.1876 + Source->state = AL_STOPPED; 56.1877 + Source->BuffersPlayed = Source->BuffersInQueue; 56.1878 + Source->HrtfMoving = AL_FALSE; 56.1879 + Source->HrtfCounter = 0; 56.1880 + } 56.1881 + Source->lOffset = -1; 56.1882 + } 56.1883 + else if(state == AL_INITIAL) 56.1884 + { 56.1885 + if(Source->state != AL_INITIAL) 56.1886 + { 56.1887 + Source->state = AL_INITIAL; 56.1888 + Source->position = 0; 56.1889 + Source->position_fraction = 0; 56.1890 + Source->BuffersPlayed = 0; 56.1891 + if(Source->queue) 56.1892 + Source->Buffer = Source->queue->buffer; 56.1893 + Source->HrtfMoving = AL_FALSE; 56.1894 + Source->HrtfCounter = 0; 56.1895 + } 56.1896 + Source->lOffset = -1; 56.1897 + } 56.1898 +} 56.1899 + 56.1900 +/* 56.1901 + GetSourceOffset 56.1902 + 56.1903 + Gets the current playback position in the given Source, in the appropriate format (Bytes, Samples or MilliSeconds) 56.1904 + The offset is relative to the start of the queue (not the start of the current buffer) 56.1905 +*/ 56.1906 +static ALvoid GetSourceOffset(ALsource *Source, ALenum name, ALdouble *offset, ALdouble updateLen) 56.1907 +{ 56.1908 + const ALbufferlistitem *BufferList; 56.1909 + const ALbuffer *Buffer = NULL; 56.1910 + enum UserFmtType OriginalType; 56.1911 + ALsizei BufferFreq; 56.1912 + ALint Channels, Bytes; 56.1913 + ALuint readPos, writePos; 56.1914 + ALuint TotalBufferDataSize; 56.1915 + ALuint i; 56.1916 + 56.1917 + // Find the first non-NULL Buffer in the Queue 56.1918 + BufferList = Source->queue; 56.1919 + while(BufferList) 56.1920 + { 56.1921 + if(BufferList->buffer) 56.1922 + { 56.1923 + Buffer = BufferList->buffer; 56.1924 + break; 56.1925 + } 56.1926 + BufferList = BufferList->next; 56.1927 + } 56.1928 + 56.1929 + if((Source->state != AL_PLAYING && Source->state != AL_PAUSED) || !Buffer) 56.1930 + { 56.1931 + offset[0] = 0.0; 56.1932 + offset[1] = 0.0; 56.1933 + return; 56.1934 + } 56.1935 + 56.1936 + // Get Current Buffer Size and frequency (in milliseconds) 56.1937 + BufferFreq = Buffer->Frequency; 56.1938 + OriginalType = Buffer->OriginalType; 56.1939 + Channels = ChannelsFromFmt(Buffer->FmtChannels); 56.1940 + Bytes = BytesFromFmt(Buffer->FmtType); 56.1941 + 56.1942 + // Get Current BytesPlayed (NOTE : This is the byte offset into the *current* buffer) 56.1943 + readPos = Source->position * Channels * Bytes; 56.1944 + // Add byte length of any processed buffers in the queue 56.1945 + TotalBufferDataSize = 0; 56.1946 + BufferList = Source->queue; 56.1947 + for(i = 0;BufferList;i++) 56.1948 + { 56.1949 + if(BufferList->buffer) 56.1950 + { 56.1951 + if(i < Source->BuffersPlayed) 56.1952 + readPos += BufferList->buffer->size; 56.1953 + TotalBufferDataSize += BufferList->buffer->size; 56.1954 + } 56.1955 + BufferList = BufferList->next; 56.1956 + } 56.1957 + if(Source->state == AL_PLAYING) 56.1958 + writePos = readPos + ((ALuint)(updateLen*BufferFreq) * Channels * Bytes); 56.1959 + else 56.1960 + writePos = readPos; 56.1961 + 56.1962 + if(Source->bLooping) 56.1963 + { 56.1964 + readPos %= TotalBufferDataSize; 56.1965 + writePos %= TotalBufferDataSize; 56.1966 + } 56.1967 + else 56.1968 + { 56.1969 + // Wrap positions back to 0 56.1970 + if(readPos >= TotalBufferDataSize) 56.1971 + readPos = 0; 56.1972 + if(writePos >= TotalBufferDataSize) 56.1973 + writePos = 0; 56.1974 + } 56.1975 + 56.1976 + switch(name) 56.1977 + { 56.1978 + case AL_SEC_OFFSET: 56.1979 + offset[0] = (ALdouble)readPos / (Channels * Bytes * BufferFreq); 56.1980 + offset[1] = (ALdouble)writePos / (Channels * Bytes * BufferFreq); 56.1981 + break; 56.1982 + case AL_SAMPLE_OFFSET: 56.1983 + case AL_SAMPLE_RW_OFFSETS_SOFT: 56.1984 + offset[0] = (ALdouble)(readPos / (Channels * Bytes)); 56.1985 + offset[1] = (ALdouble)(writePos / (Channels * Bytes)); 56.1986 + break; 56.1987 + case AL_BYTE_OFFSET: 56.1988 + case AL_BYTE_RW_OFFSETS_SOFT: 56.1989 + // Take into account the original format of the Buffer 56.1990 + if(OriginalType == UserFmtIMA4) 56.1991 + { 56.1992 + ALuint FrameBlockSize = 65 * Bytes * Channels; 56.1993 + ALuint BlockSize = 36 * Channels; 56.1994 + 56.1995 + // Round down to nearest ADPCM block 56.1996 + offset[0] = (ALdouble)(readPos / FrameBlockSize * BlockSize); 56.1997 + if(Source->state != AL_PLAYING) 56.1998 + offset[1] = offset[0]; 56.1999 + else 56.2000 + { 56.2001 + // Round up to nearest ADPCM block 56.2002 + offset[1] = (ALdouble)((writePos+FrameBlockSize-1) / 56.2003 + FrameBlockSize * BlockSize); 56.2004 + } 56.2005 + } 56.2006 + else 56.2007 + { 56.2008 + ALuint OrigBytes = BytesFromUserFmt(OriginalType); 56.2009 + offset[0] = (ALdouble)(readPos / Bytes * OrigBytes); 56.2010 + offset[1] = (ALdouble)(writePos / Bytes * OrigBytes); 56.2011 + } 56.2012 + break; 56.2013 + } 56.2014 +} 56.2015 + 56.2016 + 56.2017 +/* 56.2018 + ApplyOffset 56.2019 + 56.2020 + Apply a playback offset to the Source. This function will update the queue (to correctly 56.2021 + mark buffers as 'pending' or 'processed' depending upon the new offset. 56.2022 +*/ 56.2023 +ALboolean ApplyOffset(ALsource *Source) 56.2024 +{ 56.2025 + const ALbufferlistitem *BufferList; 56.2026 + const ALbuffer *Buffer; 56.2027 + ALint lBufferSize, lTotalBufferSize; 56.2028 + ALint BuffersPlayed; 56.2029 + ALint lByteOffset; 56.2030 + 56.2031 + // Get true byte offset 56.2032 + lByteOffset = GetByteOffset(Source); 56.2033 + 56.2034 + // If the offset is invalid, don't apply it 56.2035 + if(lByteOffset == -1) 56.2036 + return AL_FALSE; 56.2037 + 56.2038 + // Sort out the queue (pending and processed states) 56.2039 + BufferList = Source->queue; 56.2040 + lTotalBufferSize = 0; 56.2041 + BuffersPlayed = 0; 56.2042 + 56.2043 + while(BufferList) 56.2044 + { 56.2045 + Buffer = BufferList->buffer; 56.2046 + lBufferSize = Buffer ? Buffer->size : 0; 56.2047 + 56.2048 + if(lBufferSize <= lByteOffset-lTotalBufferSize) 56.2049 + { 56.2050 + // Offset is past this buffer so increment BuffersPlayed 56.2051 + BuffersPlayed++; 56.2052 + } 56.2053 + else if(lTotalBufferSize <= lByteOffset) 56.2054 + { 56.2055 + // Offset is within this buffer 56.2056 + // Set Current Buffer 56.2057 + Source->Buffer = BufferList->buffer; 56.2058 + Source->BuffersPlayed = BuffersPlayed; 56.2059 + 56.2060 + // SW Mixer Positions are in Samples 56.2061 + Source->position = (lByteOffset - lTotalBufferSize) / 56.2062 + FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 56.2063 + return AL_TRUE; 56.2064 + } 56.2065 + 56.2066 + // Increment the TotalBufferSize 56.2067 + lTotalBufferSize += lBufferSize; 56.2068 + 56.2069 + // Move on to next buffer in the Queue 56.2070 + BufferList = BufferList->next; 56.2071 + } 56.2072 + // Offset is out of range of the buffer queue 56.2073 + return AL_FALSE; 56.2074 +} 56.2075 + 56.2076 + 56.2077 +/* 56.2078 + GetByteOffset 56.2079 + 56.2080 + Returns the 'true' byte offset into the Source's queue (from the Sample, Byte or Millisecond 56.2081 + offset supplied by the application). This takes into account the fact that the buffer format 56.2082 + may have been modifed by AL (e.g 8bit samples are converted to float) 56.2083 +*/ 56.2084 +static ALint GetByteOffset(ALsource *Source) 56.2085 +{ 56.2086 + const ALbuffer *Buffer = NULL; 56.2087 + const ALbufferlistitem *BufferList; 56.2088 + ALint ByteOffset = -1; 56.2089 + 56.2090 + // Find the first non-NULL Buffer in the Queue 56.2091 + BufferList = Source->queue; 56.2092 + while(BufferList) 56.2093 + { 56.2094 + if(BufferList->buffer) 56.2095 + { 56.2096 + Buffer = BufferList->buffer; 56.2097 + break; 56.2098 + } 56.2099 + BufferList = BufferList->next; 56.2100 + } 56.2101 + 56.2102 + if(!Buffer) 56.2103 + { 56.2104 + Source->lOffset = -1; 56.2105 + return -1; 56.2106 + } 56.2107 + 56.2108 + // Determine the ByteOffset (and ensure it is block aligned) 56.2109 + switch(Source->lOffsetType) 56.2110 + { 56.2111 + case AL_BYTE_OFFSET: 56.2112 + // Take into consideration the original format 56.2113 + ByteOffset = Source->lOffset; 56.2114 + if(Buffer->OriginalType == UserFmtIMA4) 56.2115 + { 56.2116 + // Round down to nearest ADPCM block 56.2117 + ByteOffset /= 36 * ChannelsFromUserFmt(Buffer->OriginalChannels); 56.2118 + // Multiply by compression rate (65 sample frames per block) 56.2119 + ByteOffset *= 65; 56.2120 + } 56.2121 + else 56.2122 + ByteOffset /= FrameSizeFromUserFmt(Buffer->OriginalChannels, Buffer->OriginalType); 56.2123 + ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 56.2124 + break; 56.2125 + 56.2126 + case AL_SAMPLE_OFFSET: 56.2127 + ByteOffset = Source->lOffset * FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 56.2128 + break; 56.2129 + 56.2130 + case AL_SEC_OFFSET: 56.2131 + // Note - lOffset is internally stored as Milliseconds 56.2132 + ByteOffset = (ALint)(Source->lOffset / 1000.0 * Buffer->Frequency); 56.2133 + ByteOffset *= FrameSizeFromFmt(Buffer->FmtChannels, Buffer->FmtType); 56.2134 + break; 56.2135 + } 56.2136 + // Clear Offset 56.2137 + Source->lOffset = -1; 56.2138 + 56.2139 + return ByteOffset; 56.2140 +} 56.2141 + 56.2142 + 56.2143 +ALvoid ReleaseALSources(ALCcontext *Context) 56.2144 +{ 56.2145 + ALsizei pos; 56.2146 + ALuint j; 56.2147 + for(pos = 0;pos < Context->SourceMap.size;pos++) 56.2148 + { 56.2149 + ALsource *temp = Context->SourceMap.array[pos].value; 56.2150 + Context->SourceMap.array[pos].value = NULL; 56.2151 + 56.2152 + // For each buffer in the source's queue, decrement its reference counter and remove it 56.2153 + while(temp->queue != NULL) 56.2154 + { 56.2155 + ALbufferlistitem *BufferList = temp->queue; 56.2156 + temp->queue = BufferList->next; 56.2157 + 56.2158 + if(BufferList->buffer != NULL) 56.2159 + BufferList->buffer->refcount--; 56.2160 + free(BufferList); 56.2161 + } 56.2162 + 56.2163 + for(j = 0;j < MAX_SENDS;++j) 56.2164 + { 56.2165 + if(temp->Send[j].Slot) 56.2166 + temp->Send[j].Slot->refcount--; 56.2167 + temp->Send[j].Slot = NULL; 56.2168 + } 56.2169 + 56.2170 + // Release source structure 56.2171 + FreeThunkEntry(temp->source); 56.2172 + memset(temp, 0, sizeof(ALsource)); 56.2173 + free(temp); 56.2174 + } 56.2175 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 57.2 +++ b/OpenAL32/alState.c Tue Oct 25 13:02:31 2011 -0700 57.3 @@ -0,0 +1,658 @@ 57.4 +/** 57.5 + * OpenAL cross platform audio library 57.6 + * Copyright (C) 1999-2000 by authors. 57.7 + * This library is free software; you can redistribute it and/or 57.8 + * modify it under the terms of the GNU Library General Public 57.9 + * License as published by the Free Software Foundation; either 57.10 + * version 2 of the License, or (at your option) any later version. 57.11 + * 57.12 + * This library is distributed in the hope that it will be useful, 57.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 57.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 57.15 + * Library General Public License for more details. 57.16 + * 57.17 + * You should have received a copy of the GNU Library General Public 57.18 + * License along with this library; if not, write to the 57.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 57.20 + * Boston, MA 02111-1307, USA. 57.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 57.22 + */ 57.23 + 57.24 +#include "config.h" 57.25 + 57.26 +#include <stdlib.h> 57.27 +#include "alMain.h" 57.28 +#include "AL/alc.h" 57.29 +#include "AL/alext.h" 57.30 +#include "alError.h" 57.31 +#include "alSource.h" 57.32 +#include "alAuxEffectSlot.h" 57.33 +#include "alState.h" 57.34 + 57.35 +static const ALchar alVendor[] = "OpenAL Community"; 57.36 +static const ALchar alVersion[] = "1.1 ALSOFT "ALSOFT_VERSION; 57.37 +static const ALchar alRenderer[] = "OpenAL Soft"; 57.38 + 57.39 +// Error Messages 57.40 +static const ALchar alNoError[] = "No Error"; 57.41 +static const ALchar alErrInvalidName[] = "Invalid Name"; 57.42 +static const ALchar alErrInvalidEnum[] = "Invalid Enum"; 57.43 +static const ALchar alErrInvalidValue[] = "Invalid Value"; 57.44 +static const ALchar alErrInvalidOp[] = "Invalid Operation"; 57.45 +static const ALchar alErrOutOfMemory[] = "Out of Memory"; 57.46 + 57.47 +AL_API ALvoid AL_APIENTRY alEnable(ALenum capability) 57.48 +{ 57.49 + ALCcontext *Context; 57.50 + 57.51 + Context = GetLockedContext(); 57.52 + if(!Context) return; 57.53 + 57.54 + switch(capability) 57.55 + { 57.56 + case AL_SOURCE_DISTANCE_MODEL: 57.57 + Context->SourceDistanceModel = AL_TRUE; 57.58 + Context->UpdateSources = AL_TRUE; 57.59 + break; 57.60 + 57.61 + default: 57.62 + alSetError(Context, AL_INVALID_ENUM); 57.63 + break; 57.64 + } 57.65 + 57.66 + UnlockContext(Context); 57.67 +} 57.68 + 57.69 +AL_API ALvoid AL_APIENTRY alDisable(ALenum capability) 57.70 +{ 57.71 + ALCcontext *Context; 57.72 + 57.73 + Context = GetLockedContext(); 57.74 + if(!Context) return; 57.75 + 57.76 + switch(capability) 57.77 + { 57.78 + case AL_SOURCE_DISTANCE_MODEL: 57.79 + Context->SourceDistanceModel = AL_FALSE; 57.80 + Context->UpdateSources = AL_TRUE; 57.81 + break; 57.82 + 57.83 + default: 57.84 + alSetError(Context, AL_INVALID_ENUM); 57.85 + break; 57.86 + } 57.87 + 57.88 + UnlockContext(Context); 57.89 +} 57.90 + 57.91 +AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability) 57.92 +{ 57.93 + ALCcontext *Context; 57.94 + ALboolean value=AL_FALSE; 57.95 + 57.96 + Context = GetLockedContext(); 57.97 + if(!Context) return AL_FALSE; 57.98 + 57.99 + switch(capability) 57.100 + { 57.101 + case AL_SOURCE_DISTANCE_MODEL: 57.102 + value = Context->SourceDistanceModel; 57.103 + break; 57.104 + 57.105 + default: 57.106 + alSetError(Context, AL_INVALID_ENUM); 57.107 + break; 57.108 + } 57.109 + 57.110 + UnlockContext(Context); 57.111 + 57.112 + return value; 57.113 +} 57.114 + 57.115 +AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname) 57.116 +{ 57.117 + ALCcontext *Context; 57.118 + ALboolean value=AL_FALSE; 57.119 + 57.120 + Context = GetLockedContext(); 57.121 + if(!Context) return AL_FALSE; 57.122 + 57.123 + switch(pname) 57.124 + { 57.125 + case AL_DOPPLER_FACTOR: 57.126 + if(Context->DopplerFactor != 0.0f) 57.127 + value = AL_TRUE; 57.128 + break; 57.129 + 57.130 + case AL_DOPPLER_VELOCITY: 57.131 + if(Context->DopplerVelocity != 0.0f) 57.132 + value = AL_TRUE; 57.133 + break; 57.134 + 57.135 + case AL_DISTANCE_MODEL: 57.136 + if(Context->DistanceModel == AL_INVERSE_DISTANCE_CLAMPED) 57.137 + value = AL_TRUE; 57.138 + break; 57.139 + 57.140 + case AL_SPEED_OF_SOUND: 57.141 + if(Context->flSpeedOfSound != 0.0f) 57.142 + value = AL_TRUE; 57.143 + break; 57.144 + 57.145 + case AL_DEFERRED_UPDATES_SOFT: 57.146 + value = Context->DeferUpdates; 57.147 + break; 57.148 + 57.149 + default: 57.150 + alSetError(Context, AL_INVALID_ENUM); 57.151 + break; 57.152 + } 57.153 + 57.154 + UnlockContext(Context); 57.155 + 57.156 + return value; 57.157 +} 57.158 + 57.159 +AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname) 57.160 +{ 57.161 + ALCcontext *Context; 57.162 + ALdouble value = 0.0; 57.163 + 57.164 + Context = GetLockedContext(); 57.165 + if(!Context) return 0.0; 57.166 + 57.167 + switch(pname) 57.168 + { 57.169 + case AL_DOPPLER_FACTOR: 57.170 + value = (double)Context->DopplerFactor; 57.171 + break; 57.172 + 57.173 + case AL_DOPPLER_VELOCITY: 57.174 + value = (double)Context->DopplerVelocity; 57.175 + break; 57.176 + 57.177 + case AL_DISTANCE_MODEL: 57.178 + value = (double)Context->DistanceModel; 57.179 + break; 57.180 + 57.181 + case AL_SPEED_OF_SOUND: 57.182 + value = (double)Context->flSpeedOfSound; 57.183 + break; 57.184 + 57.185 + case AL_DEFERRED_UPDATES_SOFT: 57.186 + value = (ALdouble)Context->DeferUpdates; 57.187 + break; 57.188 + 57.189 + default: 57.190 + alSetError(Context, AL_INVALID_ENUM); 57.191 + break; 57.192 + } 57.193 + 57.194 + UnlockContext(Context); 57.195 + 57.196 + return value; 57.197 +} 57.198 + 57.199 +AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname) 57.200 +{ 57.201 + ALCcontext *Context; 57.202 + ALfloat value = 0.0f; 57.203 + 57.204 + Context = GetLockedContext(); 57.205 + if(!Context) return 0.0f; 57.206 + 57.207 + switch(pname) 57.208 + { 57.209 + case AL_DOPPLER_FACTOR: 57.210 + value = Context->DopplerFactor; 57.211 + break; 57.212 + 57.213 + case AL_DOPPLER_VELOCITY: 57.214 + value = Context->DopplerVelocity; 57.215 + break; 57.216 + 57.217 + case AL_DISTANCE_MODEL: 57.218 + value = (float)Context->DistanceModel; 57.219 + break; 57.220 + 57.221 + case AL_SPEED_OF_SOUND: 57.222 + value = Context->flSpeedOfSound; 57.223 + break; 57.224 + 57.225 + case AL_DEFERRED_UPDATES_SOFT: 57.226 + value = (ALfloat)Context->DeferUpdates; 57.227 + break; 57.228 + 57.229 + default: 57.230 + alSetError(Context, AL_INVALID_ENUM); 57.231 + break; 57.232 + } 57.233 + 57.234 + UnlockContext(Context); 57.235 + 57.236 + return value; 57.237 +} 57.238 + 57.239 +AL_API ALint AL_APIENTRY alGetInteger(ALenum pname) 57.240 +{ 57.241 + ALCcontext *Context; 57.242 + ALint value = 0; 57.243 + 57.244 + Context = GetLockedContext(); 57.245 + if(!Context) return 0; 57.246 + 57.247 + switch(pname) 57.248 + { 57.249 + case AL_DOPPLER_FACTOR: 57.250 + value = (ALint)Context->DopplerFactor; 57.251 + break; 57.252 + 57.253 + case AL_DOPPLER_VELOCITY: 57.254 + value = (ALint)Context->DopplerVelocity; 57.255 + break; 57.256 + 57.257 + case AL_DISTANCE_MODEL: 57.258 + value = (ALint)Context->DistanceModel; 57.259 + break; 57.260 + 57.261 + case AL_SPEED_OF_SOUND: 57.262 + value = (ALint)Context->flSpeedOfSound; 57.263 + break; 57.264 + 57.265 + case AL_DEFERRED_UPDATES_SOFT: 57.266 + value = (ALint)Context->DeferUpdates; 57.267 + break; 57.268 + 57.269 + default: 57.270 + alSetError(Context, AL_INVALID_ENUM); 57.271 + break; 57.272 + } 57.273 + 57.274 + UnlockContext(Context); 57.275 + 57.276 + return value; 57.277 +} 57.278 + 57.279 +AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname,ALboolean *data) 57.280 +{ 57.281 + ALCcontext *Context; 57.282 + 57.283 + if(data) 57.284 + { 57.285 + switch(pname) 57.286 + { 57.287 + case AL_DOPPLER_FACTOR: 57.288 + case AL_DOPPLER_VELOCITY: 57.289 + case AL_DISTANCE_MODEL: 57.290 + case AL_SPEED_OF_SOUND: 57.291 + case AL_DEFERRED_UPDATES_SOFT: 57.292 + *data = alGetBoolean(pname); 57.293 + return; 57.294 + } 57.295 + } 57.296 + 57.297 + Context = GetLockedContext(); 57.298 + if(!Context) return; 57.299 + 57.300 + if(data) 57.301 + { 57.302 + switch(pname) 57.303 + { 57.304 + default: 57.305 + alSetError(Context, AL_INVALID_ENUM); 57.306 + break; 57.307 + } 57.308 + } 57.309 + else 57.310 + { 57.311 + // data is a NULL pointer 57.312 + alSetError(Context, AL_INVALID_VALUE); 57.313 + } 57.314 + 57.315 + UnlockContext(Context); 57.316 +} 57.317 + 57.318 +AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname,ALdouble *data) 57.319 +{ 57.320 + ALCcontext *Context; 57.321 + 57.322 + if(data) 57.323 + { 57.324 + switch(pname) 57.325 + { 57.326 + case AL_DOPPLER_FACTOR: 57.327 + case AL_DOPPLER_VELOCITY: 57.328 + case AL_DISTANCE_MODEL: 57.329 + case AL_SPEED_OF_SOUND: 57.330 + case AL_DEFERRED_UPDATES_SOFT: 57.331 + *data = alGetDouble(pname); 57.332 + return; 57.333 + } 57.334 + } 57.335 + 57.336 + Context = GetLockedContext(); 57.337 + if(!Context) return; 57.338 + 57.339 + if(data) 57.340 + { 57.341 + switch(pname) 57.342 + { 57.343 + default: 57.344 + alSetError(Context, AL_INVALID_ENUM); 57.345 + break; 57.346 + } 57.347 + } 57.348 + else 57.349 + { 57.350 + // data is a NULL pointer 57.351 + alSetError(Context, AL_INVALID_VALUE); 57.352 + } 57.353 + 57.354 + UnlockContext(Context); 57.355 +} 57.356 + 57.357 +AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname,ALfloat *data) 57.358 +{ 57.359 + ALCcontext *Context; 57.360 + 57.361 + if(data) 57.362 + { 57.363 + switch(pname) 57.364 + { 57.365 + case AL_DOPPLER_FACTOR: 57.366 + case AL_DOPPLER_VELOCITY: 57.367 + case AL_DISTANCE_MODEL: 57.368 + case AL_SPEED_OF_SOUND: 57.369 + case AL_DEFERRED_UPDATES_SOFT: 57.370 + *data = alGetFloat(pname); 57.371 + return; 57.372 + } 57.373 + } 57.374 + 57.375 + Context = GetLockedContext(); 57.376 + if(!Context) return; 57.377 + 57.378 + if(data) 57.379 + { 57.380 + switch(pname) 57.381 + { 57.382 + default: 57.383 + alSetError(Context, AL_INVALID_ENUM); 57.384 + break; 57.385 + } 57.386 + } 57.387 + else 57.388 + { 57.389 + // data is a NULL pointer 57.390 + alSetError(Context, AL_INVALID_VALUE); 57.391 + } 57.392 + 57.393 + UnlockContext(Context); 57.394 +} 57.395 + 57.396 +AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname,ALint *data) 57.397 +{ 57.398 + ALCcontext *Context; 57.399 + 57.400 + if(data) 57.401 + { 57.402 + switch(pname) 57.403 + { 57.404 + case AL_DOPPLER_FACTOR: 57.405 + case AL_DOPPLER_VELOCITY: 57.406 + case AL_DISTANCE_MODEL: 57.407 + case AL_SPEED_OF_SOUND: 57.408 + case AL_DEFERRED_UPDATES_SOFT: 57.409 + *data = alGetInteger(pname); 57.410 + return; 57.411 + } 57.412 + } 57.413 + 57.414 + Context = GetLockedContext(); 57.415 + if(!Context) return; 57.416 + 57.417 + if(data) 57.418 + { 57.419 + switch(pname) 57.420 + { 57.421 + default: 57.422 + alSetError(Context, AL_INVALID_ENUM); 57.423 + break; 57.424 + } 57.425 + } 57.426 + else 57.427 + { 57.428 + // data is a NULL pointer 57.429 + alSetError(Context, AL_INVALID_VALUE); 57.430 + } 57.431 + 57.432 + UnlockContext(Context); 57.433 +} 57.434 + 57.435 +AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname) 57.436 +{ 57.437 + const ALchar *value; 57.438 + ALCcontext *pContext; 57.439 + 57.440 + pContext = GetLockedContext(); 57.441 + if(!pContext) return NULL; 57.442 + 57.443 + switch(pname) 57.444 + { 57.445 + case AL_VENDOR: 57.446 + value=alVendor; 57.447 + break; 57.448 + 57.449 + case AL_VERSION: 57.450 + value=alVersion; 57.451 + break; 57.452 + 57.453 + case AL_RENDERER: 57.454 + value=alRenderer; 57.455 + break; 57.456 + 57.457 + case AL_EXTENSIONS: 57.458 + value=pContext->ExtensionList;//alExtensions; 57.459 + break; 57.460 + 57.461 + case AL_NO_ERROR: 57.462 + value=alNoError; 57.463 + break; 57.464 + 57.465 + case AL_INVALID_NAME: 57.466 + value=alErrInvalidName; 57.467 + break; 57.468 + 57.469 + case AL_INVALID_ENUM: 57.470 + value=alErrInvalidEnum; 57.471 + break; 57.472 + 57.473 + case AL_INVALID_VALUE: 57.474 + value=alErrInvalidValue; 57.475 + break; 57.476 + 57.477 + case AL_INVALID_OPERATION: 57.478 + value=alErrInvalidOp; 57.479 + break; 57.480 + 57.481 + case AL_OUT_OF_MEMORY: 57.482 + value=alErrOutOfMemory; 57.483 + break; 57.484 + 57.485 + default: 57.486 + value=NULL; 57.487 + alSetError(pContext, AL_INVALID_ENUM); 57.488 + break; 57.489 + } 57.490 + 57.491 + UnlockContext(pContext); 57.492 + 57.493 + return value; 57.494 +} 57.495 + 57.496 +AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value) 57.497 +{ 57.498 + ALCcontext *Context; 57.499 + 57.500 + Context = GetLockedContext(); 57.501 + if(!Context) return; 57.502 + 57.503 + if(value >= 0.0f && isfinite(value)) 57.504 + { 57.505 + Context->DopplerFactor = value; 57.506 + Context->UpdateSources = AL_TRUE; 57.507 + } 57.508 + else 57.509 + alSetError(Context, AL_INVALID_VALUE); 57.510 + 57.511 + UnlockContext(Context); 57.512 +} 57.513 + 57.514 +AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value) 57.515 +{ 57.516 + ALCcontext *Context; 57.517 + 57.518 + Context = GetLockedContext(); 57.519 + if(!Context) return; 57.520 + 57.521 + if(value > 0.0f && isfinite(value)) 57.522 + { 57.523 + Context->DopplerVelocity=value; 57.524 + Context->UpdateSources = AL_TRUE; 57.525 + } 57.526 + else 57.527 + alSetError(Context, AL_INVALID_VALUE); 57.528 + 57.529 + UnlockContext(Context); 57.530 +} 57.531 + 57.532 +AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat flSpeedOfSound) 57.533 +{ 57.534 + ALCcontext *pContext; 57.535 + 57.536 + pContext = GetLockedContext(); 57.537 + if(!pContext) return; 57.538 + 57.539 + if(flSpeedOfSound > 0.0f && isfinite(flSpeedOfSound)) 57.540 + { 57.541 + pContext->flSpeedOfSound = flSpeedOfSound; 57.542 + pContext->UpdateSources = AL_TRUE; 57.543 + } 57.544 + else 57.545 + alSetError(pContext, AL_INVALID_VALUE); 57.546 + 57.547 + UnlockContext(pContext); 57.548 +} 57.549 + 57.550 +AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value) 57.551 +{ 57.552 + ALCcontext *Context; 57.553 + 57.554 + Context = GetLockedContext(); 57.555 + if(!Context) return; 57.556 + 57.557 + switch(value) 57.558 + { 57.559 + case AL_NONE: 57.560 + case AL_INVERSE_DISTANCE: 57.561 + case AL_INVERSE_DISTANCE_CLAMPED: 57.562 + case AL_LINEAR_DISTANCE: 57.563 + case AL_LINEAR_DISTANCE_CLAMPED: 57.564 + case AL_EXPONENT_DISTANCE: 57.565 + case AL_EXPONENT_DISTANCE_CLAMPED: 57.566 + Context->DistanceModel = value; 57.567 + Context->UpdateSources = AL_TRUE; 57.568 + break; 57.569 + 57.570 + default: 57.571 + alSetError(Context, AL_INVALID_VALUE); 57.572 + break; 57.573 + } 57.574 + 57.575 + UnlockContext(Context); 57.576 +} 57.577 + 57.578 + 57.579 +AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void) 57.580 +{ 57.581 + ALCcontext *Context; 57.582 + 57.583 + Context = GetLockedContext(); 57.584 + if(!Context) return; 57.585 + 57.586 + if(!Context->DeferUpdates) 57.587 + { 57.588 + ALboolean UpdateSources; 57.589 + ALsource **src, **src_end; 57.590 + ALeffectslot *ALEffectSlot; 57.591 + ALsizei e; 57.592 + 57.593 + Context->DeferUpdates = AL_TRUE; 57.594 + 57.595 + /* Make sure all pending updates are performed */ 57.596 + UpdateSources = Context->UpdateSources; 57.597 + Context->UpdateSources = AL_FALSE; 57.598 + 57.599 + src = Context->ActiveSources; 57.600 + src_end = src + Context->ActiveSourceCount; 57.601 + while(src != src_end) 57.602 + { 57.603 + if((*src)->state != AL_PLAYING) 57.604 + { 57.605 + Context->ActiveSourceCount--; 57.606 + *src = *(--src_end); 57.607 + continue; 57.608 + } 57.609 + 57.610 + if((*src)->NeedsUpdate || UpdateSources) 57.611 + { 57.612 + (*src)->NeedsUpdate = AL_FALSE; 57.613 + ALsource_Update(*src, Context); 57.614 + } 57.615 + src++; 57.616 + } 57.617 + 57.618 + for(e = 0;e < Context->EffectSlotMap.size;e++) 57.619 + { 57.620 + ALEffectSlot = Context->EffectSlotMap.array[e].value; 57.621 + if(ALEffectSlot->NeedsUpdate) 57.622 + { 57.623 + ALEffectSlot->NeedsUpdate = AL_FALSE; 57.624 + ALEffect_Update(ALEffectSlot->EffectState, Context, ALEffectSlot); 57.625 + } 57.626 + } 57.627 + } 57.628 + 57.629 + UnlockContext(Context); 57.630 +} 57.631 + 57.632 +AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void) 57.633 +{ 57.634 + ALCcontext *Context; 57.635 + 57.636 + Context = GetLockedContext(); 57.637 + if(!Context) return; 57.638 + 57.639 + if(Context->DeferUpdates) 57.640 + { 57.641 + ALsizei pos; 57.642 + 57.643 + Context->DeferUpdates = AL_FALSE; 57.644 + 57.645 + for(pos = 0;pos < Context->SourceMap.size;pos++) 57.646 + { 57.647 + ALsource *Source = Context->SourceMap.array[pos].value; 57.648 + ALenum new_state; 57.649 + 57.650 + if(Source->lOffset != -1) 57.651 + ApplyOffset(Source); 57.652 + 57.653 + new_state = Source->new_state; 57.654 + Source->new_state = AL_NONE; 57.655 + if(new_state) 57.656 + SetSourceState(Source, Context, new_state); 57.657 + } 57.658 + } 57.659 + 57.660 + UnlockContext(Context); 57.661 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 58.2 +++ b/OpenAL32/alThunk.c Tue Oct 25 13:02:31 2011 -0700 58.3 @@ -0,0 +1,93 @@ 58.4 +/** 58.5 + * OpenAL cross platform audio library 58.6 + * Copyright (C) 1999-2007 by authors. 58.7 + * This library is free software; you can redistribute it and/or 58.8 + * modify it under the terms of the GNU Library General Public 58.9 + * License as published by the Free Software Foundation; either 58.10 + * version 2 of the License, or (at your option) any later version. 58.11 + * 58.12 + * This library is distributed in the hope that it will be useful, 58.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 58.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 58.15 + * Library General Public License for more details. 58.16 + * 58.17 + * You should have received a copy of the GNU Library General Public 58.18 + * License along with this library; if not, write to the 58.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 58.20 + * Boston, MA 02111-1307, USA. 58.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 58.22 + */ 58.23 + 58.24 +#include "config.h" 58.25 + 58.26 +#include <stdlib.h> 58.27 + 58.28 +#include "alMain.h" 58.29 +#include "alThunk.h" 58.30 + 58.31 + 58.32 +static ALboolean *ThunkArray; 58.33 +static ALuint ThunkArraySize; 58.34 + 58.35 +static CRITICAL_SECTION ThunkLock; 58.36 + 58.37 +void ThunkInit(void) 58.38 +{ 58.39 + InitializeCriticalSection(&ThunkLock); 58.40 + ThunkArraySize = 1; 58.41 + ThunkArray = calloc(1, ThunkArraySize * sizeof(*ThunkArray)); 58.42 +} 58.43 + 58.44 +void ThunkExit(void) 58.45 +{ 58.46 + free(ThunkArray); 58.47 + ThunkArray = NULL; 58.48 + ThunkArraySize = 0; 58.49 + DeleteCriticalSection(&ThunkLock); 58.50 +} 58.51 + 58.52 +ALenum NewThunkEntry(ALuint *index) 58.53 +{ 58.54 + ALuint i; 58.55 + 58.56 + EnterCriticalSection(&ThunkLock); 58.57 + 58.58 + for(i = 0;i < ThunkArraySize;i++) 58.59 + { 58.60 + if(ThunkArray[i] == AL_FALSE) 58.61 + break; 58.62 + } 58.63 + 58.64 + if(i == ThunkArraySize) 58.65 + { 58.66 + ALboolean *NewList; 58.67 + 58.68 + NewList = realloc(ThunkArray, ThunkArraySize*2 * sizeof(*ThunkArray)); 58.69 + if(!NewList) 58.70 + { 58.71 + LeaveCriticalSection(&ThunkLock); 58.72 + ERR("Realloc failed to increase to %u enties!\n", ThunkArraySize*2); 58.73 + return AL_OUT_OF_MEMORY; 58.74 + } 58.75 + memset(&NewList[ThunkArraySize], 0, ThunkArraySize*sizeof(*ThunkArray)); 58.76 + ThunkArraySize *= 2; 58.77 + ThunkArray = NewList; 58.78 + } 58.79 + 58.80 + ThunkArray[i] = AL_TRUE; 58.81 + *index = i+1; 58.82 + 58.83 + LeaveCriticalSection(&ThunkLock); 58.84 + 58.85 + return AL_NO_ERROR; 58.86 +} 58.87 + 58.88 +void FreeThunkEntry(ALuint index) 58.89 +{ 58.90 + EnterCriticalSection(&ThunkLock); 58.91 + 58.92 + if(index > 0 && index <= ThunkArraySize) 58.93 + ThunkArray[index-1] = AL_FALSE; 58.94 + 58.95 + LeaveCriticalSection(&ThunkLock); 58.96 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 59.2 +++ b/README Tue Oct 25 13:02:31 2011 -0700 59.3 @@ -0,0 +1,53 @@ 59.4 +Source Install 59.5 +============== 59.6 + 59.7 +To install OpenAL Soft, use your favorite shell to go into the build/ 59.8 +directory, and run: 59.9 + 59.10 +cmake .. 59.11 + 59.12 +Assuming configuration went well, you can then build it, typically using GNU 59.13 +Make (KDevelop, MSVC, and others are possible depending on your system setup 59.14 +and CMake configuration). 59.15 + 59.16 +Please Note: Double check that the appropriate backends were detected. Often, 59.17 +complaints of no sound, crashing, and missing devices can be solved by making 59.18 +sure the correct backends are being used. CMake's output will identify which 59.19 +backends were enabled. 59.20 + 59.21 +For most systems, you will likely want to make sure ALSA, OSS, and PulseAudio 59.22 +were detected (if your target system uses them). For Windows, make sure 59.23 +DirectSound was detected. 59.24 + 59.25 + 59.26 +Utilities 59.27 +========= 59.28 + 59.29 +The source package comes with an informational utility, openal-info, and is 59.30 +built by default. It prints out information provided by the ALC and AL sub- 59.31 +systems, including discovered devices, version information, and extensions. 59.32 + 59.33 + 59.34 +Configuration 59.35 +============= 59.36 + 59.37 +OpenAL Soft can be configured on a per-user and per-system basis. This allows 59.38 +users and sysadmins to control information provided to applications, as well 59.39 +as application-agnostic behavior of the library. See alsoftrc.sample for 59.40 +available settings. 59.41 + 59.42 + 59.43 +Acknowledgements 59.44 +================ 59.45 + 59.46 +Special thanks go to: 59.47 + 59.48 +Creative Labs for the original source code this is based off of. 59.49 + 59.50 +Christopher Fitzgerald for the current reverb effect implementation, and 59.51 +helping with the low-pass filter. 59.52 + 59.53 +Christian Borss for the 3D panning code the current implementation is heavilly 59.54 +based on. 59.55 + 59.56 +Ben Davis for the idea behind the current click-removal code.
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 60.2 +++ b/RecordAudioRenderer.java Tue Oct 25 13:02:31 2011 -0700 60.3 @@ -0,0 +1,1183 @@ 60.4 +package com.jme3.capture; 60.5 + 60.6 +import static org.lwjgl.openal.AL10.AL_BUFFER; 60.7 +import static org.lwjgl.openal.AL10.AL_BUFFERS_PROCESSED; 60.8 +import static org.lwjgl.openal.AL10.AL_CONE_INNER_ANGLE; 60.9 +import static org.lwjgl.openal.AL10.AL_CONE_OUTER_ANGLE; 60.10 +import static org.lwjgl.openal.AL10.AL_CONE_OUTER_GAIN; 60.11 +import static org.lwjgl.openal.AL10.AL_DIRECTION; 60.12 +import static org.lwjgl.openal.AL10.AL_FALSE; 60.13 +import static org.lwjgl.openal.AL10.AL_FORMAT_MONO16; 60.14 +import static org.lwjgl.openal.AL10.AL_FORMAT_MONO8; 60.15 +import static org.lwjgl.openal.AL10.AL_FORMAT_STEREO16; 60.16 +import static org.lwjgl.openal.AL10.AL_FORMAT_STEREO8; 60.17 +import static org.lwjgl.openal.AL10.AL_GAIN; 60.18 +import static org.lwjgl.openal.AL10.AL_LOOPING; 60.19 +import static org.lwjgl.openal.AL10.AL_MAX_DISTANCE; 60.20 +import static org.lwjgl.openal.AL10.AL_ORIENTATION; 60.21 +import static org.lwjgl.openal.AL10.AL_PAUSED; 60.22 +import static org.lwjgl.openal.AL10.AL_PITCH; 60.23 +import static org.lwjgl.openal.AL10.AL_POSITION; 60.24 +import static org.lwjgl.openal.AL10.AL_REFERENCE_DISTANCE; 60.25 +import static org.lwjgl.openal.AL10.AL_RENDERER; 60.26 +import static org.lwjgl.openal.AL10.AL_SOURCE_RELATIVE; 60.27 +import static org.lwjgl.openal.AL10.AL_SOURCE_STATE; 60.28 +import static org.lwjgl.openal.AL10.AL_STOPPED; 60.29 +import static org.lwjgl.openal.AL10.AL_TRUE; 60.30 +import static org.lwjgl.openal.AL10.AL_VELOCITY; 60.31 +import static org.lwjgl.openal.AL10.AL_VENDOR; 60.32 +import static org.lwjgl.openal.AL10.AL_VERSION; 60.33 +import static org.lwjgl.openal.AL10.alBufferData; 60.34 +import static org.lwjgl.openal.AL10.alDeleteBuffers; 60.35 +import static org.lwjgl.openal.AL10.alDeleteSources; 60.36 +import static org.lwjgl.openal.AL10.alGenBuffers; 60.37 +import static org.lwjgl.openal.AL10.alGenSources; 60.38 +import static org.lwjgl.openal.AL10.alGetError; 60.39 +import static org.lwjgl.openal.AL10.alGetSourcei; 60.40 +import static org.lwjgl.openal.AL10.alGetString; 60.41 +import static org.lwjgl.openal.AL10.alListener; 60.42 +import static org.lwjgl.openal.AL10.alListener3f; 60.43 +import static org.lwjgl.openal.AL10.alListenerf; 60.44 +import static org.lwjgl.openal.AL10.alSource3f; 60.45 +import static org.lwjgl.openal.AL10.alSourcePause; 60.46 +import static org.lwjgl.openal.AL10.alSourcePlay; 60.47 +import static org.lwjgl.openal.AL10.alSourceQueueBuffers; 60.48 +import static org.lwjgl.openal.AL10.alSourceStop; 60.49 +import static org.lwjgl.openal.AL10.alSourceUnqueueBuffers; 60.50 +import static org.lwjgl.openal.AL10.alSourcef; 60.51 +import static org.lwjgl.openal.AL10.alSourcei; 60.52 + 60.53 +import java.lang.reflect.Field; 60.54 +import java.nio.ByteBuffer; 60.55 +import java.nio.FloatBuffer; 60.56 +import java.nio.IntBuffer; 60.57 +import java.util.ArrayList; 60.58 +import java.util.Vector; 60.59 +import java.util.concurrent.atomic.AtomicBoolean; 60.60 +import java.util.logging.Level; 60.61 +import java.util.logging.Logger; 60.62 + 60.63 +import org.lwjgl.LWJGLException; 60.64 +import org.lwjgl.openal.AL; 60.65 +import org.lwjgl.openal.AL11; 60.66 +import org.lwjgl.openal.ALC10; 60.67 +import org.lwjgl.openal.ALCdevice; 60.68 +import org.lwjgl.openal.EFX10; 60.69 +import org.lwjgl.openal.OpenALException; 60.70 + 60.71 +import com.jme3.audio.AudioBuffer; 60.72 +import com.jme3.audio.AudioData; 60.73 +import com.jme3.audio.AudioNode; 60.74 +import com.jme3.audio.AudioNode.Status; 60.75 +import com.jme3.audio.AudioParam; 60.76 +import com.jme3.audio.AudioRenderer; 60.77 +import com.jme3.audio.AudioStream; 60.78 +import com.jme3.audio.Environment; 60.79 +import com.jme3.audio.Filter; 60.80 +import com.jme3.audio.Listener; 60.81 +import com.jme3.audio.ListenerParam; 60.82 +import com.jme3.audio.LowPassFilter; 60.83 +import com.jme3.math.Vector3f; 60.84 +import com.jme3.util.BufferUtils; 60.85 + 60.86 + 60.87 + 60.88 +public class RecordAudioRenderer implements AudioRenderer, Runnable { 60.89 + 60.90 + 60.91 + 60.92 + public static void getMainSamples(){ 60.93 + 60.94 + } 60.95 + 60.96 + 60.97 + private static final Logger logger = Logger.getLogger(RecordAudioRenderer.class.getName()); 60.98 + 60.99 + // When multiplied by STREAMING_BUFFER_COUNT, will equal 44100 * 2 * 2 60.100 + // which is exactly 1 second of audio. 60.101 + private static final int BUFFER_SIZE = 35280; 60.102 + private static final int STREAMING_BUFFER_COUNT = 5; 60.103 + 60.104 + private final static int MAX_NUM_CHANNELS = 2; 60.105 + private IntBuffer ib = BufferUtils.createIntBuffer(1); 60.106 + private final FloatBuffer fb = BufferUtils.createVector3Buffer(2); 60.107 + private final ByteBuffer nativeBuf = BufferUtils.createByteBuffer(BUFFER_SIZE); 60.108 + private final byte[] arrayBuf = new byte[BUFFER_SIZE]; 60.109 + 60.110 + private int[] channels; 60.111 + private AudioNode[] chanSrcs; 60.112 + private int nextChan = 0; 60.113 + private ArrayList<Integer> freeChans = new ArrayList<Integer>(); 60.114 + 60.115 + private Listener listener; 60.116 + private boolean audioDisabled = false; 60.117 + 60.118 + private boolean supportEfx = false; 60.119 + private int auxSends = 0; 60.120 + private int reverbFx = -1; 60.121 + private int reverbFxSlot = -1; 60.122 + 60.123 + // RLM: this is to call the native methods which require the OpenAL device ID. 60.124 + // currently it is obtained through reflection. 60.125 + private long deviceID; 60.126 + 60.127 + // Update audio 20 times per second 60.128 + private static final float UPDATE_RATE = 0.05f; 60.129 + 60.130 + private final Thread audioThread = new Thread(this, "jME3 Audio Thread"); 60.131 + private final AtomicBoolean threadLock = new AtomicBoolean(false); 60.132 + 60.133 + public RecordAudioRenderer(){ 60.134 + } 60.135 + 60.136 + public static native void helloEveryone(); 60.137 + 60.138 + 60.139 + public static native void nstep(long device); 60.140 + public void step(){ 60.141 + nstep(this.deviceID); 60.142 + } 60.143 + 60.144 + 60.145 + 60.146 + public void getMainSamples(ByteBuffer buffer){ 60.147 + ngetMainSamples(this.deviceID, buffer, buffer.position()); 60.148 + } 60.149 + public static native void ngetMainSamples(long device, ByteBuffer buffer, int position); 60.150 + 60.151 + 60.152 + public void getAuxSamples(ByteBuffer buffer){ 60.153 + ngetAuxSamples(this.deviceID, buffer, buffer.position()); 60.154 + } 60.155 + public static native void ngetAuxSamples(long device, ByteBuffer buffer, int position); 60.156 + 60.157 + 60.158 + 60.159 + public void initialize(){ 60.160 + if (!audioThread.isAlive()){ 60.161 + audioThread.setDaemon(true); 60.162 + audioThread.setPriority(Thread.NORM_PRIORITY+1); 60.163 + audioThread.start(); 60.164 + }else{ 60.165 + throw new IllegalStateException("Initialize already called"); 60.166 + } 60.167 + } 60.168 + 60.169 + private void checkDead(){ 60.170 + if (audioThread.getState() == Thread.State.TERMINATED) 60.171 + throw new IllegalStateException("Audio thread is terminated"); 60.172 + } 60.173 + 60.174 + public void run(){ 60.175 + initInThread(); 60.176 + synchronized (threadLock){ 60.177 + threadLock.set(true); 60.178 + threadLock.notifyAll(); 60.179 + } 60.180 + 60.181 + 60.182 + helloEveryone(); 60.183 + System.out.println("AudioRecorder: Trying to call native methods."); 60.184 + System.out.println("our device ID is : " + this.deviceID); 60.185 + 60.186 + 60.187 + 60.188 + 60.189 + long updateRateNanos = (long) (UPDATE_RATE * 1000000000); 60.190 + mainloop: while (true){ 60.191 + long startTime = System.nanoTime(); 60.192 + 60.193 + if (Thread.interrupted()) 60.194 + break; 60.195 + 60.196 + synchronized (threadLock){ 60.197 + updateInThread(UPDATE_RATE); 60.198 + } 60.199 + 60.200 + long endTime = System.nanoTime(); 60.201 + long diffTime = endTime - startTime; 60.202 + 60.203 + if (diffTime < updateRateNanos){ 60.204 + long desiredEndTime = startTime + updateRateNanos; 60.205 + while (System.nanoTime() < desiredEndTime){ 60.206 + try{ 60.207 + Thread.sleep(1); 60.208 + }catch (InterruptedException ex){ 60.209 + break mainloop; 60.210 + } 60.211 + } 60.212 + } 60.213 + } 60.214 + 60.215 + synchronized (threadLock){ 60.216 + cleanupInThread(); 60.217 + } 60.218 + } 60.219 + 60.220 + public void initInThread(){ 60.221 + try{ 60.222 + if (!AL.isCreated()){ 60.223 + AL.create("Aurellem", 44100, 15, false); 60.224 + } 60.225 + }catch (OpenALException ex){ 60.226 + logger.log(Level.SEVERE, "Failed to load audio library", ex); 60.227 + audioDisabled = true; 60.228 + return; 60.229 + }catch (LWJGLException ex){ 60.230 + logger.log(Level.SEVERE, "Failed to load audio library", ex); 60.231 + audioDisabled = true; 60.232 + return; 60.233 + } 60.234 + 60.235 + ALCdevice device = AL.getDevice(); 60.236 + 60.237 + // RLM: use reflection to grab the ID of our device for use later. 60.238 + try { 60.239 + Field deviceIDField; 60.240 + deviceIDField = ALCdevice.class.getDeclaredField("device"); 60.241 + deviceIDField.setAccessible(true); 60.242 + try {deviceID = (Long)deviceIDField.get(device);} 60.243 + catch (IllegalArgumentException e) {e.printStackTrace();} 60.244 + catch (IllegalAccessException e) {e.printStackTrace();} 60.245 + deviceIDField.setAccessible(false);} 60.246 + catch (SecurityException e) {e.printStackTrace();} 60.247 + catch (NoSuchFieldException e) {e.printStackTrace();} 60.248 + 60.249 + 60.250 + 60.251 + String deviceName = ALC10.alcGetString(device, ALC10.ALC_DEVICE_SPECIFIER); 60.252 + 60.253 + logger.log(Level.FINER, "Audio Device: {0}", deviceName); 60.254 + logger.log(Level.FINER, "Audio Vendor: {0}", alGetString(AL_VENDOR)); 60.255 + logger.log(Level.FINER, "Audio Renderer: {0}", alGetString(AL_RENDERER)); 60.256 + logger.log(Level.FINER, "Audio Version: {0}", alGetString(AL_VERSION)); 60.257 + 60.258 + // Find maximum # of sources supported by this implementation 60.259 + // RLM: this may not be wise -- exceeding the number of available channels 60.260 + // can crash some versions of OpenAL 60.261 + ArrayList<Integer> channelList = new ArrayList<Integer>(); 60.262 + for (int i = 0; i < MAX_NUM_CHANNELS; i++){ 60.263 + int chan = alGenSources(); 60.264 + if (alGetError() != 0){ 60.265 + break; 60.266 + }else{ 60.267 + channelList.add(chan); 60.268 + } 60.269 + } 60.270 + 60.271 + channels = new int[channelList.size()]; 60.272 + for (int i = 0; i < channels.length; i++){ 60.273 + channels[i] = channelList.get(i); 60.274 + } 60.275 + 60.276 + ib = BufferUtils.createIntBuffer(channels.length); 60.277 + chanSrcs = new AudioNode[channels.length]; 60.278 + 60.279 + logger.log(Level.INFO, "AudioRenderer supports {0} channels", channels.length); 60.280 + 60.281 + supportEfx = ALC10.alcIsExtensionPresent(device, "ALC_EXT_EFX"); 60.282 + // RLM: disable this for now. 60.283 + supportEfx = false; 60.284 + logger.log(Level.FINER, "Audio EFX support: {0}", supportEfx); 60.285 + 60.286 + if (supportEfx){ 60.287 + ib.position(0).limit(1); 60.288 + ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, ib); 60.289 + int major = ib.get(0); 60.290 + ib.position(0).limit(1); 60.291 + ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, ib); 60.292 + int minor = ib.get(0); 60.293 + logger.log(Level.INFO, "Audio effect extension version: {0}.{1}", new Object[]{major, minor}); 60.294 + 60.295 + ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, ib); 60.296 + auxSends = ib.get(0); 60.297 + logger.log(Level.INFO, "Audio max auxilary sends: {0}", auxSends); 60.298 + 60.299 + // create slot 60.300 + ib.position(0).limit(1); 60.301 + EFX10.alGenAuxiliaryEffectSlots(ib); 60.302 + reverbFxSlot = ib.get(0); 60.303 + 60.304 + // create effect 60.305 + ib.position(0).limit(1); 60.306 + EFX10.alGenEffects(ib); 60.307 + reverbFx = ib.get(0); 60.308 + EFX10.alEffecti(reverbFx, EFX10.AL_EFFECT_TYPE, EFX10.AL_EFFECT_REVERB); 60.309 + 60.310 + // attach reverb effect to effect slot 60.311 +// EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); 60.312 + } 60.313 + } 60.314 + 60.315 + public void cleanupInThread(){ 60.316 + 60.317 + 60.318 + if (audioDisabled){ 60.319 + AL.destroy(); 60.320 + return; 60.321 + } 60.322 + 60.323 + // delete channel-based sources 60.324 + ib.clear(); 60.325 + ib.put(channels); 60.326 + ib.flip(); 60.327 + alDeleteSources(ib); 60.328 + 60.329 + if (supportEfx){ 60.330 + ib.position(0).limit(1); 60.331 + ib.put(0, reverbFx); 60.332 + EFX10.alDeleteEffects(ib); 60.333 + 60.334 + ib.position(0).limit(1); 60.335 + ib.put(0, reverbFxSlot); 60.336 + EFX10.alDeleteAuxiliaryEffectSlots(ib); 60.337 + } 60.338 + 60.339 + // XXX: Delete other buffers/sources 60.340 + AL.destroy(); 60.341 + } 60.342 + 60.343 + public void cleanup(){ 60.344 + // kill audio thread 60.345 + 60.346 + if (audioThread.isAlive()){ 60.347 + audioThread.interrupt(); 60.348 + } 60.349 + 60.350 + Byte[] data1 = new Byte[this.fullWaveData1.size()]; 60.351 + data1 = this.fullWaveData1.toArray(data1); 60.352 + 60.353 + Byte[] data2 = new Byte[this.fullWaveData2.size()]; 60.354 + data2 = this.fullWaveData2.toArray(data2); 60.355 + System.out.println(this.fullWaveData1.size()); 60.356 + System.out.println("Saving WAVE data!"); 60.357 + /*for (int i = 0; i < data1.length;i++){ 60.358 + System.out.print(data1[i]+","); 60.359 + if (i%32 ==0){System.out.println();} 60.360 + } 60.361 + */ 60.362 + 60.363 + 60.364 + StdAudio.save("/home/r/wave-output/data2.wav", data2); 60.365 + StdAudio.save("/home/r/wave-output/data1.wav", data1); 60.366 + } 60.367 + 60.368 + private void updateFilter(Filter f){ 60.369 + int id = f.getId(); 60.370 + if (id == -1){ 60.371 + ib.position(0).limit(1); 60.372 + EFX10.alGenFilters(ib); 60.373 + id = ib.get(0); 60.374 + f.setId(id); 60.375 + } 60.376 + 60.377 + if (f instanceof LowPassFilter){ 60.378 + LowPassFilter lpf = (LowPassFilter) f; 60.379 + EFX10.alFilteri(id, EFX10.AL_FILTER_TYPE, EFX10.AL_FILTER_LOWPASS); 60.380 + EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAIN, lpf.getVolume()); 60.381 + EFX10.alFilterf(id, EFX10.AL_LOWPASS_GAINHF, lpf.getHighFreqVolume()); 60.382 + }else{ 60.383 + throw new UnsupportedOperationException("Filter type unsupported: "+ 60.384 + f.getClass().getName()); 60.385 + } 60.386 + 60.387 + f.clearUpdateNeeded(); 60.388 + } 60.389 + 60.390 + public void updateSourceParam(AudioNode src, AudioParam param){ 60.391 + checkDead(); 60.392 + synchronized (threadLock){ 60.393 + while (!threadLock.get()){ 60.394 + try { 60.395 + threadLock.wait(); 60.396 + } catch (InterruptedException ex) { 60.397 + } 60.398 + } 60.399 + if (audioDisabled) 60.400 + return; 60.401 + 60.402 + // There is a race condition in AudioNode that can 60.403 + // cause this to be called for a node that has been 60.404 + // detached from its channel. For example, setVolume() 60.405 + // called from the render thread may see that that AudioNode 60.406 + // still has a channel value but the audio thread may 60.407 + // clear that channel before setVolume() gets to call 60.408 + // updateSourceParam() (because the audio stopped playing 60.409 + // on its own right as the volume was set). In this case, 60.410 + // it should be safe to just ignore the update 60.411 + if (src.getChannel() < 0) 60.412 + return; 60.413 + 60.414 + assert src.getChannel() >= 0; 60.415 + 60.416 + int id = channels[src.getChannel()]; 60.417 + switch (param){ 60.418 + case Position: 60.419 + if (!src.isPositional()) 60.420 + return; 60.421 + 60.422 + Vector3f pos = src.getWorldTranslation(); 60.423 + alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); 60.424 + break; 60.425 + case Velocity: 60.426 + if (!src.isPositional()) 60.427 + return; 60.428 + 60.429 + Vector3f vel = src.getVelocity(); 60.430 + alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); 60.431 + break; 60.432 + case MaxDistance: 60.433 + if (!src.isPositional()) 60.434 + return; 60.435 + 60.436 + alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); 60.437 + break; 60.438 + case RefDistance: 60.439 + if (!src.isPositional()) 60.440 + return; 60.441 + 60.442 + alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); 60.443 + break; 60.444 + case ReverbFilter: 60.445 + if (!src.isPositional() || !src.isReverbEnabled()) 60.446 + return; 60.447 + 60.448 + int filter = EFX10.AL_FILTER_NULL; 60.449 + if (src.getReverbFilter() != null){ 60.450 + Filter f = src.getReverbFilter(); 60.451 + if (f.isUpdateNeeded()){ 60.452 + updateFilter(f); 60.453 + } 60.454 + filter = f.getId(); 60.455 + } 60.456 + AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); 60.457 + break; 60.458 + case ReverbEnabled: 60.459 + if (!src.isPositional()) 60.460 + return; 60.461 + 60.462 + if (src.isReverbEnabled()){ 60.463 + updateSourceParam(src, AudioParam.ReverbFilter); 60.464 + }else{ 60.465 + AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); 60.466 + } 60.467 + break; 60.468 + case IsPositional: 60.469 + if (!src.isPositional()){ 60.470 + // play in headspace 60.471 + alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); 60.472 + alSource3f(id, AL_POSITION, 0,0,0); 60.473 + alSource3f(id, AL_VELOCITY, 0,0,0); 60.474 + }else{ 60.475 + alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); 60.476 + updateSourceParam(src, AudioParam.Position); 60.477 + updateSourceParam(src, AudioParam.Velocity); 60.478 + updateSourceParam(src, AudioParam.MaxDistance); 60.479 + updateSourceParam(src, AudioParam.RefDistance); 60.480 + updateSourceParam(src, AudioParam.ReverbEnabled); 60.481 + } 60.482 + break; 60.483 + case Direction: 60.484 + if (!src.isDirectional()) 60.485 + return; 60.486 + 60.487 + Vector3f dir = src.getDirection(); 60.488 + alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); 60.489 + break; 60.490 + case InnerAngle: 60.491 + if (!src.isDirectional()) 60.492 + return; 60.493 + 60.494 + alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); 60.495 + break; 60.496 + case OuterAngle: 60.497 + if (!src.isDirectional()) 60.498 + return; 60.499 + 60.500 + alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); 60.501 + break; 60.502 + case IsDirectional: 60.503 + if (src.isDirectional()){ 60.504 + updateSourceParam(src, AudioParam.Direction); 60.505 + updateSourceParam(src, AudioParam.InnerAngle); 60.506 + updateSourceParam(src, AudioParam.OuterAngle); 60.507 + alSourcef(id, AL_CONE_OUTER_GAIN, 0); 60.508 + }else{ 60.509 + alSourcef(id, AL_CONE_INNER_ANGLE, 360); 60.510 + alSourcef(id, AL_CONE_OUTER_ANGLE, 360); 60.511 + alSourcef(id, AL_CONE_OUTER_GAIN, 1f); 60.512 + } 60.513 + break; 60.514 + case DryFilter: 60.515 + if (src.getDryFilter() != null){ 60.516 + Filter f = src.getDryFilter(); 60.517 + if (f.isUpdateNeeded()){ 60.518 + updateFilter(f); 60.519 + 60.520 + // NOTE: must re-attach filter for changes to apply. 60.521 + alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); 60.522 + } 60.523 + }else{ 60.524 + alSourcei(id, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); 60.525 + } 60.526 + break; 60.527 + case Looping: 60.528 + if (src.isLooping()){ 60.529 + if (!(src.getAudioData() instanceof AudioStream)){ 60.530 + alSourcei(id, AL_LOOPING, AL_TRUE); 60.531 + } 60.532 + }else{ 60.533 + alSourcei(id, AL_LOOPING, AL_FALSE); 60.534 + } 60.535 + break; 60.536 + case Volume: 60.537 + alSourcef(id, AL_GAIN, src.getVolume()); 60.538 + break; 60.539 + case Pitch: 60.540 + alSourcef(id, AL_PITCH, src.getPitch()); 60.541 + break; 60.542 + } 60.543 + } 60.544 + } 60.545 + 60.546 + private void setSourceParams(int id, AudioNode src, boolean forceNonLoop){ 60.547 + if (src.isPositional()){ 60.548 + Vector3f pos = src.getWorldTranslation(); 60.549 + Vector3f vel = src.getVelocity(); 60.550 + alSource3f(id, AL_POSITION, pos.x, pos.y, pos.z); 60.551 + alSource3f(id, AL_VELOCITY, vel.x, vel.y, vel.z); 60.552 + alSourcef(id, AL_MAX_DISTANCE, src.getMaxDistance()); 60.553 + alSourcef(id, AL_REFERENCE_DISTANCE, src.getRefDistance()); 60.554 + alSourcei(id, AL_SOURCE_RELATIVE, AL_FALSE); 60.555 + 60.556 + if (src.isReverbEnabled()){ 60.557 + int filter = EFX10.AL_FILTER_NULL; 60.558 + if (src.getReverbFilter() != null){ 60.559 + Filter f = src.getReverbFilter(); 60.560 + if (f.isUpdateNeeded()){ 60.561 + updateFilter(f); 60.562 + } 60.563 + filter = f.getId(); 60.564 + } 60.565 + AL11.alSource3i(id, EFX10.AL_AUXILIARY_SEND_FILTER, reverbFxSlot, 0, filter); 60.566 + } 60.567 + }else{ 60.568 + // play in headspace 60.569 + alSourcei(id, AL_SOURCE_RELATIVE, AL_TRUE); 60.570 + alSource3f(id, AL_POSITION, 0,0,0); 60.571 + alSource3f(id, AL_VELOCITY, 0,0,0); 60.572 + } 60.573 + 60.574 + if (src.getDryFilter() != null){ 60.575 + Filter f = src.getDryFilter(); 60.576 + if (f.isUpdateNeeded()){ 60.577 + updateFilter(f); 60.578 + 60.579 + // NOTE: must re-attach filter for changes to apply. 60.580 + alSourcei(id, EFX10.AL_DIRECT_FILTER, f.getId()); 60.581 + } 60.582 + } 60.583 + 60.584 + if (forceNonLoop){ 60.585 + alSourcei(id, AL_LOOPING, AL_FALSE); 60.586 + }else{ 60.587 + alSourcei(id, AL_LOOPING, src.isLooping() ? AL_TRUE : AL_FALSE); 60.588 + } 60.589 + alSourcef(id, AL_GAIN, src.getVolume()); 60.590 + alSourcef(id, AL_PITCH, src.getPitch()); 60.591 + alSourcef(id, AL11.AL_SEC_OFFSET, src.getTimeOffset()); 60.592 + 60.593 + if (src.isDirectional()){ 60.594 + Vector3f dir = src.getDirection(); 60.595 + alSource3f(id, AL_DIRECTION, dir.x, dir.y, dir.z); 60.596 + alSourcef(id, AL_CONE_INNER_ANGLE, src.getInnerAngle()); 60.597 + alSourcef(id, AL_CONE_OUTER_ANGLE, src.getOuterAngle()); 60.598 + alSourcef(id, AL_CONE_OUTER_GAIN, 0); 60.599 + }else{ 60.600 + alSourcef(id, AL_CONE_INNER_ANGLE, 360); 60.601 + alSourcef(id, AL_CONE_OUTER_ANGLE, 360); 60.602 + alSourcef(id, AL_CONE_OUTER_GAIN, 1f); 60.603 + } 60.604 + } 60.605 + 60.606 + public void updateListenerParam(Listener listener, ListenerParam param){ 60.607 + checkDead(); 60.608 + synchronized (threadLock){ 60.609 + while (!threadLock.get()){ 60.610 + try { 60.611 + threadLock.wait(); 60.612 + } catch (InterruptedException ex) { 60.613 + } 60.614 + } 60.615 + if (audioDisabled) 60.616 + return; 60.617 + 60.618 + switch (param){ 60.619 + case Position: 60.620 + Vector3f pos = listener.getLocation(); 60.621 + alListener3f(AL_POSITION, pos.x, pos.y, pos.z); 60.622 + break; 60.623 + case Rotation: 60.624 + Vector3f dir = listener.getDirection(); 60.625 + Vector3f up = listener.getUp(); 60.626 + fb.rewind(); 60.627 + fb.put(dir.x).put(dir.y).put(dir.z); 60.628 + fb.put(up.x).put(up.y).put(up.z); 60.629 + fb.flip(); 60.630 + alListener(AL_ORIENTATION, fb); 60.631 + break; 60.632 + case Velocity: 60.633 + Vector3f vel = listener.getVelocity(); 60.634 + alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); 60.635 + break; 60.636 + case Volume: 60.637 + alListenerf(AL_GAIN, listener.getVolume()); 60.638 + break; 60.639 + } 60.640 + } 60.641 + } 60.642 + 60.643 + private void setListenerParams(Listener listener){ 60.644 + Vector3f pos = listener.getLocation(); 60.645 + Vector3f vel = listener.getVelocity(); 60.646 + Vector3f dir = listener.getDirection(); 60.647 + Vector3f up = listener.getUp(); 60.648 + 60.649 + alListener3f(AL_POSITION, pos.x, pos.y, pos.z); 60.650 + alListener3f(AL_VELOCITY, vel.x, vel.y, vel.z); 60.651 + fb.rewind(); 60.652 + fb.put(dir.x).put(dir.y).put(dir.z); 60.653 + fb.put(up.x).put(up.y).put(up.z); 60.654 + fb.flip(); 60.655 + alListener(AL_ORIENTATION, fb); 60.656 + alListenerf(AL_GAIN, listener.getVolume()); 60.657 + } 60.658 + 60.659 + private int newChannel(){ 60.660 + if (freeChans.size() > 0) 60.661 + return freeChans.remove(0); 60.662 + else if (nextChan < channels.length){ 60.663 + return nextChan++; 60.664 + }else{ 60.665 + return -1; 60.666 + } 60.667 + } 60.668 + 60.669 + private void freeChannel(int index){ 60.670 + if (index == nextChan-1){ 60.671 + nextChan--; 60.672 + } else{ 60.673 + freeChans.add(index); 60.674 + } 60.675 + } 60.676 + 60.677 + public void setEnvironment(Environment env){ 60.678 + checkDead(); 60.679 + synchronized (threadLock){ 60.680 + while (!threadLock.get()){ 60.681 + try { 60.682 + threadLock.wait(); 60.683 + } catch (InterruptedException ex) { 60.684 + } 60.685 + } 60.686 + if (audioDisabled) 60.687 + return; 60.688 + 60.689 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DENSITY, env.getDensity()); 60.690 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DIFFUSION, env.getDiffusion()); 60.691 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAIN, env.getGain()); 60.692 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_GAINHF, env.getGainHf()); 60.693 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_TIME, env.getDecayTime()); 60.694 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_DECAY_HFRATIO, env.getDecayHFRatio()); 60.695 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_GAIN, env.getReflectGain()); 60.696 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_REFLECTIONS_DELAY, env.getReflectDelay()); 60.697 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_GAIN, env.getLateReverbGain()); 60.698 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_LATE_REVERB_DELAY, env.getLateReverbDelay()); 60.699 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_AIR_ABSORPTION_GAINHF, env.getAirAbsorbGainHf()); 60.700 + EFX10.alEffectf(reverbFx, EFX10.AL_REVERB_ROOM_ROLLOFF_FACTOR, env.getRoomRolloffFactor()); 60.701 + 60.702 + // attach effect to slot 60.703 + EFX10.alAuxiliaryEffectSloti(reverbFxSlot, EFX10.AL_EFFECTSLOT_EFFECT, reverbFx); 60.704 + } 60.705 + } 60.706 + 60.707 + private boolean fillBuffer(AudioStream stream, int id){ 60.708 + int size = 0; 60.709 + int result; 60.710 + 60.711 + while (size < arrayBuf.length){ 60.712 + result = stream.readSamples(arrayBuf, size, arrayBuf.length - size); 60.713 + 60.714 + if(result > 0){ 60.715 + size += result; 60.716 + }else{ 60.717 + break; 60.718 + } 60.719 + } 60.720 + 60.721 + if(size == 0) 60.722 + return false; 60.723 + 60.724 + nativeBuf.clear(); 60.725 + nativeBuf.put(arrayBuf, 0, size); 60.726 + nativeBuf.flip(); 60.727 + 60.728 + alBufferData(id, convertFormat(stream), nativeBuf, stream.getSampleRate()); 60.729 + 60.730 + return true; 60.731 + } 60.732 + 60.733 + private boolean fillStreamingSource(int sourceId, AudioStream stream){ 60.734 + if (!stream.isOpen()) 60.735 + return false; 60.736 + 60.737 + boolean active = true; 60.738 + int processed = alGetSourcei(sourceId, AL_BUFFERS_PROCESSED); 60.739 + 60.740 +// while((processed--) != 0){ 60.741 + if (processed > 0){ 60.742 + int buffer; 60.743 + 60.744 + ib.position(0).limit(1); 60.745 + alSourceUnqueueBuffers(sourceId, ib); 60.746 + buffer = ib.get(0); 60.747 + 60.748 + active = fillBuffer(stream, buffer); 60.749 + 60.750 + ib.position(0).limit(1); 60.751 + ib.put(0, buffer); 60.752 + alSourceQueueBuffers(sourceId, ib); 60.753 + } 60.754 + 60.755 + if (!active && stream.isOpen()) 60.756 + stream.close(); 60.757 + 60.758 + return active; 60.759 + } 60.760 + 60.761 + private boolean attachStreamToSource(int sourceId, AudioStream stream){ 60.762 + boolean active = true; 60.763 + for (int id : stream.getIds()){ 60.764 + active = fillBuffer(stream, id); 60.765 + ib.position(0).limit(1); 60.766 + ib.put(id).flip(); 60.767 + alSourceQueueBuffers(sourceId, ib); 60.768 + } 60.769 + return active; 60.770 + } 60.771 + 60.772 + private boolean attachBufferToSource(int sourceId, AudioBuffer buffer){ 60.773 + alSourcei(sourceId, AL_BUFFER, buffer.getId()); 60.774 + return true; 60.775 + } 60.776 + 60.777 + private boolean attachAudioToSource(int sourceId, AudioData data){ 60.778 + if (data instanceof AudioBuffer){ 60.779 + return attachBufferToSource(sourceId, (AudioBuffer) data); 60.780 + }else if (data instanceof AudioStream){ 60.781 + return attachStreamToSource(sourceId, (AudioStream) data); 60.782 + } 60.783 + throw new UnsupportedOperationException(); 60.784 + } 60.785 + 60.786 + private void clearChannel(int index){ 60.787 + // make room at this channel 60.788 + if (chanSrcs[index] != null){ 60.789 + AudioNode src = chanSrcs[index]; 60.790 + 60.791 + int sourceId = channels[index]; 60.792 + alSourceStop(sourceId); 60.793 + 60.794 + if (src.getAudioData() instanceof AudioStream){ 60.795 + AudioStream str = (AudioStream) src.getAudioData(); 60.796 + ib.position(0).limit(STREAMING_BUFFER_COUNT); 60.797 + ib.put(str.getIds()).flip(); 60.798 + alSourceUnqueueBuffers(sourceId, ib); 60.799 + }else if (src.getAudioData() instanceof AudioBuffer){ 60.800 + alSourcei(sourceId, AL_BUFFER, 0); 60.801 + } 60.802 + 60.803 + if (src.getDryFilter() != null){ 60.804 + // detach filter 60.805 + alSourcei(sourceId, EFX10.AL_DIRECT_FILTER, EFX10.AL_FILTER_NULL); 60.806 + } 60.807 + if (src.isPositional()){ 60.808 + AudioNode pas = (AudioNode) src; 60.809 + if (pas.isReverbEnabled()) { 60.810 + AL11.alSource3i(sourceId, EFX10.AL_AUXILIARY_SEND_FILTER, 0, 0, EFX10.AL_FILTER_NULL); 60.811 + } 60.812 + } 60.813 + 60.814 + chanSrcs[index] = null; 60.815 + } 60.816 + } 60.817 + 60.818 + public void update(float tpf){ 60.819 + //ByteBuffer test = BufferUtils.createByteBuffer(1); 60.820 + //AurellemTransport.getAuxSamples(AL.getDevice(), test); 60.821 + } 60.822 + 60.823 + Vector<Byte> fullWaveData1 = new Vector<Byte>(); 60.824 + Vector<Byte> fullWaveData2 = new Vector<Byte>(); 60.825 + 60.826 + public void updateInThread(float tpf){ 60.827 + if (audioDisabled) 60.828 + return; 60.829 + 60.830 + step(); 60.831 + ByteBuffer test = BufferUtils.createByteBuffer(4096); 60.832 + test.clear(); 60.833 + this.getMainSamples(test); 60.834 + byte[] waveData = new byte[4096]; 60.835 + test.get(waveData, 0, 4096); 60.836 + //System.out.println("J DATA:"); 60.837 + /*for (int j = 0; j < 1; j++){ 60.838 + for(int i = 64 * j; i < (64*j) + 64; i++){ 60.839 + System.out.print(waveData[i]); 60.840 + } 60.841 + System.out.println(); 60.842 + }*/ 60.843 + 60.844 + ByteBuffer test2 = BufferUtils.createByteBuffer(4096); 60.845 + test2.clear(); 60.846 + this.getAuxSamples(test2); 60.847 + byte[] waveData2 = new byte[4096]; 60.848 + test2.get(waveData2, 0, 4096); 60.849 + //System.out.print("wave1:"); 60.850 + //for (int j = 0; j< 32; j++){ 60.851 + // System.out.print(waveData[j]+","); 60.852 + // } 60.853 + //System.out.println(); 60.854 + //System.out.print("wave2:"); 60.855 + // for (int j = 0; j< 4096; j++){ 60.856 + // if (waveData2[j] != 0){ 60.857 + // System.out.println("fucked at : " + j); 60.858 + // } 60.859 + 60.860 + /* System.out.print(waveData2[j]+","); 60.861 + if (0 == (j % 64)){System.out.println();}*/ 60.862 + //} 60.863 + //System.out.println(); 60.864 + 60.865 + for (byte b : waveData){ 60.866 + this.fullWaveData1.add(b); 60.867 + } 60.868 + 60.869 + for (byte b : waveData2){ 60.870 + this.fullWaveData2.add(b); 60.871 + } 60.872 + 60.873 + 60.874 + for (int i = 0; i < channels.length; i++){ 60.875 + AudioNode src = chanSrcs[i]; 60.876 + if (src == null) 60.877 + continue; 60.878 + 60.879 + int sourceId = channels[i]; 60.880 + 60.881 + // is the source bound to this channel 60.882 + // if false, it's an instanced playback 60.883 + boolean boundSource = i == src.getChannel(); 60.884 + 60.885 + // source's data is streaming 60.886 + boolean streaming = src.getAudioData() instanceof AudioStream; 60.887 + 60.888 + // only buffered sources can be bound 60.889 + assert (boundSource && streaming) || (!streaming); 60.890 + 60.891 + int state = alGetSourcei(sourceId, AL_SOURCE_STATE); 60.892 + boolean wantPlaying = src.getStatus() == Status.Playing; 60.893 + boolean stopped = state == AL_STOPPED; 60.894 + 60.895 + if (streaming && wantPlaying){ 60.896 + AudioStream stream = (AudioStream) src.getAudioData(); 60.897 + if (stream.isOpen()){ 60.898 + fillStreamingSource(sourceId, stream); 60.899 + if (stopped) 60.900 + alSourcePlay(sourceId); 60.901 + 60.902 + }else{ 60.903 + if (stopped){ 60.904 + // became inactive 60.905 + src.setStatus(Status.Stopped); 60.906 + src.setChannel(-1); 60.907 + clearChannel(i); 60.908 + freeChannel(i); 60.909 + 60.910 + // And free the audio since it cannot be 60.911 + // played again anyway. 60.912 + deleteAudioData(stream); 60.913 + } 60.914 + } 60.915 + }else if (!streaming){ 60.916 + boolean paused = state == AL_PAUSED; 60.917 + 60.918 + // make sure OAL pause state & source state coincide 60.919 + assert (src.getStatus() == Status.Paused && paused) || (!paused); 60.920 + 60.921 + if (stopped){ 60.922 + if (boundSource){ 60.923 + src.setStatus(Status.Stopped); 60.924 + src.setChannel(-1); 60.925 + } 60.926 + clearChannel(i); 60.927 + freeChannel(i); 60.928 + } 60.929 + } 60.930 + } 60.931 + } 60.932 + 60.933 + public void setListener(Listener listener) { 60.934 + checkDead(); 60.935 + synchronized (threadLock){ 60.936 + while (!threadLock.get()){ 60.937 + try { 60.938 + threadLock.wait(); 60.939 + } catch (InterruptedException ex) { 60.940 + } 60.941 + } 60.942 + if (audioDisabled) 60.943 + return; 60.944 + 60.945 + if (this.listener != null){ 60.946 + // previous listener no longer associated with current 60.947 + // renderer 60.948 + this.listener.setRenderer(null); 60.949 + } 60.950 + 60.951 + this.listener = listener; 60.952 + this.listener.setRenderer(this); 60.953 + setListenerParams(listener); 60.954 + } 60.955 + } 60.956 + 60.957 + public void playSourceInstance(AudioNode src){ 60.958 + checkDead(); 60.959 + synchronized (threadLock){ 60.960 + while (!threadLock.get()){ 60.961 + try { 60.962 + threadLock.wait(); 60.963 + } catch (InterruptedException ex) { 60.964 + } 60.965 + } 60.966 + if (audioDisabled) 60.967 + return; 60.968 + 60.969 + if (src.getAudioData() instanceof AudioStream) 60.970 + throw new UnsupportedOperationException( 60.971 + "Cannot play instances " + 60.972 + "of audio streams. Use playSource() instead."); 60.973 + 60.974 + if (src.getAudioData().isUpdateNeeded()){ 60.975 + updateAudioData(src.getAudioData()); 60.976 + } 60.977 + 60.978 + // create a new index for an audio-channel 60.979 + int index = newChannel(); 60.980 + if (index == -1) 60.981 + return; 60.982 + 60.983 + int sourceId = channels[index]; 60.984 + 60.985 + clearChannel(index); 60.986 + 60.987 + // set parameters, like position and max distance 60.988 + setSourceParams(sourceId, src, true); 60.989 + attachAudioToSource(sourceId, src.getAudioData()); 60.990 + chanSrcs[index] = src; 60.991 + 60.992 + // play the channel 60.993 + alSourcePlay(sourceId); 60.994 + } 60.995 + } 60.996 + 60.997 + 60.998 + public void playSource(AudioNode src) { 60.999 + checkDead(); 60.1000 + synchronized (threadLock){ 60.1001 + while (!threadLock.get()){ 60.1002 + try { 60.1003 + threadLock.wait(); 60.1004 + } catch (InterruptedException ex) { 60.1005 + } 60.1006 + } 60.1007 + if (audioDisabled) 60.1008 + return; 60.1009 + 60.1010 + //assert src.getStatus() == Status.Stopped || src.getChannel() == -1; 60.1011 + 60.1012 + if (src.getStatus() == Status.Playing){ 60.1013 + return; 60.1014 + }else if (src.getStatus() == Status.Stopped){ 60.1015 + 60.1016 + // allocate channel to this source 60.1017 + int index = newChannel(); 60.1018 + if (index == -1) { 60.1019 + logger.log(Level.WARNING, "No channel available to play {0}", src); 60.1020 + return; 60.1021 + } 60.1022 + clearChannel(index); 60.1023 + src.setChannel(index); 60.1024 + 60.1025 + AudioData data = src.getAudioData(); 60.1026 + if (data.isUpdateNeeded()) 60.1027 + updateAudioData(data); 60.1028 + 60.1029 + chanSrcs[index] = src; 60.1030 + setSourceParams(channels[index], src, false); 60.1031 + attachAudioToSource(channels[index], data); 60.1032 + } 60.1033 + 60.1034 + alSourcePlay(channels[src.getChannel()]); 60.1035 + src.setStatus(Status.Playing); 60.1036 + } 60.1037 + } 60.1038 + 60.1039 + 60.1040 + public void pauseSource(AudioNode src) { 60.1041 + checkDead(); 60.1042 + synchronized (threadLock){ 60.1043 + while (!threadLock.get()){ 60.1044 + try { 60.1045 + threadLock.wait(); 60.1046 + } catch (InterruptedException ex) { 60.1047 + } 60.1048 + } 60.1049 + if (audioDisabled) 60.1050 + return; 60.1051 + 60.1052 + if (src.getStatus() == Status.Playing){ 60.1053 + assert src.getChannel() != -1; 60.1054 + 60.1055 + alSourcePause(channels[src.getChannel()]); 60.1056 + src.setStatus(Status.Paused); 60.1057 + } 60.1058 + } 60.1059 + } 60.1060 + 60.1061 + 60.1062 + public void stopSource(AudioNode src) { 60.1063 + synchronized (threadLock){ 60.1064 + while (!threadLock.get()){ 60.1065 + try { 60.1066 + threadLock.wait(); 60.1067 + } catch (InterruptedException ex) { 60.1068 + } 60.1069 + } 60.1070 + if (audioDisabled) 60.1071 + return; 60.1072 + 60.1073 + if (src.getStatus() != Status.Stopped){ 60.1074 + int chan = src.getChannel(); 60.1075 + assert chan != -1; // if it's not stopped, must have id 60.1076 + 60.1077 + src.setStatus(Status.Stopped); 60.1078 + src.setChannel(-1); 60.1079 + clearChannel(chan); 60.1080 + freeChannel(chan); 60.1081 + 60.1082 + if (src.getAudioData() instanceof AudioStream) { 60.1083 + 60.1084 + AudioStream stream = (AudioStream)src.getAudioData(); 60.1085 + if (stream.isOpen()) { 60.1086 + stream.close(); 60.1087 + } 60.1088 + 60.1089 + // And free the audio since it cannot be 60.1090 + // played again anyway. 60.1091 + deleteAudioData(src.getAudioData()); 60.1092 + } 60.1093 + } 60.1094 + } 60.1095 + } 60.1096 + 60.1097 + private int convertFormat(AudioData ad){ 60.1098 + switch (ad.getBitsPerSample()){ 60.1099 + case 8: 60.1100 + if (ad.getChannels() == 1) 60.1101 + return AL_FORMAT_MONO8; 60.1102 + else if (ad.getChannels() == 2) 60.1103 + return AL_FORMAT_STEREO8; 60.1104 + 60.1105 + break; 60.1106 + case 16: 60.1107 + if (ad.getChannels() == 1) 60.1108 + return AL_FORMAT_MONO16; 60.1109 + else 60.1110 + return AL_FORMAT_STEREO16; 60.1111 + } 60.1112 + throw new UnsupportedOperationException("Unsupported channels/bits combination: "+ 60.1113 + "bits="+ad.getBitsPerSample()+", channels="+ad.getChannels()); 60.1114 + } 60.1115 + 60.1116 + private void updateAudioBuffer(AudioBuffer ab){ 60.1117 + int id = ab.getId(); 60.1118 + if (ab.getId() == -1){ 60.1119 + ib.position(0).limit(1); 60.1120 + alGenBuffers(ib); 60.1121 + id = ib.get(0); 60.1122 + ab.setId(id); 60.1123 + } 60.1124 + 60.1125 + ab.getData().clear(); 60.1126 + alBufferData(id, convertFormat(ab), ab.getData(), ab.getSampleRate()); 60.1127 + ab.clearUpdateNeeded(); 60.1128 + } 60.1129 + 60.1130 + private void updateAudioStream(AudioStream as){ 60.1131 + if (as.getIds() != null){ 60.1132 + deleteAudioData(as); 60.1133 + } 60.1134 + 60.1135 + int[] ids = new int[STREAMING_BUFFER_COUNT]; 60.1136 + ib.position(0).limit(STREAMING_BUFFER_COUNT); 60.1137 + alGenBuffers(ib); 60.1138 + ib.position(0).limit(STREAMING_BUFFER_COUNT); 60.1139 + ib.get(ids); 60.1140 + 60.1141 + as.setIds(ids); 60.1142 + as.clearUpdateNeeded(); 60.1143 + } 60.1144 + 60.1145 + private void updateAudioData(AudioData ad){ 60.1146 + if (ad instanceof AudioBuffer){ 60.1147 + updateAudioBuffer((AudioBuffer) ad); 60.1148 + }else if (ad instanceof AudioStream){ 60.1149 + updateAudioStream((AudioStream) ad); 60.1150 + } 60.1151 + } 60.1152 + 60.1153 + public void deleteAudioData(AudioData ad){ 60.1154 + synchronized (threadLock){ 60.1155 + while (!threadLock.get()){ 60.1156 + try { 60.1157 + threadLock.wait(); 60.1158 + } catch (InterruptedException ex) { 60.1159 + } 60.1160 + } 60.1161 + if (audioDisabled) 60.1162 + return; 60.1163 + 60.1164 + if (ad instanceof AudioBuffer){ 60.1165 + AudioBuffer ab = (AudioBuffer) ad; 60.1166 + int id = ab.getId(); 60.1167 + if (id != -1){ 60.1168 + ib.put(0,id); 60.1169 + ib.position(0).limit(1); 60.1170 + alDeleteBuffers(ib); 60.1171 + ab.resetObject(); 60.1172 + } 60.1173 + }else if (ad instanceof AudioStream){ 60.1174 + AudioStream as = (AudioStream) ad; 60.1175 + int[] ids = as.getIds(); 60.1176 + if (ids != null){ 60.1177 + ib.clear(); 60.1178 + ib.put(ids).flip(); 60.1179 + alDeleteBuffers(ib); 60.1180 + as.resetObject(); 60.1181 + } 60.1182 + } 60.1183 + } 60.1184 + } 60.1185 + 60.1186 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 61.2 +++ b/XCompile.txt Tue Oct 25 13:02:31 2011 -0700 61.3 @@ -0,0 +1,30 @@ 61.4 +# Cross-compiling requires CMake 2.6 or newer. To use it from build/, call it 61.5 +# like this: 61.6 +# cmake .. -DCMAKE_TOOLCHAIN_FILE=../XCompile.txt -DHOST=i686-pc-mingw32 61.7 +# Where 'i686-pc-mingw32' is the host prefix for your cross-compiler. If you 61.8 +# already have a toolchain file setup, you may use that instead of this file. 61.9 + 61.10 +# the name of the target operating system 61.11 +SET(CMAKE_SYSTEM_NAME Windows) 61.12 + 61.13 +# which compilers to use for C and C++ 61.14 +SET(CMAKE_C_COMPILER "${HOST}-gcc") 61.15 +SET(CMAKE_CXX_COMPILER "${HOST}-g++") 61.16 + 61.17 +# here is the target environment located 61.18 +SET(CMAKE_FIND_ROOT_PATH "/usr/${HOST}") 61.19 + 61.20 +# here is where stuff gets installed to 61.21 +SET(CMAKE_INSTALL_PREFIX "${CMAKE_FIND_ROOT_PATH}/usr" CACHE STRING "Install path prefix, prepended onto install directories." FORCE) 61.22 + 61.23 +# adjust the default behaviour of the FIND_XXX() commands: 61.24 +# search headers and libraries in the target environment, search 61.25 +# programs in the host environment 61.26 +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) 61.27 +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) 61.28 +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) 61.29 + 61.30 +# set env vars so that pkg-config will look in the appropriate directory for 61.31 +# .pc files (as there seems to be no way to force using ${HOST}-pkg-config) 61.32 +set(ENV{PKG_CONFIG_LIBDIR} "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig") 61.33 +set(ENV{PKG_CONFIG_PATH} "")
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 62.2 +++ b/alsoftrc.sample Tue Oct 25 13:02:31 2011 -0700 62.3 @@ -0,0 +1,277 @@ 62.4 +# OpenAL config file. Options that are not under a block or are under the 62.5 +# [general] block are for general, non-backend-specific options. Blocks may 62.6 +# appear multiple times, and duplicated options will take the last value 62.7 +# specified. 62.8 +# The system-wide settings can be put in /etc/openal/alsoft.conf and user- 62.9 +# specific override settings in ~/.alsoftrc. 62.10 +# For Windows, these settings should go into %AppData%\alsoft.ini 62.11 +# The environment variable ALSOFT_CONF can be used to specify another config 62.12 +# override 62.13 + 62.14 +# Option and block names are case-insenstive. The supplied values are only 62.15 +# hints and may not be honored (though generally it'll try to get as close as 62.16 +# possible). Note: options that are left unset may default to app- or system- 62.17 +# specified values. These are the current available settings: 62.18 + 62.19 +## format: 62.20 +# Sets the output format. Can be one of: 62.21 +# AL_FORMAT_MONO8 (8-bit mono) 62.22 +# AL_FORMAT_STEREO8 (8-bit stereo) 62.23 +# AL_FORMAT_QUAD8 (8-bit 4-channel) 62.24 +# AL_FORMAT_51CHN8 (8-bit 5.1 output) 62.25 +# AL_FORMAT_61CHN8 (8-bit 6.1 output) 62.26 +# AL_FORMAT_71CHN8 (8-bit 7.1 output) 62.27 +# AL_FORMAT_MONO16 (16-bit mono) 62.28 +# AL_FORMAT_STEREO16 (16-bit stereo) 62.29 +# AL_FORMAT_QUAD16 (16-bit 4-channel) 62.30 +# AL_FORMAT_51CHN16 (16-bit 5.1 output) 62.31 +# AL_FORMAT_61CHN16 (16-bit 6.1 output) 62.32 +# AL_FORMAT_71CHN16 (16-bit 7.1 output) 62.33 +# AL_FORMAT_MONO32 (32-bit float mono) 62.34 +# AL_FORMAT_STEREO32 (32-bit float stereo) 62.35 +# AL_FORMAT_QUAD32 (32-bit float 4-channel) 62.36 +# AL_FORMAT_51CHN32 (32-bit float 5.1 output) 62.37 +# AL_FORMAT_61CHN32 (32-bit float 6.1 output) 62.38 +# AL_FORMAT_71CHN32 (32-bit float 7.1 output) 62.39 +#format = AL_FORMAT_STEREO16 62.40 + 62.41 +## hrtf: 62.42 +# Enables HRTF filters. These filters provide for better sound spatialization 62.43 +# while using headphones. The filters will only work when output is 44100hz 62.44 +# stereo. While HRTF is active, the cf_level option is disabled. Default is 62.45 +# disabled since stereo speaker output quality may suffer. 62.46 +#hrtf = false 62.47 + 62.48 +## cf_level: 62.49 +# Sets the crossfeed level for stereo output. Valid values are: 62.50 +# 0 - No crossfeed 62.51 +# 1 - Low crossfeed 62.52 +# 2 - Middle crossfeed 62.53 +# 3 - High crossfeed (virtual speakers are closer to itself) 62.54 +# 4 - Low easy crossfeed 62.55 +# 5 - Middle easy crossfeed 62.56 +# 6 - High easy crossfeed 62.57 +# Users of headphones may want to try various settings. Has no effect on non- 62.58 +# stereo modes. 62.59 +#cf_level = 0 62.60 + 62.61 +## frequency: 62.62 +# Sets the output frequency. 62.63 +#frequency = 44100 62.64 + 62.65 +## resampler: 62.66 +# Selects the resampler used when mixing sources. Valid values are: 62.67 +# 0 - None (nearest sample, no interpolation) 62.68 +# 1 - Linear (extrapolates samples using a linear slope between samples) 62.69 +# 2 - Cubic (extrapolates samples using a Catmull-Rom spline) 62.70 +# Specifying other values will result in using the default (linear). 62.71 +#resampler = 1 62.72 + 62.73 +## rt-prio: 62.74 +# Sets real-time priority for the mixing thread. Not all drivers may use this 62.75 +# (eg. PortAudio) as they already control the priority of the mixing thread. 62.76 +# 0 and negative values will disable it. Note that this may constitute a 62.77 +# security risk since a real-time priority thread can indefinitely block 62.78 +# normal-priority threads if it fails to wait. As such, the default is 62.79 +# disabled. 62.80 +#rt-prio = 0 62.81 + 62.82 +## period_size: 62.83 +# Sets the update period size, in frames. This is the number of frames needed 62.84 +# for each mixing update. 62.85 +#period_size = 1024 62.86 + 62.87 +## periods: 62.88 +# Sets the number of update periods. Higher values create a larger mix ahead, 62.89 +# which helps protect against skips when the CPU is under load, but increases 62.90 +# the delay between a sound getting mixed and being heard. 62.91 +#periods = 4 62.92 + 62.93 +## sources: 62.94 +# Sets the maximum number of allocatable sources. Lower values may help for 62.95 +# systems with apps that try to play more sounds than the CPU can handle. 62.96 +#sources = 256 62.97 + 62.98 +## stereodup: 62.99 +# Sets whether to duplicate stereo sounds behind the listener for 4+ channel 62.100 +# output. This provides a "fuller" playback quality for surround sound output 62.101 +# modes, although each individual speaker will have a slight reduction in 62.102 +# volume to compensate for the extra output speakers. True, yes, on, and non-0 62.103 +# values will duplicate stereo sources. 0 and anything else will cause stereo 62.104 +# sounds to only play in front. This only has an effect when a suitable output 62.105 +# format is used (ie. those that contain side and/or rear speakers). 62.106 +#stereodup = true 62.107 + 62.108 +## drivers: 62.109 +# Sets the backend driver list order, comma-seperated. Unknown backends and 62.110 +# duplicated names are ignored. Unlisted backends won't be considered for use 62.111 +# unless the list is ended with a comma (eg. 'oss,' will list OSS first 62.112 +# followed by all other available backends, while 'oss' will list OSS only). 62.113 +# Backends prepended with - won't be available for use (eg. '-oss,' will allow 62.114 +# all available backends except OSS). An empty list means the default. 62.115 +#drivers = pulse,alsa,core,oss,solaris,sndio,mmdevapi,dsound,winmm,port,opensl,null,wave 62.116 + 62.117 +## excludefx: 62.118 +# Sets which effects to exclude, preventing apps from using them. This can 62.119 +# help for apps that try to use effects which are too CPU intensive for the 62.120 +# system to handle. Available effects are: eaxreverb,reverb,echo,modulator, 62.121 +# dedicated 62.122 +#excludefx = 62.123 + 62.124 +## slots: 62.125 +# Sets the maximum number of Auxiliary Effect Slots an app can create. A slot 62.126 +# can use a non-negligible amount of CPU time if an effect is set on it even 62.127 +# if no sources are feeding it, so this may help when apps use more than the 62.128 +# system can handle. 62.129 +#slots = 4 62.130 + 62.131 +## sends: 62.132 +# Sets the number of auxiliary sends per source. When not specified (default), 62.133 +# it allows the app to request how many it wants. The maximum value currently 62.134 +# possible is 4. 62.135 +#sends = 62.136 + 62.137 +## layout: 62.138 +# Sets the virtual speaker layout. Values are specified in degrees, where 0 is 62.139 +# straight in front, negative goes left, and positive goes right. Unspecified 62.140 +# speakers will remain at their default positions (which are dependant on the 62.141 +# output format). Available speakers are back-left(bl), side-left(sl), front- 62.142 +# left(fl), front-center(fc), front-right(fr), side-right(sr), back-right(br), 62.143 +# and back-center(bc). 62.144 +#layout = 62.145 + 62.146 +## layout_*: 62.147 +# Channel-specific layouts may be specified to override the layout option. The 62.148 +# same speakers as the layout option are available, and the default settings 62.149 +# are shown below. 62.150 +#layout_STEREO = fl=-90, fr=90 62.151 +#layout_QUAD = fl=-45, fr=45, bl=-135, br=135 62.152 +#layout_51CHN = fl=-30, fr=30, fc=0, bl=-110, br=110 62.153 +#layout_61CHN = fl=-30, fr=30, fc=0, sl=-90, sr=90, bc=180 62.154 +#layout_71CHN = fl=-30, fr=30, fc=0, sl=-90, sr=90, bl=-150, br=150 62.155 + 62.156 +## 62.157 +## Reverb effect stuff (includes EAX reverb) 62.158 +## 62.159 +[reverb] 62.160 + 62.161 +## boost: 62.162 +# A global amplification for reverb output, expressed in decibels. The value 62.163 +# is logarithmic, so +6 will be a scale of (approximately) 2x, +12 will be a 62.164 +# scale of 4x, etc. Similarly, -6 will be about half, and -12 about 1/4th. A 62.165 +# value of 0 means no change. 62.166 +#boost = 0 62.167 + 62.168 +## emulate-eax: 62.169 +# Allows the standard reverb effect to be used in place of EAX reverb. EAX 62.170 +# reverb processing is a bit more CPU intensive than standard, so this option 62.171 +# allows a simpler effect to be used at the loss of some quality. 62.172 +#emulate-eax = false 62.173 + 62.174 +## 62.175 +## ALSA backend stuff 62.176 +## 62.177 +[alsa] 62.178 + 62.179 +## device: 62.180 +# Sets the device name for the default playback device. 62.181 +#device = default 62.182 + 62.183 +## device-prefix: 62.184 +# Sets the prefix used by the discovered (non-default) playback devices. This 62.185 +# will be appended with "CARD=c,DEV=d", where c is the card id and d is the 62.186 +# device index for the requested device name. 62.187 +#device-prefix = plughw: 62.188 + 62.189 +## capture: 62.190 +# Sets the device name for the default capture device. 62.191 +#capture = default 62.192 + 62.193 +## capture-prefix: 62.194 +# Sets the prefix used by the discovered (non-default) capture devices. This 62.195 +# will be appended with "CARD=c,DEV=d", where c is the card number and d is 62.196 +# the device number for the requested device name. 62.197 +#capture-prefix = plughw: 62.198 + 62.199 +## mmap: 62.200 +# Sets whether to try using mmap mode (helps reduce latencies and CPU 62.201 +# consumption). If mmap isn't available, it will automatically fall back to 62.202 +# non-mmap mode. True, yes, on, and non-0 values will attempt to use mmap. 0 62.203 +# and anything else will force mmap off. 62.204 +#mmap = true 62.205 + 62.206 +## 62.207 +## OSS backend stuff 62.208 +## 62.209 +[oss] 62.210 + 62.211 +## device: 62.212 +# Sets the device name for OSS output. 62.213 +#device = /dev/dsp 62.214 + 62.215 +## capture: 62.216 +# Sets the device name for OSS capture. 62.217 +#capture = /dev/dsp 62.218 + 62.219 +## 62.220 +## Solaris backend stuff 62.221 +## 62.222 +[solaris] 62.223 + 62.224 +## device: 62.225 +# Sets the device name for Solaris output. 62.226 +#device = /dev/audio 62.227 + 62.228 +## 62.229 +## MMDevApi backend stuff 62.230 +## 62.231 +[mmdevapi] 62.232 + 62.233 +## 62.234 +## DirectSound backend stuff 62.235 +## 62.236 +[dsound] 62.237 + 62.238 +## 62.239 +## Windows Multimedia backend stuff 62.240 +## 62.241 +[winmm] 62.242 + 62.243 +## 62.244 +## PortAudio backend stuff 62.245 +## 62.246 +[port] 62.247 + 62.248 +## device: 62.249 +# Sets the device index for output. Negative values will use the default as 62.250 +# given by PortAudio itself. 62.251 +#device = -1 62.252 + 62.253 +## capture: 62.254 +# Sets the device index for capture. Negative values will use the default as 62.255 +# given by PortAudio itself. 62.256 +#capture = -1 62.257 + 62.258 +## 62.259 +## PulseAudio backend stuff 62.260 +## 62.261 +[pulse] 62.262 + 62.263 +## spawn-server: 62.264 +# Attempts to spawn a PulseAudio server when requesting to open a PulseAudio 62.265 +# device. Note that some apps may open and probe all enumerated devices on 62.266 +# startup, causing a server to spawn even if a PulseAudio device is not 62.267 +# actually selected. Setting autospawn to false in Pulse's client.conf will 62.268 +# still prevent autospawning even if this is set to true. 62.269 +#spawn-server = false 62.270 + 62.271 +## 62.272 +## Wave File Writer stuff 62.273 +## 62.274 +[wave] 62.275 + 62.276 +## file: 62.277 +# Sets the filename of the wave file to write to. An empty name prevents the 62.278 +# backend from opening, even when explicitly requested. 62.279 +# THIS WILL OVERWRITE EXISTING FILES WITHOUT QUESTION! 62.280 +#file =
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 63.2 +++ b/bugs-in-openal.org Tue Oct 25 13:02:31 2011 -0700 63.3 @@ -0,0 +1,50 @@ 63.4 +* bugs in OpenAl-soft 63.5 + 63.6 +Wave files produced by wave writer do not have the correct header. 63.7 + 63.8 +something is wrong with 63.9 + 63.10 +#+begin_src conf 63.11 +drivers = null, 63.12 +#+end_src 63.13 + 63.14 +It only produces the single null option when queried with 63.15 +ALC_ALL_DEVICES_SPECIFIER, where it should produce much more output. 63.16 + 63.17 +specifically, 63.18 + 63.19 +------------------------------ 63.20 +#+begin_src conf 63.21 +drivers = oss, 63.22 +#+end_src 63.23 + 63.24 +#+begin_src text 63.25 +0: OSS Software 63.26 +1: PulseAudio Software 63.27 +2: ALSA Software on default 63.28 +3: ALSA Software on HDA Intel [ALC272 Analog] (hw:0,0) 63.29 +4: ALSA Software on HDA Intel [ALC272 Digital] (hw:0,1) 63.30 +5: ALSA Software on HDA Intel [INTEL HDMI] (hw:0,3) 63.31 +6: PortAudio Software 63.32 +7: Wave File Writer 63.33 +#+end_src 63.34 +------------------------------ 63.35 +#+begin_src conf 63.36 +drivers = pulse, 63.37 +#+end_src 63.38 + 63.39 +#+begin_src text 63.40 +Devices 63.41 +0: Internal Audio Analog Stereo 63.42 +#+end_src 63.43 +------------------------------ 63.44 +#+begin_src conf 63.45 +drivers = wave, 63.46 +#+end_src 63.47 + 63.48 +#+begin_src text 63.49 +Devices 63.50 +0: Wave File Writer 63.51 +#+end_src 63.52 +------------------------------ 63.53 +
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 64.2 +++ b/cleanup-message.txt Tue Oct 25 13:02:31 2011 -0700 64.3 @@ -0,0 +1,100 @@ 64.4 +My name is Robert McIntyre. I am seeking help packaging some changes 64.5 +I've made to open-al. 64.6 + 64.7 +* tl;dr how do I distribute changes to open-al which involve adding a 64.8 + new device? 64.9 + 64.10 +* Background / Motivation 64.11 + 64.12 +I'm working on an AI simulation involving multiple listeners, where 64.13 +each listener is a separate AI entity. Since each AI entity can move 64.14 +independently, I needed to add multiple listener functionality to 64.15 +open-al. Furthermore, my entire simulation allows time to dilate 64.16 +depending on how hard the entities are collectively "thinking," so 64.17 +that the entities can keep up with the simulation. Therefore, I 64.18 +needed to have a system that renders sound on-demand instead of trying 64.19 +to render in real time as open-al does. 64.20 + 64.21 +I don't need any of the more advanced effects, just 3D positioning, 64.22 +and I'm only using open-al from jMonkeyEngine3 that uses the LWJGL 64.23 +bindings that importantly only allow access to one and only one 64.24 +context. 64.25 + 64.26 +Under these constraints, I made a new device which renders sound in 64.27 +small, user-defined increments. It must be explicitly told to render 64.28 +sound or it won't do anything. It maintains a separate "auxiliary 64.29 +context" for every additional listener, and syncs the sources from the 64.30 +LWJGL context whenever it is about to render samples. I've tested it 64.31 +and it works quite well for my purposes. So far, I've gotten 1,000 64.32 +separate listeners to work in a single simulation easily. 64.33 + 64.34 +The code is here: 64.35 +http://aurellem.localhost/audio-send/html/send.html 64.36 +No criticism is too harsh! 64.37 + 64.38 +Note that the java JNI bindings that are part of the device code right 64.39 +now would be moved to a separate file the the same way that LWJGL does 64.40 +it. I left them there for now to show how the device might be used. 64.41 + 64.42 +Although I made this for my own AI work, it's ideal for recording 64.43 +perfect audio from a video game to create trailers/demos, since the 64.44 +computer doesn't have to try to record the sound in real time. This 64.45 +device could be used to record audio in any system that wraps open-al 64.46 +and only exposes one context, which is what many wrappers do. 64.47 + 64.48 + 64.49 +* Actual Question 64.50 + 64.51 +My question is about packaging --- how do you recommend I distribute 64.52 +my new device? I got it to work by just grafting it on the open-al's 64.53 +primitive object system, but this requires quite a few changes to main 64.54 +open-al source files, and as far as I can tell requires me to 64.55 +recompile open-al against my new device. 64.56 + 64.57 +I also don't want the user to be able to hide my devices presence 64.58 +using their ~/.alsoftrc file, since that gets in the way of easy 64.59 +recording when the system is wrapped several layers deep, and they've 64.60 +already implicitly requested my device anyway by using my code in the 64.61 +first place. 64.62 + 64.63 +The options I have thought of so far are: 64.64 + 64.65 +1.) Create my own C-artifact, compiled against open-al, which somehow 64.66 +"hooks in" my device to open-al and forces open-al to use it to the 64.67 +exclusion of all other devices. This new artifact would have bindings 64.68 +for java, etc. I don't know how to do this, since there doesn't seem 64.69 +to be any way to access the list of devices in Alc/ALc.c for example. 64.70 +In order to add a new device to open-al I had to modify 5 separate 64.71 +files, documented here: 64.72 + 64.73 +http://aurellem.localhost/audio-send/html/add-new-device.html 64.74 + 64.75 +and there doesn't seem to be a way to get the same effect 64.76 +programmatically. 64.77 + 64.78 +2.) Strip down open-al to a minimal version that only has my device 64.79 +and deal with selecting the right open-al library at a higher level, 64.80 +depending on whether the user wants to record sound or actually hear 64.81 +it. I don't like this because I can't easily benefit from 64.82 +improvements in the main open-al distribution. It also would involve 64.83 +more significant modification to jMonkeyEngine3's logic which selects 64.84 +the appropriate C-artifact at runtime. 64.85 + 64.86 +3.) Get this new device added to open-al, and provide a java wrapper 64.87 +for it in a separate artifact. Problem here is that this device does 64.88 +not have the same semantics as the other devices --- it must be told 64.89 +to render sound, doesn't support multiple user-created contexts, and 64.90 +it exposes extra functions for retrieving the rendered sounds. It also 64.91 +might be too "niche" for open-al proper. 64.92 + 64.93 +4.) Maybe abandon the device metaphor and use something better suited 64.94 +to my problem that /can/ be done as in (1)? 64.95 + 64.96 + 64.97 +I'm sure someone here knows enough about open-al's devices to give me 64.98 +a better solution than these 4! All help would be most appreciated. 64.99 + 64.100 +sincerely, 64.101 +--Robert McIntyre 64.102 + 64.103 +
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 65.2 +++ b/cmake/CheckCCompilerFlag.cmake Tue Oct 25 13:02:31 2011 -0700 65.3 @@ -0,0 +1,59 @@ 65.4 +# - Check if the C source code provided in the SOURCE argument compiles. 65.5 +# CHECK_C_SOURCE_COMPILES(SOURCE VAR) 65.6 +# 65.7 +# FLAG - compiler flag to check 65.8 +# VAR - variable to store whether the source code compiled 65.9 +# 65.10 +# The following variables may be set before calling this macro to 65.11 +# modify the way the check is run: 65.12 +# 65.13 +# CMAKE_REQUIRED_FLAGS = string of compile command line flags 65.14 +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) 65.15 +# CMAKE_REQUIRED_INCLUDES = list of include directories 65.16 +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link 65.17 + 65.18 +MACRO(CHECK_C_COMPILER_FLAG FLAG VAR) 65.19 + IF("${VAR}" MATCHES "^${VAR}$") 65.20 + SET(MACRO_CHECK_FUNCTION_DEFINITIONS 65.21 + "${FLAG} ${CMAKE_REQUIRED_FLAGS}") 65.22 + IF(CMAKE_REQUIRED_LIBRARIES) 65.23 + SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES 65.24 + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES}") 65.25 + ELSE(CMAKE_REQUIRED_LIBRARIES) 65.26 + SET(CHECK_C_COMPILER_FLAG_ADD_LIBRARIES) 65.27 + ENDIF(CMAKE_REQUIRED_LIBRARIES) 65.28 + IF(CMAKE_REQUIRED_INCLUDES) 65.29 + SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES 65.30 + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") 65.31 + ELSE(CMAKE_REQUIRED_INCLUDES) 65.32 + SET(CHECK_C_COMPILER_FLAG_ADD_INCLUDES) 65.33 + ENDIF(CMAKE_REQUIRED_INCLUDES) 65.34 + FILE(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c" 65.35 + "int main() {return 0;}\n") 65.36 + 65.37 + MESSAGE(STATUS "Checking if C compiler supports ${FLAG}") 65.38 + TRY_COMPILE(${VAR} 65.39 + ${CMAKE_BINARY_DIR} 65.40 + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/src.c 65.41 + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} 65.42 + CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS} 65.43 + "${CHECK_C_COMPILER_FLAG_ADD_LIBRARIES}" 65.44 + "${CHECK_C_COMPILER_FLAG_ADD_INCLUDES}" 65.45 + OUTPUT_VARIABLE OUTPUT) 65.46 + IF(${VAR}) 65.47 + SET(${VAR} 1 CACHE INTERNAL "Test ${VAR}") 65.48 + MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Success") 65.49 + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 65.50 + "Performing C SOURCE FILE Test ${VAR} succeded with the following output:\n" 65.51 + "${OUTPUT}\n" 65.52 + "Source file was:\n${SOURCE}\n") 65.53 + ELSE(${VAR}) 65.54 + MESSAGE(STATUS "Checking if C compiler supports ${FLAG} - Failed") 65.55 + SET(${VAR} "" CACHE INTERNAL "Test ${VAR}") 65.56 + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 65.57 + "Performing C SOURCE FILE Test ${VAR} failed with the following output:\n" 65.58 + "${OUTPUT}\n" 65.59 + "Source file was:\n${SOURCE}\n") 65.60 + ENDIF(${VAR}) 65.61 + ENDIF("${VAR}" MATCHES "^${VAR}$") 65.62 +ENDMACRO(CHECK_C_COMPILER_FLAG)
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 66.2 +++ b/cmake/CheckSharedFunctionExists.cmake Tue Oct 25 13:02:31 2011 -0700 66.3 @@ -0,0 +1,92 @@ 66.4 +# - Check if a symbol exists as a function, variable, or macro 66.5 +# CHECK_SYMBOL_EXISTS(<symbol> <files> <variable>) 66.6 +# 66.7 +# Check that the <symbol> is available after including given header 66.8 +# <files> and store the result in a <variable>. Specify the list 66.9 +# of files in one argument as a semicolon-separated list. 66.10 +# 66.11 +# If the header files define the symbol as a macro it is considered 66.12 +# available and assumed to work. If the header files declare the 66.13 +# symbol as a function or variable then the symbol must also be 66.14 +# available for linking. If the symbol is a type or enum value 66.15 +# it will not be recognized (consider using CheckTypeSize or 66.16 +# CheckCSourceCompiles). 66.17 +# 66.18 +# The following variables may be set before calling this macro to 66.19 +# modify the way the check is run: 66.20 +# 66.21 +# CMAKE_REQUIRED_FLAGS = string of compile command line flags 66.22 +# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar) 66.23 +# CMAKE_REQUIRED_INCLUDES = list of include directories 66.24 +# CMAKE_REQUIRED_LIBRARIES = list of libraries to link 66.25 + 66.26 +#============================================================================= 66.27 +# Copyright 2003-2011 Kitware, Inc. 66.28 +# 66.29 +# Distributed under the OSI-approved BSD License (the "License"); 66.30 +# see accompanying file Copyright.txt for details. 66.31 +# 66.32 +# This software is distributed WITHOUT ANY WARRANTY; without even the 66.33 +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 66.34 +# See the License for more information. 66.35 +#============================================================================= 66.36 +# (To distribute this file outside of CMake, substitute the full 66.37 +# License text for the above reference.) 66.38 + 66.39 +MACRO(CHECK_SHARED_FUNCTION_EXISTS SYMBOL FILES LIBRARY LOCATION VARIABLE) 66.40 + IF("${VARIABLE}" MATCHES "^${VARIABLE}$") 66.41 + SET(CMAKE_CONFIGURABLE_FILE_CONTENT "/* */\n") 66.42 + SET(MACRO_CHECK_SYMBOL_EXISTS_FLAGS ${CMAKE_REQUIRED_FLAGS}) 66.43 + IF(CMAKE_REQUIRED_LIBRARIES) 66.44 + SET(CHECK_SYMBOL_EXISTS_LIBS 66.45 + "-DLINK_LIBRARIES:STRING=${CMAKE_REQUIRED_LIBRARIES};${LIBRARY}") 66.46 + ELSE(CMAKE_REQUIRED_LIBRARIES) 66.47 + SET(CHECK_SYMBOL_EXISTS_LIBS 66.48 + "-DLINK_LIBRARIES:STRING=${LIBRARY}") 66.49 + ENDIF(CMAKE_REQUIRED_LIBRARIES) 66.50 + IF(CMAKE_REQUIRED_INCLUDES) 66.51 + SET(CMAKE_SYMBOL_EXISTS_INCLUDES 66.52 + "-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}") 66.53 + ELSE(CMAKE_REQUIRED_INCLUDES) 66.54 + SET(CMAKE_SYMBOL_EXISTS_INCLUDES) 66.55 + ENDIF(CMAKE_REQUIRED_INCLUDES) 66.56 + FOREACH(FILE ${FILES}) 66.57 + SET(CMAKE_CONFIGURABLE_FILE_CONTENT 66.58 + "${CMAKE_CONFIGURABLE_FILE_CONTENT}#include <${FILE}>\n") 66.59 + ENDFOREACH(FILE) 66.60 + SET(CMAKE_CONFIGURABLE_FILE_CONTENT 66.61 + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\nvoid cmakeRequireSymbol(int dummy,...){(void)dummy;}\nint main()\n{\n cmakeRequireSymbol(0,&${SYMBOL});\n return 0;\n}\n") 66.62 + 66.63 + CONFIGURE_FILE("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" 66.64 + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c" @ONLY) 66.65 + 66.66 + MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY}") 66.67 + TRY_COMPILE(${VARIABLE} 66.68 + ${CMAKE_BINARY_DIR} 66.69 + ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c 66.70 + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} 66.71 + CMAKE_FLAGS 66.72 + -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_SYMBOL_EXISTS_FLAGS} 66.73 + -DLINK_DIRECTORIES:STRING=${LOCATION} 66.74 + "${CHECK_SYMBOL_EXISTS_LIBS}" 66.75 + "${CMAKE_SYMBOL_EXISTS_INCLUDES}" 66.76 + OUTPUT_VARIABLE OUTPUT) 66.77 + IF(${VARIABLE}) 66.78 + MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - found") 66.79 + SET(${VARIABLE} 1 CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}") 66.80 + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log 66.81 + "Determining if the ${SYMBOL} " 66.82 + "exist in ${LIBRARY} passed with the following output:\n" 66.83 + "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n" 66.84 + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") 66.85 + ELSE(${VARIABLE}) 66.86 + MESSAGE(STATUS "Looking for ${SYMBOL} in ${LIBRARY} - not found.") 66.87 + SET(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL} in ${LIBRARY}") 66.88 + FILE(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log 66.89 + "Determining if the ${SYMBOL} " 66.90 + "exist in ${LIBRARY} failed with the following output:\n" 66.91 + "${OUTPUT}\nFile ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/CheckSymbolExists.c:\n" 66.92 + "${CMAKE_CONFIGURABLE_FILE_CONTENT}\n") 66.93 + ENDIF(${VARIABLE}) 66.94 + ENDIF("${VARIABLE}" MATCHES "^${VARIABLE}$") 66.95 +ENDMACRO(CHECK_SHARED_FUNCTION_EXISTS)
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 67.2 +++ b/config.h.in Tue Oct 25 13:02:31 2011 -0700 67.3 @@ -0,0 +1,129 @@ 67.4 +/* API declaration export attribute */ 67.5 +#define AL_API ${EXPORT_DECL} 67.6 +#define ALC_API ${EXPORT_DECL} 67.7 + 67.8 +/* Define to the library version */ 67.9 +#define ALSOFT_VERSION "${LIB_VERSION}" 67.10 + 67.11 +/* Define if we have the ALSA backend */ 67.12 +#cmakedefine HAVE_ALSA 67.13 + 67.14 +/* Define if we have the OSS backend */ 67.15 +#cmakedefine HAVE_OSS 67.16 + 67.17 +/* Define if we have the Solaris backend */ 67.18 +#cmakedefine HAVE_SOLARIS 67.19 + 67.20 +/* Define if we have the SndIO backend */ 67.21 +#cmakedefine HAVE_SNDIO 67.22 + 67.23 +/* Define if we have the MMDevApi backend */ 67.24 +#cmakedefine HAVE_MMDEVAPI 67.25 + 67.26 +/* Define if we have the DSound backend */ 67.27 +#cmakedefine HAVE_DSOUND 67.28 + 67.29 +/* Define if we have the Windows Multimedia backend */ 67.30 +#cmakedefine HAVE_WINMM 67.31 + 67.32 +/* Define if we have the PortAudio backend */ 67.33 +#cmakedefine HAVE_PORTAUDIO 67.34 + 67.35 +/* Define if we have the PulseAudio backend */ 67.36 +#cmakedefine HAVE_PULSEAUDIO 67.37 + 67.38 +/* Define if we have the CoreAudio backend */ 67.39 +#cmakedefine HAVE_COREAUDIO 67.40 + 67.41 +/* Define if we have the OpenSL backend */ 67.42 +#cmakedefine HAVE_OPENSL 67.43 + 67.44 +/* Define if we have the Wave Writer backend */ 67.45 +#cmakedefine HAVE_WAVE 67.46 + 67.47 +/* RLM: add send backend */ 67.48 +#cmakedefine HAVE_SEND 67.49 + 67.50 +/* Define if we have dlfcn.h */ 67.51 +#cmakedefine HAVE_DLFCN_H 67.52 + 67.53 +/* Define if we have the stat function */ 67.54 +#cmakedefine HAVE_STAT 67.55 + 67.56 +/* Define if we have the powf function */ 67.57 +#cmakedefine HAVE_POWF 67.58 + 67.59 +/* Define if we have the sqrtf function */ 67.60 +#cmakedefine HAVE_SQRTF 67.61 + 67.62 +/* Define if we have the acosf function */ 67.63 +#cmakedefine HAVE_ACOSF 67.64 + 67.65 +/* Define if we have the atanf function */ 67.66 +#cmakedefine HAVE_ATANF 67.67 + 67.68 +/* Define if we have the fabsf function */ 67.69 +#cmakedefine HAVE_FABSF 67.70 + 67.71 +/* Define if we have the strtof function */ 67.72 +#cmakedefine HAVE_STRTOF 67.73 + 67.74 +/* Define if we have stdint.h */ 67.75 +#cmakedefine HAVE_STDINT_H 67.76 + 67.77 +/* Define if we have the __int64 type */ 67.78 +#cmakedefine HAVE___INT64 67.79 + 67.80 +/* Define to the size of a long int type */ 67.81 +#cmakedefine SIZEOF_LONG ${SIZEOF_LONG} 67.82 + 67.83 +/* Define to the size of a long long int type */ 67.84 +#cmakedefine SIZEOF_LONG_LONG ${SIZEOF_LONG_LONG} 67.85 + 67.86 +/* Define to the size of an unsigned int type */ 67.87 +#cmakedefine SIZEOF_UINT ${SIZEOF_UINT} 67.88 + 67.89 +/* Define to the size of a void pointer type */ 67.90 +#cmakedefine SIZEOF_VOIDP ${SIZEOF_VOIDP} 67.91 + 67.92 +/* Define if we have GCC's destructor attribute */ 67.93 +#cmakedefine HAVE_GCC_DESTRUCTOR 67.94 + 67.95 +/* Define if we have GCC's format attribute */ 67.96 +#cmakedefine HAVE_GCC_FORMAT 67.97 + 67.98 +/* Define if we have pthread_np.h */ 67.99 +#cmakedefine HAVE_PTHREAD_NP_H 67.100 + 67.101 +/* Define if we have arm_neon.h */ 67.102 +#cmakedefine HAVE_ARM_NEON_H 67.103 + 67.104 +/* Define if we have guiddef.h */ 67.105 +#cmakedefine HAVE_GUIDDEF_H 67.106 + 67.107 +/* Define if we have guiddef.h */ 67.108 +#cmakedefine HAVE_INITGUID_H 67.109 + 67.110 +/* Define if we have ieeefp.h */ 67.111 +#cmakedefine HAVE_IEEEFP_H 67.112 + 67.113 +/* Define if we have float.h */ 67.114 +#cmakedefine HAVE_FLOAT_H 67.115 + 67.116 +/* Define if we have fenv.h */ 67.117 +#cmakedefine HAVE_FENV_H 67.118 + 67.119 +/* Define if we have fesetround() */ 67.120 +#cmakedefine HAVE_FESETROUND 67.121 + 67.122 +/* Define if we have _controlfp() */ 67.123 +#cmakedefine HAVE__CONTROLFP 67.124 + 67.125 +/* Define if we have pthread_setschedparam() */ 67.126 +#cmakedefine HAVE_PTHREAD_SETSCHEDPARAM 67.127 + 67.128 +/* Define if we have the restrict keyword */ 67.129 +#cmakedefine HAVE_RESTRICT 67.130 + 67.131 +/* Define if we have the __restrict keyword */ 67.132 +#cmakedefine HAVE___RESTRICT
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 68.2 +++ b/device_details.org Tue Oct 25 13:02:31 2011 -0700 68.3 @@ -0,0 +1,37 @@ 68.4 +* a device has a two names, 68.5 + - *name*, which is the filename and which appears before all of the functions. 68.6 + - *trueName*, which is a string that is used to summon the device. 68.7 + 68.8 + 68.9 +Every device has the *<name>_data* struct, which is where all the 68.10 +device specific state is located. 68.11 + 68.12 +In the function *<name>_open_playback*, the device is initialized, 68.13 +here the trueName is set, and the devices data is initialized. 68.14 + 68.15 +The ALCdevice's ExtraData field must always be cast to to the actual 68.16 +data struct that the device uses. 68.17 + 68.18 + 68.19 + 68.20 +the =open_playback= function is where everything is initialized, 68.21 + 68.22 + 68.23 +but the =reset_playback= is where the actual thread which is the heart 68.24 +of the device is started. 68.25 + 68.26 + 68.27 +every device has a <name>Proc function which takes a pointer to an 68.28 +ALCdevice and is run in a separate thread. It is this procedure that 68.29 +actually does stuff with sound data. 68.30 + 68.31 + 68.32 +It is the ALContext which controls the particulars of a listener. 68.33 + 68.34 +The context contains the device. 68.35 + 68.36 +* so do we need a new context for each listener, alone with their own 68.37 +devices? 68.38 + 68.39 +However, the device also maintains a *list* of contexts... 68.40 +
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 69.2 +++ b/ear.html Tue Oct 25 13:02:31 2011 -0700 69.3 @@ -0,0 +1,266 @@ 69.4 +<?xml version="1.0" encoding="utf-8"?> 69.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 69.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 69.7 +<html xmlns="http://www.w3.org/1999/xhtml" 69.8 +lang="en" xml:lang="en"> 69.9 +<head> 69.10 +<title>The EARS!</title> 69.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 69.12 +<meta name="generator" content="Org-mode"/> 69.13 +<meta name="generated" content="2011-09-21 16:38:27 MDT"/> 69.14 +<meta name="author" content="Robert McIntyre"/> 69.15 +<meta name="description" content="Simulating multiple listeners and the sense of hearing in uMonkeyEngine3"/> 69.16 +<meta name="keywords" content=""/> 69.17 +<style type="text/css"> 69.18 + <!--/*--><![CDATA[/*><!--*/ 69.19 + html { font-family: Times, serif; font-size: 12pt; } 69.20 + .title { text-align: center; } 69.21 + .todo { color: red; } 69.22 + .done { color: green; } 69.23 + .tag { background-color: #add8e6; font-weight:normal } 69.24 + .target { } 69.25 + .timestamp { color: #bebebe; } 69.26 + .timestamp-kwd { color: #5f9ea0; } 69.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 69.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 69.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 69.30 + p.verse { margin-left: 3% } 69.31 + pre { 69.32 + border: 1pt solid #AEBDCC; 69.33 + background-color: #F3F5F7; 69.34 + padding: 5pt; 69.35 + font-family: courier, monospace; 69.36 + font-size: 90%; 69.37 + overflow:auto; 69.38 + } 69.39 + table { border-collapse: collapse; } 69.40 + td, th { vertical-align: top; } 69.41 + th.right { text-align:center; } 69.42 + th.left { text-align:center; } 69.43 + th.center { text-align:center; } 69.44 + td.right { text-align:right; } 69.45 + td.left { text-align:left; } 69.46 + td.center { text-align:center; } 69.47 + dt { font-weight: bold; } 69.48 + div.figure { padding: 0.5em; } 69.49 + div.figure p { text-align: center; } 69.50 + textarea { overflow-x: auto; } 69.51 + .linenr { font-size:smaller } 69.52 + .code-highlighted {background-color:#ffff00;} 69.53 + .org-info-js_info-navigation { border-style:none; } 69.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 69.55 + white-space:nowrap; } 69.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 69.57 + font-weight:bold; } 69.58 + /*]]>*/--> 69.59 +</style> 69.60 +<link rel="stylesheet" type="text/css" href="../aurellem/src/css/aurellem.css"/> 69.61 +<script type="text/javascript"> 69.62 +<!--/*--><![CDATA[/*><!--*/ 69.63 + function CodeHighlightOn(elem, id) 69.64 + { 69.65 + var target = document.getElementById(id); 69.66 + if(null != target) { 69.67 + elem.cacheClassElem = elem.className; 69.68 + elem.cacheClassTarget = target.className; 69.69 + target.className = "code-highlighted"; 69.70 + elem.className = "code-highlighted"; 69.71 + } 69.72 + } 69.73 + function CodeHighlightOff(elem, id) 69.74 + { 69.75 + var target = document.getElementById(id); 69.76 + if(elem.cacheClassElem) 69.77 + elem.className = elem.cacheClassElem; 69.78 + if(elem.cacheClassTarget) 69.79 + target.className = elem.cacheClassTarget; 69.80 + } 69.81 +/*]]>*///--> 69.82 +</script> 69.83 + 69.84 +</head> 69.85 +<body> 69.86 + 69.87 +<div id="content"> 69.88 + 69.89 + 69.90 + 69.91 +<div class="header"> 69.92 + <div class="float-right"> 69.93 + <!-- 69.94 + <form> 69.95 + <input type="text"/><input type="submit" value="search the blog »"/> 69.96 + </form> 69.97 + --> 69.98 + </div> 69.99 + 69.100 + <h1>aurellem <em>☉</em></h1> 69.101 + <ul class="nav"> 69.102 + <li><a href="/">read the blog »</a></li> 69.103 + <!-- li><a href="#">learn about us »</a></li--> 69.104 + </ul> 69.105 +</div> 69.106 + 69.107 +<h1 class="title">The EARS!</h1> 69.108 +<div class="author">Written by <author>Robert McIntyre</author></div> 69.109 + 69.110 + 69.111 + 69.112 + 69.113 + 69.114 + 69.115 + 69.116 + 69.117 + 69.118 + 69.119 +<div id="table-of-contents"> 69.120 +<h2>Table of Contents</h2> 69.121 +<div id="text-table-of-contents"> 69.122 +<ul> 69.123 +<li><a href="#sec-1">1 Ears! </a></li> 69.124 +</ul> 69.125 +</div> 69.126 +</div> 69.127 + 69.128 +<div id="outline-container-1" class="outline-2"> 69.129 +<h2 id="sec-1"><span class="section-number-2">1</span> Ears! </h2> 69.130 +<div class="outline-text-2" id="text-1"> 69.131 + 69.132 + 69.133 +<p> 69.134 +I want to be able to place ears in a similiar manner to how I place 69.135 +the eyes. I want to be able to place ears in a unique spatial 69.136 +position, and recieve as output at every tick the FFT of whatever 69.137 +signals are happening at that point. 69.138 +</p> 69.139 + 69.140 + 69.141 + 69.142 +<pre class="src src-clojure">(<span style="color: #9b30ff;">ns</span> body.ear) 69.143 +(<span style="color: #da70d6;">use</span> 'cortex.world) 69.144 +(<span style="color: #da70d6;">use</span> 'cortex.import) 69.145 +(<span style="color: #da70d6;">use</span> 'clojure.contrib.def) 69.146 +(cortex.import/mega-import-jme3) 69.147 +(rlm.rlm-commands/help) 69.148 +(<span style="color: #9b30ff;">import</span> java.nio.ByteBuffer) 69.149 +(<span style="color: #9b30ff;">import</span> java.awt.image.BufferedImage) 69.150 +(<span style="color: #9b30ff;">import</span> java.awt.Color) 69.151 +(<span style="color: #9b30ff;">import</span> java.awt.Dimension) 69.152 +(<span style="color: #9b30ff;">import</span> java.awt.Graphics) 69.153 +(<span style="color: #9b30ff;">import</span> java.awt.Graphics2D) 69.154 +(<span style="color: #9b30ff;">import</span> java.awt.event.WindowAdapter) 69.155 +(<span style="color: #9b30ff;">import</span> java.awt.event.WindowEvent) 69.156 +(<span style="color: #9b30ff;">import</span> java.awt.image.BufferedImage) 69.157 +(<span style="color: #9b30ff;">import</span> java.nio.ByteBuffer) 69.158 +(<span style="color: #9b30ff;">import</span> javax.swing.JFrame) 69.159 +(<span style="color: #9b30ff;">import</span> javax.swing.JPanel) 69.160 +(<span style="color: #9b30ff;">import</span> javax.swing.SwingUtilities) 69.161 +(<span style="color: #9b30ff;">import</span> javax.swing.ImageIcon) 69.162 +(<span style="color: #9b30ff;">import</span> javax.swing.JOptionPane) 69.163 +(<span style="color: #9b30ff;">import</span> java.awt.image.ImageObserver) 69.164 +</pre> 69.165 + 69.166 + 69.167 + 69.168 + 69.169 +<p> 69.170 +JMonkeyEngine3's audio system works as follows: 69.171 +first, an appropiate audio renderer is created during initialization 69.172 +and depending on the context. On my computer, this is the 69.173 +LwjglAudioRenderer. 69.174 +</p> 69.175 +<p> 69.176 +The LwjglAudioRenderer sets a few internal state variables depending 69.177 +on what capabilities the audio system has. 69.178 +</p> 69.179 +<p> 69.180 +may very well need to make my own AudioRenderer 69.181 +</p> 69.182 + 69.183 + 69.184 + 69.185 +<pre class="src src-clojure">(<span style="color: #9b30ff;">in-ns</span> 'body.ear) 69.186 +(<span style="color: #9b30ff;">import</span> 'com.jme3.capture.SoundProcessor) 69.187 + 69.188 + 69.189 +(<span style="color: #9b30ff;">defn</span> <span style="color: #0000ff;">sound-processor</span> 69.190 + <span style="color: #EB4264;">"deals with converting ByteBuffers into Arrays of bytes so that the</span> 69.191 +<span style="color: #EB4264;"> continuation functions can be defined in terms of immutable stuff."</span> 69.192 + [continuation] 69.193 + (<span style="color: #da70d6;">proxy</span> [SoundProcessor] [] 69.194 + (cleanup []) 69.195 + (process 69.196 + [<span style="color: #228b22;">#^ByteBuffer</span> audioSamples numSamples] 69.197 + (no-exceptions 69.198 + (<span style="color: #9b30ff;">let</span> [byte-array (<span style="color: #da70d6;">byte-array</span> numSamples)] 69.199 + (.get audioSamples byte-array 0 numSamples) 69.200 + (continuation 69.201 + (<span style="color: #da70d6;">vec</span> byte-array))))))) 69.202 + 69.203 + 69.204 +(<span style="color: #9b30ff;">defn</span> <span style="color: #0000ff;">add-ear</span> 69.205 + <span style="color: #EB4264;">"add an ear to the world. The continuation function will be called</span> 69.206 +<span style="color: #EB4264;"> on the FFT or the sounds which the ear hears in the given</span> 69.207 +<span style="color: #EB4264;"> timeframe. Sound is 3D."</span> 69.208 + [world listener continuation] 69.209 + (<span style="color: #9b30ff;">let</span> [renderer (.getAudioRenderer world)] 69.210 + (.addListener renderer listener) 69.211 + (.registerSoundProcessor renderer listener 69.212 + (sound-processor continuation)) 69.213 + listener)) 69.214 + 69.215 +</pre> 69.216 + 69.217 + 69.218 + 69.219 + 69.220 + 69.221 + 69.222 + 69.223 +<pre class="src src-clojure">(<span style="color: #9b30ff;">ns</span> test.hearing) 69.224 +(<span style="color: #da70d6;">use</span> 'cortex.world) 69.225 +(<span style="color: #da70d6;">use</span> 'cortex.import) 69.226 +(<span style="color: #da70d6;">use</span> 'clojure.contrib.def) 69.227 +(<span style="color: #da70d6;">use</span> 'body.ear) 69.228 +(cortex.import/mega-import-jme3) 69.229 +(rlm.rlm-commands/help) 69.230 + 69.231 +(<span style="color: #9b30ff;">defn</span> <span style="color: #0000ff;">setup-fn</span> [world] 69.232 + (<span style="color: #9b30ff;">let</span> [listener (Listener.)] 69.233 + (add-ear world listener #(<span style="color: #da70d6;">println</span> (<span style="color: #da70d6;">nth</span> % 0))))) 69.234 + 69.235 +(<span style="color: #9b30ff;">defn</span> <span style="color: #0000ff;">play-sound</span> [node world value] 69.236 + (<span style="color: #9b30ff;">if</span> (<span style="color: #da70d6;">not</span> value) 69.237 + (<span style="color: #9b30ff;">do</span> 69.238 + (.playSource (.getAudioRenderer world) node)))) 69.239 + 69.240 +(<span style="color: #9b30ff;">defn</span> <span style="color: #0000ff;">test-world</span> [] 69.241 + (<span style="color: #9b30ff;">let</span> [node1 (AudioNode. (asset-manager) <span style="color: #3AA221;">"Sounds/pure.wav"</span> false false)] 69.242 + (world 69.243 + (Node.) 69.244 + {<span style="color: #3AA221;">"key-space"</span> (<span style="color: #da70d6;">partial</span> play-sound node1)} 69.245 + setup-fn 69.246 + no-op 69.247 + ))) 69.248 + 69.249 + 69.250 +</pre> 69.251 + 69.252 + 69.253 + 69.254 + 69.255 + 69.256 + 69.257 + 69.258 + 69.259 +</div> 69.260 +</div> 69.261 +<div id="postamble"> 69.262 +<p class="date">Date: 2011-09-21 16:38:27 MDT</p> 69.263 +<p class="author">Author: Robert McIntyre</p> 69.264 +<p class="creator">Org version 7.6 with Emacs version 23</p> 69.265 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 69.266 +</div> 69.267 +</div> 69.268 +</body> 69.269 +</html>
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 70.2 +++ b/ear.org Tue Oct 25 13:02:31 2011 -0700 70.3 @@ -0,0 +1,137 @@ 70.4 +#+title: The EARS! 70.5 +#+author: Robert McIntyre 70.6 +#+email: rlm@mit.edu 70.7 +#+MATHJAX: align:"left" mathml:t path:"../aurellem/src/MathJax/MathJax.js" 70.8 +#+STYLE: <link rel="stylesheet" type="text/css" href="../aurellem/src/css/aurellem.css"/> 70.9 +#+BABEL: :exports both :noweb yes :cache no :mkdirp yes 70.10 +#+INCLUDE: ../aurellem/src/templates/level-0.org 70.11 +#+description: Simulating multiple listeners and the sense of hearing in uMonkeyEngine3 70.12 + 70.13 + 70.14 + 70.15 + 70.16 +* Ears! 70.17 + 70.18 +I want to be able to place ears in a similiar manner to how I place 70.19 +the eyes. I want to be able to place ears in a unique spatial 70.20 +position, and recieve as output at every tick the FFT of whatever 70.21 +signals are happening at that point. 70.22 + 70.23 +#+srcname: ear-header 70.24 +#+begin_src clojure 70.25 +(ns body.ear) 70.26 +(use 'cortex.world) 70.27 +(use 'cortex.import) 70.28 +(use 'clojure.contrib.def) 70.29 +(cortex.import/mega-import-jme3) 70.30 +(rlm.rlm-commands/help) 70.31 +(import java.nio.ByteBuffer) 70.32 +(import java.awt.image.BufferedImage) 70.33 +(import java.awt.Color) 70.34 +(import java.awt.Dimension) 70.35 +(import java.awt.Graphics) 70.36 +(import java.awt.Graphics2D) 70.37 +(import java.awt.event.WindowAdapter) 70.38 +(import java.awt.event.WindowEvent) 70.39 +(import java.awt.image.BufferedImage) 70.40 +(import java.nio.ByteBuffer) 70.41 +(import javax.swing.JFrame) 70.42 +(import javax.swing.JPanel) 70.43 +(import javax.swing.SwingUtilities) 70.44 +(import javax.swing.ImageIcon) 70.45 +(import javax.swing.JOptionPane) 70.46 +(import java.awt.image.ImageObserver) 70.47 +#+end_src 70.48 + 70.49 +JMonkeyEngine3's audio system works as follows: 70.50 +first, an appropiate audio renderer is created during initialization 70.51 +and depending on the context. On my computer, this is the 70.52 +LwjglAudioRenderer. 70.53 + 70.54 +The LwjglAudioRenderer sets a few internal state variables depending 70.55 +on what capabilities the audio system has. 70.56 + 70.57 +may very well need to make my own AudioRenderer 70.58 + 70.59 +#+srcname: ear-body-1 70.60 +#+begin_src clojure :results silent 70.61 +(in-ns 'body.ear) 70.62 +(import 'com.jme3.capture.SoundProcessor) 70.63 + 70.64 + 70.65 +(defn sound-processor 70.66 + "deals with converting ByteBuffers into Arrays of bytes so that the 70.67 + continuation functions can be defined in terms of immutable stuff." 70.68 + [continuation] 70.69 + (proxy [SoundProcessor] [] 70.70 + (cleanup []) 70.71 + (process 70.72 + [#^ByteBuffer audioSamples numSamples] 70.73 + (no-exceptions 70.74 + (let [byte-array (byte-array numSamples)] 70.75 + (.get audioSamples byte-array 0 numSamples) 70.76 + (continuation 70.77 + (vec byte-array))))))) 70.78 + 70.79 + 70.80 +(defn add-ear 70.81 + "add an ear to the world. The continuation function will be called 70.82 + on the FFT or the sounds which the ear hears in the given 70.83 + timeframe. Sound is 3D." 70.84 + [world listener continuation] 70.85 + (let [renderer (.getAudioRenderer world)] 70.86 + (.addListener renderer listener) 70.87 + (.registerSoundProcessor renderer listener 70.88 + (sound-processor continuation)) 70.89 + listener)) 70.90 + 70.91 +#+end_src 70.92 + 70.93 + 70.94 + 70.95 +#+srcname: test-hearing 70.96 +#+begin_src clojure :results silent 70.97 +(ns test.hearing) 70.98 +(use 'cortex.world) 70.99 +(use 'cortex.import) 70.100 +(use 'clojure.contrib.def) 70.101 +(use 'body.ear) 70.102 +(cortex.import/mega-import-jme3) 70.103 +(rlm.rlm-commands/help) 70.104 + 70.105 +(defn setup-fn [world] 70.106 + (let [listener (Listener.)] 70.107 + (add-ear world listener #(println (nth % 0))))) 70.108 + 70.109 +(defn play-sound [node world value] 70.110 + (if (not value) 70.111 + (do 70.112 + (.playSource (.getAudioRenderer world) node)))) 70.113 + 70.114 +(defn test-world [] 70.115 + (let [node1 (AudioNode. (asset-manager) "Sounds/pure.wav" false false)] 70.116 + (world 70.117 + (Node.) 70.118 + {"key-space" (partial play-sound node1)} 70.119 + setup-fn 70.120 + no-op 70.121 + ))) 70.122 + 70.123 + 70.124 +#+end_src 70.125 + 70.126 + 70.127 + 70.128 +* COMMENT Code Generation 70.129 + 70.130 +#+begin_src clojure :tangle /home/r/cortex/src/body/ear.clj 70.131 +<<ear-header>> 70.132 +<<ear-body-1>> 70.133 +#+end_src 70.134 + 70.135 + 70.136 +#+begin_src clojure :tangle /home/r/cortex/src/test/hearing.clj 70.137 +<<test-hearing>> 70.138 +#+end_src 70.139 + 70.140 +
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 71.2 +++ b/html/add-new-device.html Tue Oct 25 13:02:31 2011 -0700 71.3 @@ -0,0 +1,301 @@ 71.4 +<?xml version="1.0" encoding="utf-8"?> 71.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 71.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 71.7 +<html xmlns="http://www.w3.org/1999/xhtml" 71.8 +lang="en" xml:lang="en"> 71.9 +<head> 71.10 +<title>all the steps to add a device to open-al</title> 71.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 71.12 +<meta name="generator" content="Org-mode"/> 71.13 +<meta name="generated" content="2011-10-20 15:48:47 MST"/> 71.14 +<meta name="author" content="Robert McIntyre"/> 71.15 +<meta name="description" content="how to add a new device to open-al"/> 71.16 +<meta name="keywords" content=""/> 71.17 +<style type="text/css"> 71.18 + <!--/*--><![CDATA[/*><!--*/ 71.19 + html { font-family: Times, serif; font-size: 12pt; } 71.20 + .title { text-align: center; } 71.21 + .todo { color: red; } 71.22 + .done { color: green; } 71.23 + .tag { background-color: #add8e6; font-weight:normal } 71.24 + .target { } 71.25 + .timestamp { color: #bebebe; } 71.26 + .timestamp-kwd { color: #5f9ea0; } 71.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 71.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 71.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 71.30 + p.verse { margin-left: 3% } 71.31 + pre { 71.32 + border: 1pt solid #AEBDCC; 71.33 + background-color: #F3F5F7; 71.34 + padding: 5pt; 71.35 + font-family: courier, monospace; 71.36 + font-size: 90%; 71.37 + overflow:auto; 71.38 + } 71.39 + table { border-collapse: collapse; } 71.40 + td, th { vertical-align: top; } 71.41 + th.right { text-align:center; } 71.42 + th.left { text-align:center; } 71.43 + th.center { text-align:center; } 71.44 + td.right { text-align:right; } 71.45 + td.left { text-align:left; } 71.46 + td.center { text-align:center; } 71.47 + dt { font-weight: bold; } 71.48 + div.figure { padding: 0.5em; } 71.49 + div.figure p { text-align: center; } 71.50 + textarea { overflow-x: auto; } 71.51 + .linenr { font-size:smaller } 71.52 + .code-highlighted {background-color:#ffff00;} 71.53 + .org-info-js_info-navigation { border-style:none; } 71.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 71.55 + white-space:nowrap; } 71.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 71.57 + font-weight:bold; } 71.58 + /*]]>*/--> 71.59 +</style> 71.60 +<link rel="stylesheet" type="text/css" href="/aurellem/css/aurellem.css" /> 71.61 +<script type="text/javascript"> 71.62 +<!--/*--><![CDATA[/*><!--*/ 71.63 + function CodeHighlightOn(elem, id) 71.64 + { 71.65 + var target = document.getElementById(id); 71.66 + if(null != target) { 71.67 + elem.cacheClassElem = elem.className; 71.68 + elem.cacheClassTarget = target.className; 71.69 + target.className = "code-highlighted"; 71.70 + elem.className = "code-highlighted"; 71.71 + } 71.72 + } 71.73 + function CodeHighlightOff(elem, id) 71.74 + { 71.75 + var target = document.getElementById(id); 71.76 + if(elem.cacheClassElem) 71.77 + elem.className = elem.cacheClassElem; 71.78 + if(elem.cacheClassTarget) 71.79 + target.className = elem.cacheClassTarget; 71.80 + } 71.81 +/*]]>*///--> 71.82 +</script> 71.83 + 71.84 +</head> 71.85 +<body> 71.86 + 71.87 +<div id="content"> 71.88 + 71.89 + 71.90 + 71.91 +<div class="header"> 71.92 + <div class="float-right"> 71.93 + <!-- 71.94 + <form> 71.95 + <input type="text"/><input type="submit" value="search the blog »"/> 71.96 + </form> 71.97 + --> 71.98 + </div> 71.99 + 71.100 + <h1>aurellem <em>☉</em></h1> 71.101 + <ul class="nav"> 71.102 + <li><a href="/">read the blog »</a></li> 71.103 + <!-- li><a href="#">learn about us »</a></li--> 71.104 + </ul> 71.105 +</div> 71.106 + 71.107 +<h1 class="title">all the steps to add a device to open-al</h1> 71.108 +<div class="author">Written by <author>Robert McIntyre</author></div> 71.109 + 71.110 + 71.111 + 71.112 + 71.113 + 71.114 + 71.115 + 71.116 +<div id="table-of-contents"> 71.117 +<h2>Table of Contents</h2> 71.118 +<div id="text-table-of-contents"> 71.119 +<ul> 71.120 +<li><a href="#sec-1">1 How to add a new backend device </a></li> 71.121 +<li><a href="#sec-2">2 In Alc/backends/<your-device>.c </a></li> 71.122 +<li><a href="#sec-3">3 In OpenAL32/Include/alMain.h : </a></li> 71.123 +<li><a href="#sec-4">4 In Alc/ALc.c : </a></li> 71.124 +<li><a href="#sec-5">5 In CMakeLists.txt </a></li> 71.125 +<li><a href="#sec-6">6 In ~/.alsoftrc </a></li> 71.126 +</ul> 71.127 +</div> 71.128 +</div> 71.129 + 71.130 +<div id="outline-container-1" class="outline-2"> 71.131 +<h2 id="sec-1"><span class="section-number-2">1</span> How to add a new backend device </h2> 71.132 +<div class="outline-text-2" id="text-1"> 71.133 + 71.134 + 71.135 +</div> 71.136 + 71.137 +</div> 71.138 + 71.139 +<div id="outline-container-2" class="outline-2"> 71.140 +<h2 id="sec-2"><span class="section-number-2">2</span> In Alc/backends/<your-device>.c </h2> 71.141 +<div class="outline-text-2" id="text-2"> 71.142 + 71.143 + 71.144 + 71.145 + 71.146 + 71.147 +<pre class="src src-C"><span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #f0dfaf; font-weight: bold;">const</span> <span style="color: #dfdfbf; font-weight: bold;">ALCchar</span> <your-device>_device[] = <your-device-name>; 71.148 + 71.149 +<span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <span style="color: #f0dfaf;">alc_</span><your-device>_init(BackendFuncs *func_list) 71.150 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_</span><your-device>_deinit(<span style="color: #dfdfbf; font-weight: bold;">void</span>) 71.151 + 71.152 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <your-device>_open_playback(ALCdevice *device, <span style="color: #f0dfaf; font-weight: bold;">const</span> <span style="color: #dfdfbf; font-weight: bold;">ALCchar</span> *<span style="color: #f0dfaf;">deviceName</span>) 71.153 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <your-device>_close_playback(ALCdevice *device) 71.154 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <your-device>_reset_playback(ALCdevice *device) 71.155 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <your-device>_stop_playback(ALCdevice *device) 71.156 +</pre> 71.157 + 71.158 + 71.159 + 71.160 + 71.161 + 71.162 +<pre class="src src-C"><span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_</span><your-device>_probe(<span style="color: #f0dfaf; font-weight: bold;">enum</span> <span style="color: #dfdfbf; font-weight: bold;">DevProbe</span> <span style="color: #f0dfaf;">type</span>) 71.163 +{ 71.164 + <span style="color: #f0dfaf; font-weight: bold;">switch</span>(type) 71.165 + { 71.166 + <span style="color: #f0dfaf; font-weight: bold;">case</span> DEVICE_PROBE: 71.167 + AppendDeviceList(<your-device>Device); 71.168 + <span style="color: #f0dfaf; font-weight: bold;">break</span>; 71.169 + <span style="color: #f0dfaf; font-weight: bold;">case</span> ALL_DEVICE_PROBE: 71.170 + AppendAllDeviceList(<your-device>Device); 71.171 + <span style="color: #f0dfaf; font-weight: bold;">break</span>; 71.172 + <span style="color: #f0dfaf; font-weight: bold;">case</span> CAPTURE_DEVICE_PROBE: 71.173 + <span style="color: #f0dfaf; font-weight: bold;">break</span>; 71.174 + } 71.175 +} 71.176 +</pre> 71.177 + 71.178 + 71.179 + 71.180 + 71.181 + 71.182 +<pre class="src src-C"><span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #f0dfaf; font-weight: bold;">const</span> <span style="color: #dfdfbf; font-weight: bold;">BackendFuncs</span> <your-device>_funcs = { 71.183 + <your-device>_open_playback, 71.184 + <your-device>_close_playback, 71.185 + <your-device>_reset_playback, 71.186 + <your-device>_stop_playback, 71.187 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 71.188 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 71.189 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 71.190 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 71.191 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 71.192 + <span style="color: #dca3a3; font-weight: bold;">NULL</span> 71.193 +}; 71.194 +</pre> 71.195 + 71.196 + 71.197 + 71.198 + 71.199 + 71.200 +</div> 71.201 + 71.202 +</div> 71.203 + 71.204 +<div id="outline-container-3" class="outline-2"> 71.205 +<h2 id="sec-3"><span class="section-number-2">3</span> In OpenAL32/Include/alMain.h : </h2> 71.206 +<div class="outline-text-2" id="text-3"> 71.207 + 71.208 + 71.209 + 71.210 + 71.211 + 71.212 +<pre class="src src-C"><span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <span style="color: #f0dfaf;">alc_</span><your-device>_init(BackendFuncs *func_list); 71.213 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_</span><your-device>_deinit(<span style="color: #dfdfbf; font-weight: bold;">void</span>); 71.214 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_</span><your-device>_probe(<span style="color: #f0dfaf; font-weight: bold;">enum</span> <span style="color: #dfdfbf; font-weight: bold;">DevProbe</span> <span style="color: #f0dfaf;">type</span>); 71.215 + 71.216 +</pre> 71.217 + 71.218 + 71.219 + 71.220 + 71.221 +</div> 71.222 + 71.223 +</div> 71.224 + 71.225 +<div id="outline-container-4" class="outline-2"> 71.226 +<h2 id="sec-4"><span class="section-number-2">4</span> In Alc/ALc.c : </h2> 71.227 +<div class="outline-text-2" id="text-4"> 71.228 + 71.229 + 71.230 + 71.231 + 71.232 +<pre class="src src-C"> { <span style="color: #cc9393;">"<your-device>"</span>, alc_<your-device>_init, 71.233 + alc_<your-device>_deinit, alc_<your-device>_probe, EmptyFuncs }, 71.234 + 71.235 +</pre> 71.236 + 71.237 + 71.238 + 71.239 + 71.240 +</div> 71.241 + 71.242 +</div> 71.243 + 71.244 +<div id="outline-container-5" class="outline-2"> 71.245 +<h2 id="sec-5"><span class="section-number-2">5</span> In CMakeLists.txt </h2> 71.246 +<div class="outline-text-2" id="text-5"> 71.247 + 71.248 + 71.249 + 71.250 + 71.251 +<pre class="src src-cmake">SET(ALC_OBJS Alc/ALc.c 71.252 + Alc/ALu.c 71.253 + Alc/alcConfig.c 71.254 + Alc/alcDedicated.c 71.255 + Alc/alcEcho.c 71.256 + Alc/alcModulator.c 71.257 + Alc/alcReverb.c 71.258 + Alc/alcRing.c 71.259 + Alc/alcThread.c 71.260 + Alc/bs2b.c 71.261 + Alc/helpers.c 71.262 + Alc/hrtf.c 71.263 + Alc/mixer.c 71.264 + Alc/panning.c 71.265 + # Default backends, always available 71.266 + Alc/backends/loopback.c 71.267 + Alc/backends/null.c 71.268 + # : add <your-device> device 71.269 + Alc/backends/<your-device>.c 71.270 +) 71.271 +</pre> 71.272 + 71.273 + 71.274 + 71.275 + 71.276 + 71.277 +</div> 71.278 + 71.279 +</div> 71.280 + 71.281 +<div id="outline-container-6" class="outline-2"> 71.282 +<h2 id="sec-6"><span class="section-number-2">6</span> In ~/.alsoftrc </h2> 71.283 +<div class="outline-text-2" id="text-6"> 71.284 + 71.285 + 71.286 + 71.287 + 71.288 + 71.289 +<pre class="src src-conf"><span style="color: #f0dfaf;">drivers</span> = <your-device> 71.290 +</pre> 71.291 + 71.292 + 71.293 + 71.294 +</div> 71.295 +</div> 71.296 +<div id="postamble"> 71.297 +<p class="date">Date: 2011-10-20 15:48:47 MST</p> 71.298 +<p class="author">Author: Robert McIntyre</p> 71.299 +<p class="creator">Org version 7.6 with Emacs version 23</p> 71.300 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 71.301 +</div> 71.302 +</div> 71.303 +</body> 71.304 +</html>
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 72.2 +++ b/html/send.html Tue Oct 25 13:02:31 2011 -0700 72.3 @@ -0,0 +1,599 @@ 72.4 +<?xml version="1.0" encoding="utf-8"?> 72.5 +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 72.6 + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 72.7 +<html xmlns="http://www.w3.org/1999/xhtml" 72.8 +lang="en" xml:lang="en"> 72.9 +<head> 72.10 +<title>send.c</title> 72.11 +<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/> 72.12 +<meta name="generator" content="Org-mode"/> 72.13 +<meta name="generated" content="2011-10-20 15:48:47 MST"/> 72.14 +<meta name="author" content="Robert McIntyre"/> 72.15 +<meta name="description" content="some code I wrote to extend open-al"/> 72.16 +<meta name="keywords" content=""/> 72.17 +<style type="text/css"> 72.18 + <!--/*--><![CDATA[/*><!--*/ 72.19 + html { font-family: Times, serif; font-size: 12pt; } 72.20 + .title { text-align: center; } 72.21 + .todo { color: red; } 72.22 + .done { color: green; } 72.23 + .tag { background-color: #add8e6; font-weight:normal } 72.24 + .target { } 72.25 + .timestamp { color: #bebebe; } 72.26 + .timestamp-kwd { color: #5f9ea0; } 72.27 + .right {margin-left:auto; margin-right:0px; text-align:right;} 72.28 + .left {margin-left:0px; margin-right:auto; text-align:left;} 72.29 + .center {margin-left:auto; margin-right:auto; text-align:center;} 72.30 + p.verse { margin-left: 3% } 72.31 + pre { 72.32 + border: 1pt solid #AEBDCC; 72.33 + background-color: #F3F5F7; 72.34 + padding: 5pt; 72.35 + font-family: courier, monospace; 72.36 + font-size: 90%; 72.37 + overflow:auto; 72.38 + } 72.39 + table { border-collapse: collapse; } 72.40 + td, th { vertical-align: top; } 72.41 + th.right { text-align:center; } 72.42 + th.left { text-align:center; } 72.43 + th.center { text-align:center; } 72.44 + td.right { text-align:right; } 72.45 + td.left { text-align:left; } 72.46 + td.center { text-align:center; } 72.47 + dt { font-weight: bold; } 72.48 + div.figure { padding: 0.5em; } 72.49 + div.figure p { text-align: center; } 72.50 + textarea { overflow-x: auto; } 72.51 + .linenr { font-size:smaller } 72.52 + .code-highlighted {background-color:#ffff00;} 72.53 + .org-info-js_info-navigation { border-style:none; } 72.54 + #org-info-js_console-label { font-size:10px; font-weight:bold; 72.55 + white-space:nowrap; } 72.56 + .org-info-js_search-highlight {background-color:#ffff00; color:#000000; 72.57 + font-weight:bold; } 72.58 + /*]]>*/--> 72.59 +</style> 72.60 +<link rel="stylesheet" type="text/css" href="/aurellem/css/aurellem.css" /> 72.61 +<script type="text/javascript"> 72.62 +<!--/*--><![CDATA[/*><!--*/ 72.63 + function CodeHighlightOn(elem, id) 72.64 + { 72.65 + var target = document.getElementById(id); 72.66 + if(null != target) { 72.67 + elem.cacheClassElem = elem.className; 72.68 + elem.cacheClassTarget = target.className; 72.69 + target.className = "code-highlighted"; 72.70 + elem.className = "code-highlighted"; 72.71 + } 72.72 + } 72.73 + function CodeHighlightOff(elem, id) 72.74 + { 72.75 + var target = document.getElementById(id); 72.76 + if(elem.cacheClassElem) 72.77 + elem.className = elem.cacheClassElem; 72.78 + if(elem.cacheClassTarget) 72.79 + target.className = elem.cacheClassTarget; 72.80 + } 72.81 +/*]]>*///--> 72.82 +</script> 72.83 + 72.84 +</head> 72.85 +<body> 72.86 + 72.87 +<div id="content"> 72.88 + 72.89 + 72.90 + 72.91 +<div class="header"> 72.92 + <div class="float-right"> 72.93 + <!-- 72.94 + <form> 72.95 + <input type="text"/><input type="submit" value="search the blog »"/> 72.96 + </form> 72.97 + --> 72.98 + </div> 72.99 + 72.100 + <h1>aurellem <em>☉</em></h1> 72.101 + <ul class="nav"> 72.102 + <li><a href="/">read the blog »</a></li> 72.103 + <!-- li><a href="#">learn about us »</a></li--> 72.104 + </ul> 72.105 +</div> 72.106 + 72.107 +<h1 class="title">send.c</h1> 72.108 +<div class="author">Written by <author>Robert McIntyre</author></div> 72.109 + 72.110 + 72.111 + 72.112 + 72.113 + 72.114 + 72.115 + 72.116 +<pre class="src src-C"><span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;">"config.h"</span> 72.117 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;"><stdlib.h></span> 72.118 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;">"alMain.h"</span> 72.119 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;">"AL/al.h"</span> 72.120 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;">"AL/alc.h"</span> 72.121 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;">"alSource.h"</span> 72.122 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;"><jni.h></span> 72.123 + 72.124 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">Summary</span> 72.125 + 72.126 +<span style="color: #f0dfaf; font-weight: bold;">struct</span> <span style="color: #dfdfbf; font-weight: bold;">send_data</span>; 72.127 +<span style="color: #f0dfaf; font-weight: bold;">struct</span> <span style="color: #dfdfbf; font-weight: bold;">context_data</span>; 72.128 + 72.129 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">addContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *); 72.130 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncContexts</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">master</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">slave</span>); 72.131 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncSources</span>(<span style="color: #dfdfbf; font-weight: bold;">ALsource</span> *<span style="color: #f0dfaf;">master</span>, <span style="color: #dfdfbf; font-weight: bold;">ALsource</span> *<span style="color: #f0dfaf;">slave</span>, 72.132 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">masterCtx</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">slaveCtx</span>); 72.133 + 72.134 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncSourcei</span>(<span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">master</span>, <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">slave</span>, 72.135 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">masterCtx</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx2</span>, <span style="color: #dfdfbf; font-weight: bold;">ALenum</span> <span style="color: #f0dfaf;">param</span>); 72.136 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncSourcef</span>(<span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">master</span>, <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">slave</span>, 72.137 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">masterCtx</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx2</span>, <span style="color: #dfdfbf; font-weight: bold;">ALenum</span> <span style="color: #f0dfaf;">param</span>); 72.138 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncSource3f</span>(<span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">master</span>, <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">slave</span>, 72.139 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">masterCtx</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx2</span>, <span style="color: #dfdfbf; font-weight: bold;">ALenum</span> <span style="color: #f0dfaf;">param</span>); 72.140 + 72.141 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">swapInContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *, <span style="color: #f0dfaf; font-weight: bold;">struct</span> <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *); 72.142 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">saveContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *, <span style="color: #f0dfaf; font-weight: bold;">struct</span> <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *); 72.143 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">limitContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *); 72.144 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">unLimitContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *); 72.145 + 72.146 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">init</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *); 72.147 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">renderData</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *, <span style="color: #dfdfbf; font-weight: bold;">int</span> <span style="color: #f0dfaf;">samples</span>); 72.148 + 72.149 +<span style="color: #8cd0d3;">#define</span> <span style="color: #f0dfaf;">UNUSED</span>(<span style="color: #f0dfaf;">x</span>) (<span style="color: #dfdfbf; font-weight: bold;">void</span>)(x) 72.150 + 72.151 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">State</span> 72.152 + 72.153 +<span style="color: #f0dfaf; font-weight: bold;">typedef</span> <span style="color: #f0dfaf; font-weight: bold;">struct</span> <span style="color: #dfdfbf; font-weight: bold;">context_data</span> { 72.154 + <span style="color: #dfdfbf; font-weight: bold;">ALfloat</span> <span style="color: #f0dfaf;">ClickRemoval</span>[MAXCHANNELS]; 72.155 + <span style="color: #dfdfbf; font-weight: bold;">ALfloat</span> <span style="color: #f0dfaf;">PendingClicks</span>[MAXCHANNELS]; 72.156 + <span style="color: #dfdfbf; font-weight: bold;">ALvoid</span> *<span style="color: #f0dfaf;">renderBuffer</span>; 72.157 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx</span>; 72.158 +} <span style="color: #f0dfaf;">context_data</span>; 72.159 + 72.160 +<span style="color: #f0dfaf; font-weight: bold;">typedef</span> <span style="color: #f0dfaf; font-weight: bold;">struct</span> <span style="color: #dfdfbf; font-weight: bold;">send_data</span> { 72.161 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">size</span>; 72.162 + <span style="color: #dfdfbf; font-weight: bold;">context_data</span> **<span style="color: #f0dfaf;">contexts</span>; 72.163 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">numContexts</span>; 72.164 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">maxContexts</span>; 72.165 +} <span style="color: #f0dfaf;">send_data</span>; 72.166 + 72.167 + 72.168 + 72.169 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">Context Creation / Synchronization</span> 72.170 + 72.171 +<span style="color: #8cd0d3;">#define</span> <span style="color: #f0dfaf;">_MAKE_SYNC</span>(<span style="color: #f0dfaf;">NAME</span>, <span style="color: #f0dfaf;">INIT_EXPR</span>, <span style="color: #f0dfaf;">GET_EXPR</span>, <span style="color: #f0dfaf;">SET_EXPR</span>) \ 72.172 + <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">NAME</span> (<span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">sourceID1</span>, <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">sourceID2</span>, \ 72.173 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx1</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx2</span>, \ 72.174 + <span style="color: #dfdfbf; font-weight: bold;">ALenum</span> <span style="color: #f0dfaf;">param</span>){ \ 72.175 + INIT_EXPR; \ 72.176 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">current</span> = alcGetCurrentContext(); \ 72.177 + alcMakeContextCurrent(ctx1); \ 72.178 + GET_EXPR; \ 72.179 + alcMakeContextCurrent(ctx2); \ 72.180 + SET_EXPR; \ 72.181 + alcMakeContextCurrent(current); \ 72.182 + } 72.183 + 72.184 +<span style="color: #8cd0d3;">#define</span> <span style="color: #f0dfaf;">MAKE_SYNC</span>(<span style="color: #f0dfaf;">NAME</span>, <span style="color: #f0dfaf;">TYPE</span>, <span style="color: #f0dfaf;">GET</span>, <span style="color: #f0dfaf;">SET</span>) \ 72.185 + _MAKE_SYNC(NAME, \ 72.186 + <span style="color: #dfdfbf; font-weight: bold;">TYPE</span> <span style="color: #f0dfaf;">value</span>, \ 72.187 + GET(sourceID1, param, &value), \ 72.188 + SET(sourceID2, param, value)) 72.189 + 72.190 +<span style="color: #8cd0d3;">#define</span> <span style="color: #f0dfaf;">MAKE_SYNC3</span>(<span style="color: #f0dfaf;">NAME</span>, <span style="color: #f0dfaf;">TYPE</span>, <span style="color: #f0dfaf;">GET</span>, <span style="color: #f0dfaf;">SET</span>) \ 72.191 + _MAKE_SYNC(NAME, \ 72.192 + <span style="color: #dfdfbf; font-weight: bold;">TYPE</span> <span style="color: #f0dfaf;">value1</span>; <span style="color: #dfdfbf; font-weight: bold;">TYPE</span> <span style="color: #f0dfaf;">value2</span>; <span style="color: #dfdfbf; font-weight: bold;">TYPE</span> <span style="color: #f0dfaf;">value3</span>;, \ 72.193 + GET(sourceID1, param, &value1, &value2, &value3), \ 72.194 + SET(sourceID2, param, value1, value2, value3)) 72.195 + 72.196 +MAKE_SYNC( syncSourcei, ALint, alGetSourcei, alSourcei); 72.197 +MAKE_SYNC( syncSourcef, ALfloat, alGetSourcef, alSourcef); 72.198 +MAKE_SYNC3(syncSource3i, ALint, alGetSource3i, alSource3i); 72.199 +MAKE_SYNC3(syncSource3f, ALfloat, alGetSource3f, alSource3f); 72.200 + 72.201 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncSources</span>(<span style="color: #dfdfbf; font-weight: bold;">ALsource</span> *<span style="color: #f0dfaf;">masterSource</span>, <span style="color: #dfdfbf; font-weight: bold;">ALsource</span> *<span style="color: #f0dfaf;">slaveSource</span>, 72.202 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">masterCtx</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">slaveCtx</span>){ 72.203 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">master</span> = masterSource->source; 72.204 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">slave</span> = slaveSource->source; 72.205 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">current</span> = alcGetCurrentContext(); 72.206 + 72.207 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_PITCH); 72.208 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_GAIN); 72.209 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_MAX_DISTANCE); 72.210 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_ROLLOFF_FACTOR); 72.211 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_REFERENCE_DISTANCE); 72.212 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_MIN_GAIN); 72.213 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_MAX_GAIN); 72.214 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_CONE_OUTER_GAIN); 72.215 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_CONE_INNER_ANGLE); 72.216 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_CONE_OUTER_ANGLE); 72.217 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_SEC_OFFSET); 72.218 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_SAMPLE_OFFSET); 72.219 + syncSourcef(master,slave,masterCtx,slaveCtx,AL_BYTE_OFFSET); 72.220 + 72.221 + syncSource3f(master,slave,masterCtx,slaveCtx,AL_POSITION); 72.222 + syncSource3f(master,slave,masterCtx,slaveCtx,AL_VELOCITY); 72.223 + syncSource3f(master,slave,masterCtx,slaveCtx,AL_DIRECTION); 72.224 + 72.225 + syncSourcei(master,slave,masterCtx,slaveCtx,AL_SOURCE_RELATIVE); 72.226 + syncSourcei(master,slave,masterCtx,slaveCtx,AL_LOOPING); 72.227 + 72.228 + alcMakeContextCurrent(masterCtx); 72.229 + <span style="color: #dfdfbf; font-weight: bold;">ALint</span> <span style="color: #f0dfaf;">source_type</span>; 72.230 + alGetSourcei(master, AL_SOURCE_TYPE, &source_type); 72.231 + 72.232 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">Only static sources are currently synchronized! </span> 72.233 + <span style="color: #f0dfaf; font-weight: bold;">if</span> (AL_STATIC == source_type){ 72.234 + <span style="color: #dfdfbf; font-weight: bold;">ALint</span> <span style="color: #f0dfaf;">master_buffer</span>; 72.235 + <span style="color: #dfdfbf; font-weight: bold;">ALint</span> <span style="color: #f0dfaf;">slave_buffer</span>; 72.236 + alGetSourcei(master, AL_BUFFER, &master_buffer); 72.237 + alcMakeContextCurrent(slaveCtx); 72.238 + alGetSourcei(slave, AL_BUFFER, &slave_buffer); 72.239 + <span style="color: #f0dfaf; font-weight: bold;">if</span> (master_buffer != slave_buffer){ 72.240 + alSourcei(slave, AL_BUFFER, master_buffer); 72.241 + } 72.242 + } 72.243 + 72.244 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">Synchronize the state of the two sources.</span> 72.245 + alcMakeContextCurrent(masterCtx); 72.246 + <span style="color: #dfdfbf; font-weight: bold;">ALint</span> <span style="color: #f0dfaf;">masterState</span>; 72.247 + <span style="color: #dfdfbf; font-weight: bold;">ALint</span> <span style="color: #f0dfaf;">slaveState</span>; 72.248 + 72.249 + alGetSourcei(master, AL_SOURCE_STATE, &masterState); 72.250 + alcMakeContextCurrent(slaveCtx); 72.251 + alGetSourcei(slave, AL_SOURCE_STATE, &slaveState); 72.252 + 72.253 + <span style="color: #f0dfaf; font-weight: bold;">if</span> (masterState != slaveState){ 72.254 + <span style="color: #f0dfaf; font-weight: bold;">switch</span> (masterState){ 72.255 + <span style="color: #f0dfaf; font-weight: bold;">case</span> AL_INITIAL : alSourceRewind(slave); <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.256 + <span style="color: #f0dfaf; font-weight: bold;">case</span> AL_PLAYING : alSourcePlay(slave); <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.257 + <span style="color: #f0dfaf; font-weight: bold;">case</span> AL_PAUSED : alSourcePause(slave); <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.258 + <span style="color: #f0dfaf; font-weight: bold;">case</span> AL_STOPPED : alSourceStop(slave); <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.259 + } 72.260 + } 72.261 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">Restore whatever context was previously active.</span> 72.262 + alcMakeContextCurrent(current); 72.263 +} 72.264 + 72.265 + 72.266 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">syncContexts</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">master</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">slave</span>){ 72.267 + <span style="color: #708070;">/* </span><span style="color: #7f9f7f;">If there aren't sufficient sources in slave to mirror </span> 72.268 +<span style="color: #7f9f7f;"> the sources in master, create them. </span><span style="color: #708070;">*/</span> 72.269 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">current</span> = alcGetCurrentContext(); 72.270 + 72.271 + <span style="color: #dfdfbf; font-weight: bold;">UIntMap</span> *<span style="color: #f0dfaf;">masterSourceMap</span> = &(master->SourceMap); 72.272 + <span style="color: #dfdfbf; font-weight: bold;">UIntMap</span> *<span style="color: #f0dfaf;">slaveSourceMap</span> = &(slave->SourceMap); 72.273 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">numMasterSources</span> = masterSourceMap->size; 72.274 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">numSlaveSources</span> = slaveSourceMap->size; 72.275 + 72.276 + alcMakeContextCurrent(slave); 72.277 + <span style="color: #f0dfaf; font-weight: bold;">if</span> (numSlaveSources < numMasterSources){ 72.278 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">numMissingSources</span> = numMasterSources - numSlaveSources; 72.279 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">newSources</span>[numMissingSources]; 72.280 + alGenSources(numMissingSources, newSources); 72.281 + } 72.282 + 72.283 + <span style="color: #708070;">/* </span><span style="color: #7f9f7f;">Now, slave is gauranteed to have at least as many sources</span> 72.284 +<span style="color: #7f9f7f;"> as master. Sync each source from master to the corresponding</span> 72.285 +<span style="color: #7f9f7f;"> source in slave. </span><span style="color: #708070;">*/</span> 72.286 + <span style="color: #dfdfbf; font-weight: bold;">int</span> <span style="color: #f0dfaf;">i</span>; 72.287 + <span style="color: #f0dfaf; font-weight: bold;">for</span>(i = 0; i < masterSourceMap->size; i++){ 72.288 + syncSources((<span style="color: #dfdfbf; font-weight: bold;">ALsource</span>*)masterSourceMap->array[i].value, 72.289 + (<span style="color: #dfdfbf; font-weight: bold;">ALsource</span>*)slaveSourceMap->array[i].value, 72.290 + master, slave); 72.291 + } 72.292 + alcMakeContextCurrent(current); 72.293 +} 72.294 + 72.295 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">addContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">context</span>){ 72.296 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)Device->ExtraData; 72.297 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">expand array if necessary</span> 72.298 + <span style="color: #f0dfaf; font-weight: bold;">if</span> (data->numContexts >= data->maxContexts){ 72.299 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">newMaxContexts</span> = data->maxContexts*2 + 1; 72.300 + data->contexts = realloc(data->contexts, newMaxContexts*<span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(context_data)); 72.301 + data->maxContexts = newMaxContexts; 72.302 + } 72.303 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">create context_data and add it to the main array</span> 72.304 + <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span>; 72.305 + ctxData = (<span style="color: #dfdfbf; font-weight: bold;">context_data</span>*)calloc(1, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(*ctxData)); 72.306 + ctxData->renderBuffer = malloc(data->size); 72.307 + ctxData->ctx = context; 72.308 + 72.309 + data->contexts[data->numContexts] = ctxData; 72.310 + data->numContexts++; 72.311 +} 72.312 + 72.313 + 72.314 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">Context Switching </span> 72.315 + 72.316 +<span style="color: #708070;">/* </span><span style="color: #7f9f7f;">A device brings along with it two pieces of state</span> 72.317 +<span style="color: #7f9f7f;"> * which have to be swapped in and out with each context.</span> 72.318 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.319 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">swapInContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>, <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span>){ 72.320 + memcpy(Device->ClickRemoval, ctxData->ClickRemoval, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)*MAXCHANNELS); 72.321 + memcpy(Device->PendingClicks, ctxData->PendingClicks, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)*MAXCHANNELS); 72.322 +} 72.323 + 72.324 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">saveContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>, <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span>){ 72.325 + memcpy(ctxData->ClickRemoval, Device->ClickRemoval, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)*MAXCHANNELS); 72.326 + memcpy(ctxData->PendingClicks, Device->PendingClicks, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)*MAXCHANNELS); 72.327 +} 72.328 + 72.329 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> **<span style="color: #f0dfaf;">currentContext</span>; 72.330 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">currentNumContext</span>; 72.331 + 72.332 +<span style="color: #708070;">/* </span><span style="color: #7f9f7f;">By default, all contexts are rendered at once for each call to aluMixData.</span> 72.333 +<span style="color: #7f9f7f;"> * This function uses the internals of the ALCdecice struct to temporarly </span> 72.334 +<span style="color: #7f9f7f;"> * cause aluMixData to only render the chosen context.</span> 72.335 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.336 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">limitContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>, <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx</span>){ 72.337 + currentContext = Device->Contexts; 72.338 + currentNumContext = Device->NumContexts; 72.339 + Device->Contexts = &ctx; 72.340 + Device->NumContexts = 1; 72.341 +} 72.342 + 72.343 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">unLimitContext</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>){ 72.344 + Device->Contexts = currentContext; 72.345 + Device->NumContexts = currentNumContext; 72.346 +} 72.347 + 72.348 + 72.349 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">Main Device Loop</span> 72.350 + 72.351 +<span style="color: #708070;">/* </span><span style="color: #7f9f7f;">Establish the LWJGL context as the main context, which will</span> 72.352 +<span style="color: #7f9f7f;"> * be synchronized to all the slave contexts</span> 72.353 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.354 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">init</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>){ 72.355 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">masterContext</span> = alcGetCurrentContext(); 72.356 + addContext(Device, masterContext); 72.357 +} 72.358 + 72.359 + 72.360 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">renderData</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>, <span style="color: #dfdfbf; font-weight: bold;">int</span> <span style="color: #f0dfaf;">samples</span>){ 72.361 + <span style="color: #f0dfaf; font-weight: bold;">if</span>(<span style="color: #f0dfaf; font-weight: bold;">!</span>Device->Connected){<span style="color: #f0dfaf; font-weight: bold;">return</span>;} 72.362 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)Device->ExtraData; 72.363 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">current</span> = alcGetCurrentContext(); 72.364 + 72.365 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">i</span>; 72.366 + <span style="color: #f0dfaf; font-weight: bold;">for</span> (i = 1; i < data->numContexts; i++){ 72.367 + syncContexts(data->contexts[0]->ctx , data->contexts[i]->ctx); 72.368 + } 72.369 + 72.370 + <span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #dfdfbf; font-weight: bold;">uint</span>) samples > Device->UpdateSize){ 72.371 + printf(<span style="color: #cc9393;">"exceeding internal buffer size; dropping samples\n"</span>); 72.372 + printf(<span style="color: #cc9393;">"requested %d; available %d\n"</span>, samples, Device->UpdateSize); 72.373 + samples = (<span style="color: #dfdfbf; font-weight: bold;">int</span>) Device->UpdateSize; 72.374 + } 72.375 + 72.376 + <span style="color: #f0dfaf; font-weight: bold;">for</span> (i = 0; i < data->numContexts; i++){ 72.377 + <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span> = data->contexts[i]; 72.378 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx</span> = ctxData->ctx; 72.379 + alcMakeContextCurrent(ctx); 72.380 + limitContext(Device, ctx); 72.381 + swapInContext(Device, ctxData); 72.382 + aluMixData(Device, ctxData->renderBuffer, samples); 72.383 + saveContext(Device, ctxData); 72.384 + unLimitContext(Device); 72.385 + } 72.386 + alcMakeContextCurrent(current); 72.387 +} 72.388 + 72.389 + 72.390 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">JNI Methods</span> 72.391 + 72.392 +<span style="color: #8cd0d3;">#include</span> <span style="color: #cc9393;">"com_jme3_capture_AudioSend.h"</span> 72.393 + 72.394 +<span style="color: #708070;">/*</span> 72.395 +<span style="color: #7f9f7f;"> * Class: com_jme3_capture_AudioSend</span> 72.396 +<span style="color: #7f9f7f;"> * Method: nstep</span> 72.397 +<span style="color: #7f9f7f;"> * Signature: (JI)V</span> 72.398 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.399 +JNIEXPORT <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">JNICALL</span> Java_com_jme3_capture_AudioSend_nstep 72.400 +(JNIEnv *env, <span style="color: #dfdfbf; font-weight: bold;">jclass</span> <span style="color: #f0dfaf;">clazz</span>, <span style="color: #dfdfbf; font-weight: bold;">jlong</span> <span style="color: #f0dfaf;">device</span>, <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">samples</span>){ 72.401 + UNUSED(env);UNUSED(clazz);UNUSED(device); 72.402 + renderData((<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span>*)((<span style="color: #dfdfbf; font-weight: bold;">intptr_t</span>)device), samples); 72.403 +} 72.404 + 72.405 +<span style="color: #708070;">/*</span> 72.406 +<span style="color: #7f9f7f;"> * Class: com_jme3_capture_AudioSend</span> 72.407 +<span style="color: #7f9f7f;"> * Method: ngetSamples</span> 72.408 +<span style="color: #7f9f7f;"> * Signature: (JLjava/nio/ByteBuffer;III)V</span> 72.409 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.410 +JNIEXPORT <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">JNICALL</span> Java_com_jme3_capture_AudioSend_ngetSamples 72.411 +(JNIEnv *env, <span style="color: #dfdfbf; font-weight: bold;">jclass</span> <span style="color: #f0dfaf;">clazz</span>, <span style="color: #dfdfbf; font-weight: bold;">jlong</span> <span style="color: #f0dfaf;">device</span>, <span style="color: #dfdfbf; font-weight: bold;">jobject</span> <span style="color: #f0dfaf;">buffer</span>, <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">position</span>, 72.412 + <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">samples</span>, <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">n</span>){ 72.413 + UNUSED(clazz); 72.414 + 72.415 + <span style="color: #dfdfbf; font-weight: bold;">ALvoid</span> *<span style="color: #f0dfaf;">buffer_address</span> = 72.416 + ((<span style="color: #dfdfbf; font-weight: bold;">ALbyte</span> *)(((<span style="color: #dfdfbf; font-weight: bold;">char</span>*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); 72.417 + <span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">recorder</span> = (<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span>*) ((<span style="color: #dfdfbf; font-weight: bold;">intptr_t</span>)device); 72.418 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)recorder->ExtraData; 72.419 + <span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #dfdfbf; font-weight: bold;">ALuint</span>)n > data->numContexts){<span style="color: #f0dfaf; font-weight: bold;">return</span>;} 72.420 + <span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #dfdfbf; font-weight: bold;">uint</span>) samples > data->size){ 72.421 + samples = (<span style="color: #dfdfbf; font-weight: bold;">int</span>) data->size; 72.422 + } 72.423 + memcpy(buffer_address, data->contexts[n]->renderBuffer, samples*<span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)); 72.424 +} 72.425 + 72.426 +<span style="color: #708070;">/*</span> 72.427 +<span style="color: #7f9f7f;"> * Class: com_jme3_capture_AudioSend</span> 72.428 +<span style="color: #7f9f7f;"> * Method: naddListener</span> 72.429 +<span style="color: #7f9f7f;"> * Signature: (J)V</span> 72.430 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.431 +JNIEXPORT <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">JNICALL</span> Java_com_jme3_capture_AudioSend_naddListener 72.432 +(JNIEnv *env, <span style="color: #dfdfbf; font-weight: bold;">jclass</span> <span style="color: #f0dfaf;">clazz</span>, <span style="color: #dfdfbf; font-weight: bold;">jlong</span> <span style="color: #f0dfaf;">device</span>){ 72.433 + UNUSED(env); UNUSED(clazz); 72.434 + printf(<span style="color: #cc9393;">"creating new context via naddListener\n"</span>); 72.435 + <span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span> = (<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span>*) ((<span style="color: #dfdfbf; font-weight: bold;">intptr_t</span>)device); 72.436 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">new</span> = alcCreateContext(Device, <span style="color: #dca3a3; font-weight: bold;">NULL</span>); 72.437 + addContext(Device, new); 72.438 +} 72.439 + 72.440 +<span style="color: #708070;">/*</span> 72.441 +<span style="color: #7f9f7f;"> * Class: com_jme3_capture_AudioSend</span> 72.442 +<span style="color: #7f9f7f;"> * Method: nsetNthListener3f</span> 72.443 +<span style="color: #7f9f7f;"> * Signature: (IFFFJI)V</span> 72.444 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.445 +JNIEXPORT <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">JNICALL</span> Java_com_jme3_capture_AudioSend_nsetNthListener3f 72.446 + (JNIEnv *env, <span style="color: #dfdfbf; font-weight: bold;">jclass</span> <span style="color: #f0dfaf;">clazz</span>, <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">param</span>, 72.447 + <span style="color: #dfdfbf; font-weight: bold;">jfloat</span> <span style="color: #f0dfaf;">v1</span>, <span style="color: #dfdfbf; font-weight: bold;">jfloat</span> <span style="color: #f0dfaf;">v2</span>, <span style="color: #dfdfbf; font-weight: bold;">jfloat</span> <span style="color: #f0dfaf;">v3</span>, <span style="color: #dfdfbf; font-weight: bold;">jlong</span> <span style="color: #f0dfaf;">device</span>, <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">contextNum</span>){ 72.448 + UNUSED(env);UNUSED(clazz); 72.449 + 72.450 + <span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span> = (<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span>*) ((<span style="color: #dfdfbf; font-weight: bold;">intptr_t</span>)device); 72.451 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)Device->ExtraData; 72.452 + 72.453 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">current</span> = alcGetCurrentContext(); 72.454 + <span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #dfdfbf; font-weight: bold;">ALuint</span>)contextNum > data->numContexts){<span style="color: #f0dfaf; font-weight: bold;">return</span>;} 72.455 + alcMakeContextCurrent(data->contexts[contextNum]->ctx); 72.456 + alListener3f(param, v1, v2, v3); 72.457 + alcMakeContextCurrent(current); 72.458 +} 72.459 + 72.460 +<span style="color: #708070;">/*</span> 72.461 +<span style="color: #7f9f7f;"> * Class: com_jme3_capture_AudioSend</span> 72.462 +<span style="color: #7f9f7f;"> * Method: nsetNthListenerf</span> 72.463 +<span style="color: #7f9f7f;"> * Signature: (IFJI)V</span> 72.464 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.465 +JNIEXPORT <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">JNICALL</span> Java_com_jme3_capture_AudioSend_nsetNthListenerf 72.466 +(JNIEnv *env, <span style="color: #dfdfbf; font-weight: bold;">jclass</span> <span style="color: #f0dfaf;">clazz</span>, <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">param</span>, <span style="color: #dfdfbf; font-weight: bold;">jfloat</span> <span style="color: #f0dfaf;">v1</span>, <span style="color: #dfdfbf; font-weight: bold;">jlong</span> <span style="color: #f0dfaf;">device</span>, 72.467 + <span style="color: #dfdfbf; font-weight: bold;">jint</span> <span style="color: #f0dfaf;">contextNum</span>){ 72.468 + 72.469 + UNUSED(env);UNUSED(clazz); 72.470 + 72.471 + <span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span> = (<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span>*) ((<span style="color: #dfdfbf; font-weight: bold;">intptr_t</span>)device); 72.472 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)Device->ExtraData; 72.473 + 72.474 + <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">current</span> = alcGetCurrentContext(); 72.475 + <span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #dfdfbf; font-weight: bold;">ALuint</span>)contextNum > data->numContexts){<span style="color: #f0dfaf; font-weight: bold;">return</span>;} 72.476 + alcMakeContextCurrent(data->contexts[contextNum]->ctx); 72.477 + alListenerf(param, v1); 72.478 + alcMakeContextCurrent(current); 72.479 +} 72.480 + 72.481 +<span style="color: #708070;">/*</span> 72.482 +<span style="color: #7f9f7f;"> * Class: com_jme3_capture_AudioSend</span> 72.483 +<span style="color: #7f9f7f;"> * Method: ninitDevice</span> 72.484 +<span style="color: #7f9f7f;"> * Signature: (J)V</span> 72.485 +<span style="color: #7f9f7f;"> </span><span style="color: #708070;">*/</span> 72.486 +JNIEXPORT <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">JNICALL</span> Java_com_jme3_capture_AudioSend_ninitDevice 72.487 +(JNIEnv *env, <span style="color: #dfdfbf; font-weight: bold;">jclass</span> <span style="color: #f0dfaf;">clazz</span>, <span style="color: #dfdfbf; font-weight: bold;">jlong</span> <span style="color: #f0dfaf;">device</span>){ 72.488 + UNUSED(env);UNUSED(clazz); 72.489 + 72.490 + <span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span> = (<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span>*) ((<span style="color: #dfdfbf; font-weight: bold;">intptr_t</span>)device); 72.491 + init(Device); 72.492 + 72.493 +} 72.494 + 72.495 + 72.496 +<span style="color: #708070;">//////////////////// </span><span style="color: #7f9f7f;">Device Initilization / Management</span> 72.497 + 72.498 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #f0dfaf; font-weight: bold;">const</span> <span style="color: #dfdfbf; font-weight: bold;">ALCchar</span> <span style="color: #f0dfaf;">sendDevice</span>[] = <span style="color: #cc9393;">"Multiple Audio Send"</span>; 72.499 + 72.500 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <span style="color: #f0dfaf;">send_open_playback</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">device</span>, 72.501 + <span style="color: #f0dfaf; font-weight: bold;">const</span> <span style="color: #dfdfbf; font-weight: bold;">ALCchar</span> *<span style="color: #f0dfaf;">deviceName</span>) 72.502 +{ 72.503 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span>; 72.504 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">stop any buffering for stdout, so that I can </span> 72.505 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">see the printf statements in my terminal immediatley</span> 72.506 + setbuf(stdout, <span style="color: #dca3a3; font-weight: bold;">NULL</span>); 72.507 + 72.508 + <span style="color: #f0dfaf; font-weight: bold;">if</span>(<span style="color: #f0dfaf; font-weight: bold;">!</span>deviceName) 72.509 + deviceName = sendDevice; 72.510 + <span style="color: #f0dfaf; font-weight: bold;">else</span> <span style="color: #f0dfaf; font-weight: bold;">if</span>(strcmp(deviceName, sendDevice) != 0) 72.511 + <span style="color: #f0dfaf; font-weight: bold;">return</span> ALC_FALSE; 72.512 + data = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)calloc(1, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(*data)); 72.513 + device->szDeviceName = strdup(deviceName); 72.514 + device->ExtraData = data; 72.515 + <span style="color: #f0dfaf; font-weight: bold;">return</span> ALC_TRUE; 72.516 +} 72.517 + 72.518 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">send_close_playback</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">device</span>) 72.519 +{ 72.520 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)device->ExtraData; 72.521 + alcMakeContextCurrent(<span style="color: #dca3a3; font-weight: bold;">NULL</span>); 72.522 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">i</span>; 72.523 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">Destroy all slave contexts. LWJGL will take care of </span> 72.524 + <span style="color: #708070;">// </span><span style="color: #7f9f7f;">its own context.</span> 72.525 + <span style="color: #f0dfaf; font-weight: bold;">for</span> (i = 1; i < data->numContexts; i++){ 72.526 + <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span> = data->contexts[i]; 72.527 + alcDestroyContext(ctxData->ctx); 72.528 + free(ctxData->renderBuffer); 72.529 + free(ctxData); 72.530 + } 72.531 + free(data); 72.532 + device->ExtraData = <span style="color: #dca3a3; font-weight: bold;">NULL</span>; 72.533 +} 72.534 + 72.535 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <span style="color: #f0dfaf;">send_reset_playback</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">device</span>) 72.536 +{ 72.537 + <span style="color: #dfdfbf; font-weight: bold;">send_data</span> *<span style="color: #f0dfaf;">data</span> = (<span style="color: #dfdfbf; font-weight: bold;">send_data</span>*)device->ExtraData; 72.538 + <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">channels</span>=0, <span style="color: #f0dfaf;">bits</span>=0; 72.539 + device->FmtType = DevFmtShort; 72.540 + bits = BytesFromDevFmt(device->FmtType) * 8; 72.541 + channels = ChannelsFromDevFmt(device->FmtChans); 72.542 + data->size = device->UpdateSize * channels * bits / 8; 72.543 + 72.544 + <span style="color: #f0dfaf; font-weight: bold;">return</span> ALC_TRUE; 72.545 +} 72.546 + 72.547 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">send_stop_playback</span>(<span style="color: #dfdfbf; font-weight: bold;">ALCdevice</span> *<span style="color: #f0dfaf;">Device</span>){ 72.548 + UNUSED(Device); 72.549 +} 72.550 + 72.551 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #f0dfaf; font-weight: bold;">const</span> <span style="color: #dfdfbf; font-weight: bold;">BackendFuncs</span> <span style="color: #f0dfaf;">send_funcs</span> = { 72.552 + send_open_playback, 72.553 + send_close_playback, 72.554 + send_reset_playback, 72.555 + send_stop_playback, 72.556 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 72.557 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, <span style="color: #708070;">/* </span><span style="color: #7f9f7f;">These would be filled with functions to </span><span style="color: #708070;">*/</span> 72.558 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, <span style="color: #708070;">/* </span><span style="color: #7f9f7f;">handle capturing audio if we we into that </span><span style="color: #708070;">*/</span> 72.559 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, <span style="color: #708070;">/* </span><span style="color: #7f9f7f;">sort of thing... </span><span style="color: #708070;">*/</span> 72.560 + <span style="color: #dca3a3; font-weight: bold;">NULL</span>, 72.561 + <span style="color: #dca3a3; font-weight: bold;">NULL</span> 72.562 +}; 72.563 + 72.564 +<span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <span style="color: #f0dfaf;">alc_send_init</span>(<span style="color: #dfdfbf; font-weight: bold;">BackendFuncs</span> *<span style="color: #f0dfaf;">func_list</span>){ 72.565 + *func_list = send_funcs; 72.566 + <span style="color: #f0dfaf; font-weight: bold;">return</span> ALC_TRUE; 72.567 +} 72.568 + 72.569 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_send_deinit</span>(<span style="color: #dfdfbf; font-weight: bold;">void</span>){} 72.570 + 72.571 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_send_probe</span>(<span style="color: #f0dfaf; font-weight: bold;">enum</span> <span style="color: #dfdfbf; font-weight: bold;">DevProbe</span> <span style="color: #f0dfaf;">type</span>) 72.572 +{ 72.573 + <span style="color: #f0dfaf; font-weight: bold;">switch</span>(type) 72.574 + { 72.575 + <span style="color: #f0dfaf; font-weight: bold;">case</span> DEVICE_PROBE: 72.576 + AppendDeviceList(sendDevice); 72.577 + <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.578 + <span style="color: #f0dfaf; font-weight: bold;">case</span> ALL_DEVICE_PROBE: 72.579 + AppendAllDeviceList(sendDevice); 72.580 + <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.581 + <span style="color: #f0dfaf; font-weight: bold;">case</span> CAPTURE_DEVICE_PROBE: 72.582 + <span style="color: #f0dfaf; font-weight: bold;">break</span>; 72.583 + } 72.584 +} 72.585 + 72.586 + 72.587 + 72.588 +</pre> 72.589 + 72.590 + 72.591 + 72.592 + 72.593 + 72.594 +<div id="postamble"> 72.595 +<p class="date">Date: 2011-10-20 15:48:47 MST</p> 72.596 +<p class="author">Author: Robert McIntyre</p> 72.597 +<p class="creator">Org version 7.6 with Emacs version 23</p> 72.598 +<a href="http://validator.w3.org/check?uri=referer">Validate XHTML 1.0</a> 72.599 +</div> 72.600 +</div> 72.601 +</body> 72.602 +</html>
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 73.2 +++ b/include/AL/al.h Tue Oct 25 13:02:31 2011 -0700 73.3 @@ -0,0 +1,718 @@ 73.4 +#ifndef AL_AL_H 73.5 +#define AL_AL_H 73.6 + 73.7 +#if defined(__cplusplus) 73.8 +extern "C" { 73.9 +#endif 73.10 + 73.11 +#ifndef AL_API 73.12 + #if defined(AL_LIBTYPE_STATIC) 73.13 + #define AL_API 73.14 + #elif defined(_WIN32) 73.15 + #define AL_API __declspec(dllimport) 73.16 + #else 73.17 + #define AL_API extern 73.18 + #endif 73.19 +#endif 73.20 + 73.21 +#if defined(_WIN32) 73.22 + #define AL_APIENTRY __cdecl 73.23 +#else 73.24 + #define AL_APIENTRY 73.25 +#endif 73.26 + 73.27 +#if defined(TARGET_OS_MAC) && TARGET_OS_MAC 73.28 + #pragma export on 73.29 +#endif 73.30 + 73.31 +/* 73.32 + * The OPENAL, ALAPI, ALAPIENTRY, AL_INVALID, AL_ILLEGAL_ENUM, and 73.33 + * AL_ILLEGAL_COMMAND macros are deprecated, but are included for 73.34 + * applications porting code from AL 1.0 73.35 + */ 73.36 +#define OPENAL 73.37 +#define ALAPI AL_API 73.38 +#define ALAPIENTRY AL_APIENTRY 73.39 +#define AL_INVALID (-1) 73.40 +#define AL_ILLEGAL_ENUM AL_INVALID_ENUM 73.41 +#define AL_ILLEGAL_COMMAND AL_INVALID_OPERATION 73.42 + 73.43 +#define AL_VERSION_1_0 73.44 +#define AL_VERSION_1_1 73.45 + 73.46 + 73.47 +/** 8-bit boolean */ 73.48 +typedef char ALboolean; 73.49 + 73.50 +/** character */ 73.51 +typedef char ALchar; 73.52 + 73.53 +/** signed 8-bit 2's complement integer */ 73.54 +typedef signed char ALbyte; 73.55 + 73.56 +/** unsigned 8-bit integer */ 73.57 +typedef unsigned char ALubyte; 73.58 + 73.59 +/** signed 16-bit 2's complement integer */ 73.60 +typedef short ALshort; 73.61 + 73.62 +/** unsigned 16-bit integer */ 73.63 +typedef unsigned short ALushort; 73.64 + 73.65 +/** signed 32-bit 2's complement integer */ 73.66 +typedef int ALint; 73.67 + 73.68 +/** unsigned 32-bit integer */ 73.69 +typedef unsigned int ALuint; 73.70 + 73.71 +/** non-negative 32-bit binary integer size */ 73.72 +typedef int ALsizei; 73.73 + 73.74 +/** enumerated 32-bit value */ 73.75 +typedef int ALenum; 73.76 + 73.77 +/** 32-bit IEEE754 floating-point */ 73.78 +typedef float ALfloat; 73.79 + 73.80 +/** 64-bit IEEE754 floating-point */ 73.81 +typedef double ALdouble; 73.82 + 73.83 +/** void type (for opaque pointers only) */ 73.84 +typedef void ALvoid; 73.85 + 73.86 + 73.87 +/* Enumerant values begin at column 50. No tabs. */ 73.88 + 73.89 +/* "no distance model" or "no buffer" */ 73.90 +#define AL_NONE 0 73.91 + 73.92 +/* Boolean False. */ 73.93 +#define AL_FALSE 0 73.94 + 73.95 +/** Boolean True. */ 73.96 +#define AL_TRUE 1 73.97 + 73.98 +/** Indicate Source has relative coordinates. */ 73.99 +#define AL_SOURCE_RELATIVE 0x202 73.100 + 73.101 + 73.102 + 73.103 +/** 73.104 + * Directional source, inner cone angle, in degrees. 73.105 + * Range: [0-360] 73.106 + * Default: 360 73.107 + */ 73.108 +#define AL_CONE_INNER_ANGLE 0x1001 73.109 + 73.110 +/** 73.111 + * Directional source, outer cone angle, in degrees. 73.112 + * Range: [0-360] 73.113 + * Default: 360 73.114 + */ 73.115 +#define AL_CONE_OUTER_ANGLE 0x1002 73.116 + 73.117 +/** 73.118 + * Specify the pitch to be applied at source. 73.119 + * Range: [0.5-2.0] 73.120 + * Default: 1.0 73.121 + */ 73.122 +#define AL_PITCH 0x1003 73.123 + 73.124 +/** 73.125 + * Specify the current location in three dimensional space. 73.126 + * OpenAL, like OpenGL, uses a right handed coordinate system, 73.127 + * where in a frontal default view X (thumb) points right, 73.128 + * Y points up (index finger), and Z points towards the 73.129 + * viewer/camera (middle finger). 73.130 + * To switch from a left handed coordinate system, flip the 73.131 + * sign on the Z coordinate. 73.132 + * Listener position is always in the world coordinate system. 73.133 + */ 73.134 +#define AL_POSITION 0x1004 73.135 + 73.136 +/** Specify the current direction. */ 73.137 +#define AL_DIRECTION 0x1005 73.138 + 73.139 +/** Specify the current velocity in three dimensional space. */ 73.140 +#define AL_VELOCITY 0x1006 73.141 + 73.142 +/** 73.143 + * Indicate whether source is looping. 73.144 + * Type: ALboolean? 73.145 + * Range: [AL_TRUE, AL_FALSE] 73.146 + * Default: FALSE. 73.147 + */ 73.148 +#define AL_LOOPING 0x1007 73.149 + 73.150 +/** 73.151 + * Indicate the buffer to provide sound samples. 73.152 + * Type: ALuint. 73.153 + * Range: any valid Buffer id. 73.154 + */ 73.155 +#define AL_BUFFER 0x1009 73.156 + 73.157 +/** 73.158 + * Indicate the gain (volume amplification) applied. 73.159 + * Type: ALfloat. 73.160 + * Range: ]0.0- ] 73.161 + * A value of 1.0 means un-attenuated/unchanged. 73.162 + * Each division by 2 equals an attenuation of -6dB. 73.163 + * Each multiplicaton with 2 equals an amplification of +6dB. 73.164 + * A value of 0.0 is meaningless with respect to a logarithmic 73.165 + * scale; it is interpreted as zero volume - the channel 73.166 + * is effectively disabled. 73.167 + */ 73.168 +#define AL_GAIN 0x100A 73.169 + 73.170 +/* 73.171 + * Indicate minimum source attenuation 73.172 + * Type: ALfloat 73.173 + * Range: [0.0 - 1.0] 73.174 + * 73.175 + * Logarthmic 73.176 + */ 73.177 +#define AL_MIN_GAIN 0x100D 73.178 + 73.179 +/** 73.180 + * Indicate maximum source attenuation 73.181 + * Type: ALfloat 73.182 + * Range: [0.0 - 1.0] 73.183 + * 73.184 + * Logarthmic 73.185 + */ 73.186 +#define AL_MAX_GAIN 0x100E 73.187 + 73.188 +/** 73.189 + * Indicate listener orientation. 73.190 + * 73.191 + * at/up 73.192 + */ 73.193 +#define AL_ORIENTATION 0x100F 73.194 + 73.195 +/** 73.196 + * Source state information. 73.197 + */ 73.198 +#define AL_SOURCE_STATE 0x1010 73.199 +#define AL_INITIAL 0x1011 73.200 +#define AL_PLAYING 0x1012 73.201 +#define AL_PAUSED 0x1013 73.202 +#define AL_STOPPED 0x1014 73.203 + 73.204 +/** 73.205 + * Buffer Queue params 73.206 + */ 73.207 +#define AL_BUFFERS_QUEUED 0x1015 73.208 +#define AL_BUFFERS_PROCESSED 0x1016 73.209 + 73.210 +/** 73.211 + * Source buffer position information 73.212 + */ 73.213 +#define AL_SEC_OFFSET 0x1024 73.214 +#define AL_SAMPLE_OFFSET 0x1025 73.215 +#define AL_BYTE_OFFSET 0x1026 73.216 + 73.217 +/* 73.218 + * Source type (Static, Streaming or undetermined) 73.219 + * Source is Static if a Buffer has been attached using AL_BUFFER 73.220 + * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers 73.221 + * Source is undetermined when it has the NULL buffer attached 73.222 + */ 73.223 +#define AL_SOURCE_TYPE 0x1027 73.224 +#define AL_STATIC 0x1028 73.225 +#define AL_STREAMING 0x1029 73.226 +#define AL_UNDETERMINED 0x1030 73.227 + 73.228 +/** Sound samples: format specifier. */ 73.229 +#define AL_FORMAT_MONO8 0x1100 73.230 +#define AL_FORMAT_MONO16 0x1101 73.231 +#define AL_FORMAT_STEREO8 0x1102 73.232 +#define AL_FORMAT_STEREO16 0x1103 73.233 + 73.234 +/** 73.235 + * source specific reference distance 73.236 + * Type: ALfloat 73.237 + * Range: 0.0 - +inf 73.238 + * 73.239 + * At 0.0, no distance attenuation occurs. Default is 73.240 + * 1.0. 73.241 + */ 73.242 +#define AL_REFERENCE_DISTANCE 0x1020 73.243 + 73.244 +/** 73.245 + * source specific rolloff factor 73.246 + * Type: ALfloat 73.247 + * Range: 0.0 - +inf 73.248 + * 73.249 + */ 73.250 +#define AL_ROLLOFF_FACTOR 0x1021 73.251 + 73.252 +/** 73.253 + * Directional source, outer cone gain. 73.254 + * 73.255 + * Default: 0.0 73.256 + * Range: [0.0 - 1.0] 73.257 + * Logarithmic 73.258 + */ 73.259 +#define AL_CONE_OUTER_GAIN 0x1022 73.260 + 73.261 +/** 73.262 + * Indicate distance above which sources are not 73.263 + * attenuated using the inverse clamped distance model. 73.264 + * 73.265 + * Default: +inf 73.266 + * Type: ALfloat 73.267 + * Range: 0.0 - +inf 73.268 + */ 73.269 +#define AL_MAX_DISTANCE 0x1023 73.270 + 73.271 +/** 73.272 + * Sound samples: frequency, in units of Hertz [Hz]. 73.273 + * This is the number of samples per second. Half of the 73.274 + * sample frequency marks the maximum significant 73.275 + * frequency component. 73.276 + */ 73.277 +#define AL_FREQUENCY 0x2001 73.278 +#define AL_BITS 0x2002 73.279 +#define AL_CHANNELS 0x2003 73.280 +#define AL_SIZE 0x2004 73.281 + 73.282 +/** 73.283 + * Buffer state. 73.284 + * 73.285 + * Not supported for public use (yet). 73.286 + */ 73.287 +#define AL_UNUSED 0x2010 73.288 +#define AL_PENDING 0x2011 73.289 +#define AL_PROCESSED 0x2012 73.290 + 73.291 + 73.292 +/** Errors: No Error. */ 73.293 +#define AL_NO_ERROR AL_FALSE 73.294 + 73.295 +/** 73.296 + * Invalid Name paramater passed to AL call. 73.297 + */ 73.298 +#define AL_INVALID_NAME 0xA001 73.299 + 73.300 +/** 73.301 + * Invalid parameter passed to AL call. 73.302 + */ 73.303 +#define AL_INVALID_ENUM 0xA002 73.304 + 73.305 +/** 73.306 + * Invalid enum parameter value. 73.307 + */ 73.308 +#define AL_INVALID_VALUE 0xA003 73.309 + 73.310 +/** 73.311 + * Illegal call. 73.312 + */ 73.313 +#define AL_INVALID_OPERATION 0xA004 73.314 + 73.315 + 73.316 +/** 73.317 + * No mojo. 73.318 + */ 73.319 +#define AL_OUT_OF_MEMORY 0xA005 73.320 + 73.321 + 73.322 +/** Context strings: Vendor Name. */ 73.323 +#define AL_VENDOR 0xB001 73.324 +#define AL_VERSION 0xB002 73.325 +#define AL_RENDERER 0xB003 73.326 +#define AL_EXTENSIONS 0xB004 73.327 + 73.328 +/** Global tweakage. */ 73.329 + 73.330 +/** 73.331 + * Doppler scale. Default 1.0 73.332 + */ 73.333 +#define AL_DOPPLER_FACTOR 0xC000 73.334 + 73.335 +/** 73.336 + * Tweaks speed of propagation. 73.337 + */ 73.338 +#define AL_DOPPLER_VELOCITY 0xC001 73.339 + 73.340 +/** 73.341 + * Speed of Sound in units per second 73.342 + */ 73.343 +#define AL_SPEED_OF_SOUND 0xC003 73.344 + 73.345 +/** 73.346 + * Distance models 73.347 + * 73.348 + * used in conjunction with DistanceModel 73.349 + * 73.350 + * implicit: NONE, which disances distance attenuation. 73.351 + */ 73.352 +#define AL_DISTANCE_MODEL 0xD000 73.353 +#define AL_INVERSE_DISTANCE 0xD001 73.354 +#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 73.355 +#define AL_LINEAR_DISTANCE 0xD003 73.356 +#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 73.357 +#define AL_EXPONENT_DISTANCE 0xD005 73.358 +#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 73.359 + 73.360 +/* 73.361 + * Renderer State management 73.362 + */ 73.363 +AL_API void AL_APIENTRY alEnable( ALenum capability ); 73.364 + 73.365 +AL_API void AL_APIENTRY alDisable( ALenum capability ); 73.366 + 73.367 +AL_API ALboolean AL_APIENTRY alIsEnabled( ALenum capability ); 73.368 + 73.369 + 73.370 +/* 73.371 + * State retrieval 73.372 + */ 73.373 +AL_API const ALchar* AL_APIENTRY alGetString( ALenum param ); 73.374 + 73.375 +AL_API void AL_APIENTRY alGetBooleanv( ALenum param, ALboolean* data ); 73.376 + 73.377 +AL_API void AL_APIENTRY alGetIntegerv( ALenum param, ALint* data ); 73.378 + 73.379 +AL_API void AL_APIENTRY alGetFloatv( ALenum param, ALfloat* data ); 73.380 + 73.381 +AL_API void AL_APIENTRY alGetDoublev( ALenum param, ALdouble* data ); 73.382 + 73.383 +AL_API ALboolean AL_APIENTRY alGetBoolean( ALenum param ); 73.384 + 73.385 +AL_API ALint AL_APIENTRY alGetInteger( ALenum param ); 73.386 + 73.387 +AL_API ALfloat AL_APIENTRY alGetFloat( ALenum param ); 73.388 + 73.389 +AL_API ALdouble AL_APIENTRY alGetDouble( ALenum param ); 73.390 + 73.391 + 73.392 +/* 73.393 + * Error support. 73.394 + * Obtain the most recent error generated in the AL state machine. 73.395 + */ 73.396 +AL_API ALenum AL_APIENTRY alGetError( void ); 73.397 + 73.398 + 73.399 +/* 73.400 + * Extension support. 73.401 + * Query for the presence of an extension, and obtain any appropriate 73.402 + * function pointers and enum values. 73.403 + */ 73.404 +AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname ); 73.405 + 73.406 +AL_API void* AL_APIENTRY alGetProcAddress( const ALchar* fname ); 73.407 + 73.408 +AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename ); 73.409 + 73.410 + 73.411 +/* 73.412 + * LISTENER 73.413 + * Listener represents the location and orientation of the 73.414 + * 'user' in 3D-space. 73.415 + * 73.416 + * Properties include: - 73.417 + * 73.418 + * Gain AL_GAIN ALfloat 73.419 + * Position AL_POSITION ALfloat[3] 73.420 + * Velocity AL_VELOCITY ALfloat[3] 73.421 + * Orientation AL_ORIENTATION ALfloat[6] (Forward then Up vectors) 73.422 +*/ 73.423 + 73.424 +/* 73.425 + * Set Listener parameters 73.426 + */ 73.427 +AL_API void AL_APIENTRY alListenerf( ALenum param, ALfloat value ); 73.428 + 73.429 +AL_API void AL_APIENTRY alListener3f( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); 73.430 + 73.431 +AL_API void AL_APIENTRY alListenerfv( ALenum param, const ALfloat* values ); 73.432 + 73.433 +AL_API void AL_APIENTRY alListeneri( ALenum param, ALint value ); 73.434 + 73.435 +AL_API void AL_APIENTRY alListener3i( ALenum param, ALint value1, ALint value2, ALint value3 ); 73.436 + 73.437 +AL_API void AL_APIENTRY alListeneriv( ALenum param, const ALint* values ); 73.438 + 73.439 +/* 73.440 + * Get Listener parameters 73.441 + */ 73.442 +AL_API void AL_APIENTRY alGetListenerf( ALenum param, ALfloat* value ); 73.443 + 73.444 +AL_API void AL_APIENTRY alGetListener3f( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); 73.445 + 73.446 +AL_API void AL_APIENTRY alGetListenerfv( ALenum param, ALfloat* values ); 73.447 + 73.448 +AL_API void AL_APIENTRY alGetListeneri( ALenum param, ALint* value ); 73.449 + 73.450 +AL_API void AL_APIENTRY alGetListener3i( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); 73.451 + 73.452 +AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values ); 73.453 + 73.454 + 73.455 +/** 73.456 + * SOURCE 73.457 + * Sources represent individual sound objects in 3D-space. 73.458 + * Sources take the PCM data provided in the specified Buffer, 73.459 + * apply Source-specific modifications, and then 73.460 + * submit them to be mixed according to spatial arrangement etc. 73.461 + * 73.462 + * Properties include: - 73.463 + * 73.464 + * Gain AL_GAIN ALfloat 73.465 + * Min Gain AL_MIN_GAIN ALfloat 73.466 + * Max Gain AL_MAX_GAIN ALfloat 73.467 + * Position AL_POSITION ALfloat[3] 73.468 + * Velocity AL_VELOCITY ALfloat[3] 73.469 + * Direction AL_DIRECTION ALfloat[3] 73.470 + * Head Relative Mode AL_SOURCE_RELATIVE ALint (AL_TRUE or AL_FALSE) 73.471 + * Reference Distance AL_REFERENCE_DISTANCE ALfloat 73.472 + * Max Distance AL_MAX_DISTANCE ALfloat 73.473 + * RollOff Factor AL_ROLLOFF_FACTOR ALfloat 73.474 + * Inner Angle AL_CONE_INNER_ANGLE ALint or ALfloat 73.475 + * Outer Angle AL_CONE_OUTER_ANGLE ALint or ALfloat 73.476 + * Cone Outer Gain AL_CONE_OUTER_GAIN ALint or ALfloat 73.477 + * Pitch AL_PITCH ALfloat 73.478 + * Looping AL_LOOPING ALint (AL_TRUE or AL_FALSE) 73.479 + * MS Offset AL_MSEC_OFFSET ALint or ALfloat 73.480 + * Byte Offset AL_BYTE_OFFSET ALint or ALfloat 73.481 + * Sample Offset AL_SAMPLE_OFFSET ALint or ALfloat 73.482 + * Attached Buffer AL_BUFFER ALint 73.483 + * State (Query only) AL_SOURCE_STATE ALint 73.484 + * Buffers Queued (Query only) AL_BUFFERS_QUEUED ALint 73.485 + * Buffers Processed (Query only) AL_BUFFERS_PROCESSED ALint 73.486 + */ 73.487 + 73.488 +/* Create Source objects */ 73.489 +AL_API void AL_APIENTRY alGenSources( ALsizei n, ALuint* sources ); 73.490 + 73.491 +/* Delete Source objects */ 73.492 +AL_API void AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sources ); 73.493 + 73.494 +/* Verify a handle is a valid Source */ 73.495 +AL_API ALboolean AL_APIENTRY alIsSource( ALuint sid ); 73.496 + 73.497 +/* 73.498 + * Set Source parameters 73.499 + */ 73.500 +AL_API void AL_APIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value ); 73.501 + 73.502 +AL_API void AL_APIENTRY alSource3f( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); 73.503 + 73.504 +AL_API void AL_APIENTRY alSourcefv( ALuint sid, ALenum param, const ALfloat* values ); 73.505 + 73.506 +AL_API void AL_APIENTRY alSourcei( ALuint sid, ALenum param, ALint value ); 73.507 + 73.508 +AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); 73.509 + 73.510 +AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum param, const ALint* values ); 73.511 + 73.512 +/* 73.513 + * Get Source parameters 73.514 + */ 73.515 +AL_API void AL_APIENTRY alGetSourcef( ALuint sid, ALenum param, ALfloat* value ); 73.516 + 73.517 +AL_API void AL_APIENTRY alGetSource3f( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); 73.518 + 73.519 +AL_API void AL_APIENTRY alGetSourcefv( ALuint sid, ALenum param, ALfloat* values ); 73.520 + 73.521 +AL_API void AL_APIENTRY alGetSourcei( ALuint sid, ALenum param, ALint* value ); 73.522 + 73.523 +AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); 73.524 + 73.525 +AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values ); 73.526 + 73.527 + 73.528 +/* 73.529 + * Source vector based playback calls 73.530 + */ 73.531 + 73.532 +/* Play, replay, or resume (if paused) a list of Sources */ 73.533 +AL_API void AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids ); 73.534 + 73.535 +/* Stop a list of Sources */ 73.536 +AL_API void AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids ); 73.537 + 73.538 +/* Rewind a list of Sources */ 73.539 +AL_API void AL_APIENTRY alSourceRewindv( ALsizei ns, const ALuint *sids ); 73.540 + 73.541 +/* Pause a list of Sources */ 73.542 +AL_API void AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids ); 73.543 + 73.544 +/* 73.545 + * Source based playback calls 73.546 + */ 73.547 + 73.548 +/* Play, replay, or resume a Source */ 73.549 +AL_API void AL_APIENTRY alSourcePlay( ALuint sid ); 73.550 + 73.551 +/* Stop a Source */ 73.552 +AL_API void AL_APIENTRY alSourceStop( ALuint sid ); 73.553 + 73.554 +/* Rewind a Source (set playback postiton to beginning) */ 73.555 +AL_API void AL_APIENTRY alSourceRewind( ALuint sid ); 73.556 + 73.557 +/* Pause a Source */ 73.558 +AL_API void AL_APIENTRY alSourcePause( ALuint sid ); 73.559 + 73.560 +/* 73.561 + * Source Queuing 73.562 + */ 73.563 +AL_API void AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint *bids ); 73.564 + 73.565 +AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids ); 73.566 + 73.567 + 73.568 +/** 73.569 + * BUFFER 73.570 + * Buffer objects are storage space for sample data. 73.571 + * Buffers are referred to by Sources. One Buffer can be used 73.572 + * by multiple Sources. 73.573 + * 73.574 + * Properties include: - 73.575 + * 73.576 + * Frequency (Query only) AL_FREQUENCY ALint 73.577 + * Size (Query only) AL_SIZE ALint 73.578 + * Bits (Query only) AL_BITS ALint 73.579 + * Channels (Query only) AL_CHANNELS ALint 73.580 + */ 73.581 + 73.582 +/* Create Buffer objects */ 73.583 +AL_API void AL_APIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); 73.584 + 73.585 +/* Delete Buffer objects */ 73.586 +AL_API void AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* buffers ); 73.587 + 73.588 +/* Verify a handle is a valid Buffer */ 73.589 +AL_API ALboolean AL_APIENTRY alIsBuffer( ALuint bid ); 73.590 + 73.591 +/* Specify the data to be copied into a buffer */ 73.592 +AL_API void AL_APIENTRY alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); 73.593 + 73.594 +/* 73.595 + * Set Buffer parameters 73.596 + */ 73.597 +AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum param, ALfloat value ); 73.598 + 73.599 +AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); 73.600 + 73.601 +AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum param, const ALfloat* values ); 73.602 + 73.603 +AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum param, ALint value ); 73.604 + 73.605 +AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); 73.606 + 73.607 +AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum param, const ALint* values ); 73.608 + 73.609 +/* 73.610 + * Get Buffer parameters 73.611 + */ 73.612 +AL_API void AL_APIENTRY alGetBufferf( ALuint bid, ALenum param, ALfloat* value ); 73.613 + 73.614 +AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); 73.615 + 73.616 +AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum param, ALfloat* values ); 73.617 + 73.618 +AL_API void AL_APIENTRY alGetBufferi( ALuint bid, ALenum param, ALint* value ); 73.619 + 73.620 +AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); 73.621 + 73.622 +AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum param, ALint* values ); 73.623 + 73.624 + 73.625 +/* 73.626 + * Global Parameters 73.627 + */ 73.628 +AL_API void AL_APIENTRY alDopplerFactor( ALfloat value ); 73.629 + 73.630 +AL_API void AL_APIENTRY alDopplerVelocity( ALfloat value ); 73.631 + 73.632 +AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value ); 73.633 + 73.634 +AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel ); 73.635 + 73.636 +/* 73.637 + * Pointer-to-function types, useful for dynamically getting AL entry points. 73.638 + */ 73.639 +typedef void (AL_APIENTRY *LPALENABLE)( ALenum capability ); 73.640 +typedef void (AL_APIENTRY *LPALDISABLE)( ALenum capability ); 73.641 +typedef ALboolean (AL_APIENTRY *LPALISENABLED)( ALenum capability ); 73.642 +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)( ALenum param ); 73.643 +typedef void (AL_APIENTRY *LPALGETBOOLEANV)( ALenum param, ALboolean* data ); 73.644 +typedef void (AL_APIENTRY *LPALGETINTEGERV)( ALenum param, ALint* data ); 73.645 +typedef void (AL_APIENTRY *LPALGETFLOATV)( ALenum param, ALfloat* data ); 73.646 +typedef void (AL_APIENTRY *LPALGETDOUBLEV)( ALenum param, ALdouble* data ); 73.647 +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)( ALenum param ); 73.648 +typedef ALint (AL_APIENTRY *LPALGETINTEGER)( ALenum param ); 73.649 +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)( ALenum param ); 73.650 +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)( ALenum param ); 73.651 +typedef ALenum (AL_APIENTRY *LPALGETERROR)( void ); 73.652 +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar* extname ); 73.653 +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)( const ALchar* fname ); 73.654 +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)( const ALchar* ename ); 73.655 +typedef void (AL_APIENTRY *LPALLISTENERF)( ALenum param, ALfloat value ); 73.656 +typedef void (AL_APIENTRY *LPALLISTENER3F)( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); 73.657 +typedef void (AL_APIENTRY *LPALLISTENERFV)( ALenum param, const ALfloat* values ); 73.658 +typedef void (AL_APIENTRY *LPALLISTENERI)( ALenum param, ALint value ); 73.659 +typedef void (AL_APIENTRY *LPALLISTENER3I)( ALenum param, ALint value1, ALint value2, ALint value3 ); 73.660 +typedef void (AL_APIENTRY *LPALLISTENERIV)( ALenum param, const ALint* values ); 73.661 +typedef void (AL_APIENTRY *LPALGETLISTENERF)( ALenum param, ALfloat* value ); 73.662 +typedef void (AL_APIENTRY *LPALGETLISTENER3F)( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); 73.663 +typedef void (AL_APIENTRY *LPALGETLISTENERFV)( ALenum param, ALfloat* values ); 73.664 +typedef void (AL_APIENTRY *LPALGETLISTENERI)( ALenum param, ALint* value ); 73.665 +typedef void (AL_APIENTRY *LPALGETLISTENER3I)( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); 73.666 +typedef void (AL_APIENTRY *LPALGETLISTENERIV)( ALenum param, ALint* values ); 73.667 +typedef void (AL_APIENTRY *LPALGENSOURCES)( ALsizei n, ALuint* sources ); 73.668 +typedef void (AL_APIENTRY *LPALDELETESOURCES)( ALsizei n, const ALuint* sources ); 73.669 +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)( ALuint sid ); 73.670 +typedef void (AL_APIENTRY *LPALSOURCEF)( ALuint sid, ALenum param, ALfloat value); 73.671 +typedef void (AL_APIENTRY *LPALSOURCE3F)( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); 73.672 +typedef void (AL_APIENTRY *LPALSOURCEFV)( ALuint sid, ALenum param, const ALfloat* values ); 73.673 +typedef void (AL_APIENTRY *LPALSOURCEI)( ALuint sid, ALenum param, ALint value); 73.674 +typedef void (AL_APIENTRY *LPALSOURCE3I)( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); 73.675 +typedef void (AL_APIENTRY *LPALSOURCEIV)( ALuint sid, ALenum param, const ALint* values ); 73.676 +typedef void (AL_APIENTRY *LPALGETSOURCEF)( ALuint sid, ALenum param, ALfloat* value ); 73.677 +typedef void (AL_APIENTRY *LPALGETSOURCE3F)( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); 73.678 +typedef void (AL_APIENTRY *LPALGETSOURCEFV)( ALuint sid, ALenum param, ALfloat* values ); 73.679 +typedef void (AL_APIENTRY *LPALGETSOURCEI)( ALuint sid, ALenum param, ALint* value ); 73.680 +typedef void (AL_APIENTRY *LPALGETSOURCE3I)( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); 73.681 +typedef void (AL_APIENTRY *LPALGETSOURCEIV)( ALuint sid, ALenum param, ALint* values ); 73.682 +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)( ALsizei ns, const ALuint *sids ); 73.683 +typedef void (AL_APIENTRY *LPALSOURCESTOPV)( ALsizei ns, const ALuint *sids ); 73.684 +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)( ALsizei ns, const ALuint *sids ); 73.685 +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)( ALsizei ns, const ALuint *sids ); 73.686 +typedef void (AL_APIENTRY *LPALSOURCEPLAY)( ALuint sid ); 73.687 +typedef void (AL_APIENTRY *LPALSOURCESTOP)( ALuint sid ); 73.688 +typedef void (AL_APIENTRY *LPALSOURCEREWIND)( ALuint sid ); 73.689 +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)( ALuint sid ); 73.690 +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, const ALuint *bids ); 73.691 +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, ALuint *bids ); 73.692 +typedef void (AL_APIENTRY *LPALGENBUFFERS)( ALsizei n, ALuint* buffers ); 73.693 +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)( ALsizei n, const ALuint* buffers ); 73.694 +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)( ALuint bid ); 73.695 +typedef void (AL_APIENTRY *LPALBUFFERDATA)( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); 73.696 +typedef void (AL_APIENTRY *LPALBUFFERF)( ALuint bid, ALenum param, ALfloat value); 73.697 +typedef void (AL_APIENTRY *LPALBUFFER3F)( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); 73.698 +typedef void (AL_APIENTRY *LPALBUFFERFV)( ALuint bid, ALenum param, const ALfloat* values ); 73.699 +typedef void (AL_APIENTRY *LPALBUFFERI)( ALuint bid, ALenum param, ALint value); 73.700 +typedef void (AL_APIENTRY *LPALBUFFER3I)( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); 73.701 +typedef void (AL_APIENTRY *LPALBUFFERIV)( ALuint bid, ALenum param, const ALint* values ); 73.702 +typedef void (AL_APIENTRY *LPALGETBUFFERF)( ALuint bid, ALenum param, ALfloat* value ); 73.703 +typedef void (AL_APIENTRY *LPALGETBUFFER3F)( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); 73.704 +typedef void (AL_APIENTRY *LPALGETBUFFERFV)( ALuint bid, ALenum param, ALfloat* values ); 73.705 +typedef void (AL_APIENTRY *LPALGETBUFFERI)( ALuint bid, ALenum param, ALint* value ); 73.706 +typedef void (AL_APIENTRY *LPALGETBUFFER3I)( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); 73.707 +typedef void (AL_APIENTRY *LPALGETBUFFERIV)( ALuint bid, ALenum param, ALint* values ); 73.708 +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)( ALfloat value ); 73.709 +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)( ALfloat value ); 73.710 +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)( ALfloat value ); 73.711 +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)( ALenum distanceModel ); 73.712 + 73.713 +#if defined(TARGET_OS_MAC) && TARGET_OS_MAC 73.714 + #pragma export off 73.715 +#endif 73.716 + 73.717 +#if defined(__cplusplus) 73.718 +} /* extern "C" */ 73.719 +#endif 73.720 + 73.721 +#endif /* AL_AL_H */
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 74.2 +++ b/include/AL/alc.h Tue Oct 25 13:02:31 2011 -0700 74.3 @@ -0,0 +1,280 @@ 74.4 +#ifndef AL_ALC_H 74.5 +#define AL_ALC_H 74.6 + 74.7 +#if defined(__cplusplus) 74.8 +extern "C" { 74.9 +#endif 74.10 + 74.11 +#ifndef ALC_API 74.12 + #if defined(AL_LIBTYPE_STATIC) 74.13 + #define ALC_API 74.14 + #elif defined(_WIN32) 74.15 + #define ALC_API __declspec(dllimport) 74.16 + #else 74.17 + #define ALC_API extern 74.18 + #endif 74.19 +#endif 74.20 + 74.21 +#if defined(_WIN32) 74.22 + #define ALC_APIENTRY __cdecl 74.23 +#else 74.24 + #define ALC_APIENTRY 74.25 +#endif 74.26 + 74.27 +#if defined(TARGET_OS_MAC) && TARGET_OS_MAC 74.28 + #pragma export on 74.29 +#endif 74.30 + 74.31 +/* 74.32 + * The ALCAPI, ALCAPIENTRY, and ALC_INVALID macros are deprecated, but are 74.33 + * included for applications porting code from AL 1.0 74.34 + */ 74.35 +#define ALCAPI ALC_API 74.36 +#define ALCAPIENTRY ALC_APIENTRY 74.37 +#define ALC_INVALID 0 74.38 + 74.39 + 74.40 +#define ALC_VERSION_0_1 1 74.41 + 74.42 +typedef struct ALCdevice_struct ALCdevice; 74.43 +typedef struct ALCcontext_struct ALCcontext; 74.44 + 74.45 + 74.46 +/** 8-bit boolean */ 74.47 +typedef char ALCboolean; 74.48 + 74.49 +/** character */ 74.50 +typedef char ALCchar; 74.51 + 74.52 +/** signed 8-bit 2's complement integer */ 74.53 +typedef signed char ALCbyte; 74.54 + 74.55 +/** unsigned 8-bit integer */ 74.56 +typedef unsigned char ALCubyte; 74.57 + 74.58 +/** signed 16-bit 2's complement integer */ 74.59 +typedef short ALCshort; 74.60 + 74.61 +/** unsigned 16-bit integer */ 74.62 +typedef unsigned short ALCushort; 74.63 + 74.64 +/** signed 32-bit 2's complement integer */ 74.65 +typedef int ALCint; 74.66 + 74.67 +/** unsigned 32-bit integer */ 74.68 +typedef unsigned int ALCuint; 74.69 + 74.70 +/** non-negative 32-bit binary integer size */ 74.71 +typedef int ALCsizei; 74.72 + 74.73 +/** enumerated 32-bit value */ 74.74 +typedef int ALCenum; 74.75 + 74.76 +/** 32-bit IEEE754 floating-point */ 74.77 +typedef float ALCfloat; 74.78 + 74.79 +/** 64-bit IEEE754 floating-point */ 74.80 +typedef double ALCdouble; 74.81 + 74.82 +/** void type (for opaque pointers only) */ 74.83 +typedef void ALCvoid; 74.84 + 74.85 + 74.86 +/* Enumerant values begin at column 50. No tabs. */ 74.87 + 74.88 +/* Boolean False. */ 74.89 +#define ALC_FALSE 0 74.90 + 74.91 +/* Boolean True. */ 74.92 +#define ALC_TRUE 1 74.93 + 74.94 +/** 74.95 + * followed by <int> Hz 74.96 + */ 74.97 +#define ALC_FREQUENCY 0x1007 74.98 + 74.99 +/** 74.100 + * followed by <int> Hz 74.101 + */ 74.102 +#define ALC_REFRESH 0x1008 74.103 + 74.104 +/** 74.105 + * followed by AL_TRUE, AL_FALSE 74.106 + */ 74.107 +#define ALC_SYNC 0x1009 74.108 + 74.109 +/** 74.110 + * followed by <int> Num of requested Mono (3D) Sources 74.111 + */ 74.112 +#define ALC_MONO_SOURCES 0x1010 74.113 + 74.114 +/** 74.115 + * followed by <int> Num of requested Stereo Sources 74.116 + */ 74.117 +#define ALC_STEREO_SOURCES 0x1011 74.118 + 74.119 +/** 74.120 + * errors 74.121 + */ 74.122 + 74.123 +/** 74.124 + * No error 74.125 + */ 74.126 +#define ALC_NO_ERROR ALC_FALSE 74.127 + 74.128 +/** 74.129 + * No device 74.130 + */ 74.131 +#define ALC_INVALID_DEVICE 0xA001 74.132 + 74.133 +/** 74.134 + * invalid context ID 74.135 + */ 74.136 +#define ALC_INVALID_CONTEXT 0xA002 74.137 + 74.138 +/** 74.139 + * bad enum 74.140 + */ 74.141 +#define ALC_INVALID_ENUM 0xA003 74.142 + 74.143 +/** 74.144 + * bad value 74.145 + */ 74.146 +#define ALC_INVALID_VALUE 0xA004 74.147 + 74.148 +/** 74.149 + * Out of memory. 74.150 + */ 74.151 +#define ALC_OUT_OF_MEMORY 0xA005 74.152 + 74.153 + 74.154 +/** 74.155 + * The Specifier string for default device 74.156 + */ 74.157 +#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 74.158 +#define ALC_DEVICE_SPECIFIER 0x1005 74.159 +#define ALC_EXTENSIONS 0x1006 74.160 + 74.161 +#define ALC_MAJOR_VERSION 0x1000 74.162 +#define ALC_MINOR_VERSION 0x1001 74.163 + 74.164 +#define ALC_ATTRIBUTES_SIZE 0x1002 74.165 +#define ALC_ALL_ATTRIBUTES 0x1003 74.166 + 74.167 + 74.168 +/** 74.169 + * Capture extension 74.170 + */ 74.171 +#define ALC_EXT_CAPTURE 1 74.172 +#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 74.173 +#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 74.174 +#define ALC_CAPTURE_SAMPLES 0x312 74.175 + 74.176 + 74.177 +/** 74.178 + * ALC_ENUMERATE_ALL_EXT enums 74.179 + */ 74.180 +#define ALC_ENUMERATE_ALL_EXT 1 74.181 +#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 74.182 +#define ALC_ALL_DEVICES_SPECIFIER 0x1013 74.183 + 74.184 + 74.185 +/* 74.186 + * Context Management 74.187 + */ 74.188 +ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist ); 74.189 + 74.190 +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context ); 74.191 + 74.192 +ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context ); 74.193 + 74.194 +ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context ); 74.195 + 74.196 +ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context ); 74.197 + 74.198 +ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( void ); 74.199 + 74.200 +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context ); 74.201 + 74.202 + 74.203 +/* 74.204 + * Device Management 74.205 + */ 74.206 +ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename ); 74.207 + 74.208 +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device ); 74.209 + 74.210 + 74.211 +/* 74.212 + * Error support. 74.213 + * Obtain the most recent Context error 74.214 + */ 74.215 +ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device ); 74.216 + 74.217 + 74.218 +/* 74.219 + * Extension support. 74.220 + * Query for the presence of an extension, and obtain any appropriate 74.221 + * function pointers and enum values. 74.222 + */ 74.223 +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname ); 74.224 + 74.225 +ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname ); 74.226 + 74.227 +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname ); 74.228 + 74.229 + 74.230 +/* 74.231 + * Query functions 74.232 + */ 74.233 +ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param ); 74.234 + 74.235 +ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data ); 74.236 + 74.237 + 74.238 +/* 74.239 + * Capture functions 74.240 + */ 74.241 +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ); 74.242 + 74.243 +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device ); 74.244 + 74.245 +ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device ); 74.246 + 74.247 +ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device ); 74.248 + 74.249 +ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); 74.250 + 74.251 +/* 74.252 + * Pointer-to-function types, useful for dynamically getting ALC entry points. 74.253 + */ 74.254 +typedef ALCcontext * (ALC_APIENTRY *LPALCCREATECONTEXT) (ALCdevice *device, const ALCint *attrlist); 74.255 +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)( ALCcontext *context ); 74.256 +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)( ALCcontext *context ); 74.257 +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)( ALCcontext *context ); 74.258 +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)( ALCcontext *context ); 74.259 +typedef ALCcontext * (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)( void ); 74.260 +typedef ALCdevice * (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)( ALCcontext *context ); 74.261 +typedef ALCdevice * (ALC_APIENTRY *LPALCOPENDEVICE)( const ALCchar *devicename ); 74.262 +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)( ALCdevice *device ); 74.263 +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)( ALCdevice *device ); 74.264 +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)( ALCdevice *device, const ALCchar *extname ); 74.265 +typedef void * (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname ); 74.266 +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname ); 74.267 +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)( ALCdevice *device, ALCenum param ); 74.268 +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ); 74.269 +typedef ALCdevice * (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ); 74.270 +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)( ALCdevice *device ); 74.271 +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)( ALCdevice *device ); 74.272 +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)( ALCdevice *device ); 74.273 +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); 74.274 + 74.275 +#if defined(TARGET_OS_MAC) && TARGET_OS_MAC 74.276 + #pragma export off 74.277 +#endif 74.278 + 74.279 +#if defined(__cplusplus) 74.280 +} 74.281 +#endif 74.282 + 74.283 +#endif /* AL_ALC_H */
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 75.2 +++ b/include/AL/alext.h Tue Oct 25 13:02:31 2011 -0700 75.3 @@ -0,0 +1,183 @@ 75.4 +/** 75.5 + * OpenAL cross platform audio library 75.6 + * Copyright (C) 2008 by authors. 75.7 + * This library is free software; you can redistribute it and/or 75.8 + * modify it under the terms of the GNU Library General Public 75.9 + * License as published by the Free Software Foundation; either 75.10 + * version 2 of the License, or (at your option) any later version. 75.11 + * 75.12 + * This library is distributed in the hope that it will be useful, 75.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 75.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 75.15 + * Library General Public License for more details. 75.16 + * 75.17 + * You should have received a copy of the GNU Library General Public 75.18 + * License along with this library; if not, write to the 75.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 75.20 + * Boston, MA 02111-1307, USA. 75.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 75.22 + */ 75.23 + 75.24 +#ifndef AL_ALEXT_H 75.25 +#define AL_ALEXT_H 75.26 + 75.27 +#include <stddef.h> 75.28 + 75.29 +#ifdef __cplusplus 75.30 +extern "C" { 75.31 +#endif 75.32 + 75.33 +#ifndef AL_LOKI_IMA_ADPCM_format 75.34 +#define AL_LOKI_IMA_ADPCM_format 1 75.35 +#define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 75.36 +#define AL_FORMAT_IMA_ADPCM_STEREO16_EXT 0x10001 75.37 +#endif 75.38 + 75.39 +#ifndef AL_LOKI_WAVE_format 75.40 +#define AL_LOKI_WAVE_format 1 75.41 +#define AL_FORMAT_WAVE_EXT 0x10002 75.42 +#endif 75.43 + 75.44 +#ifndef AL_EXT_vorbis 75.45 +#define AL_EXT_vorbis 1 75.46 +#define AL_FORMAT_VORBIS_EXT 0x10003 75.47 +#endif 75.48 + 75.49 +#ifndef AL_LOKI_quadriphonic 75.50 +#define AL_LOKI_quadriphonic 1 75.51 +#define AL_FORMAT_QUAD8_LOKI 0x10004 75.52 +#define AL_FORMAT_QUAD16_LOKI 0x10005 75.53 +#endif 75.54 + 75.55 +#ifndef AL_EXT_float32 75.56 +#define AL_EXT_float32 1 75.57 +#define AL_FORMAT_MONO_FLOAT32 0x10010 75.58 +#define AL_FORMAT_STEREO_FLOAT32 0x10011 75.59 +#endif 75.60 + 75.61 +#ifndef AL_EXT_double 75.62 +#define AL_EXT_double 1 75.63 +#define AL_FORMAT_MONO_DOUBLE_EXT 0x10012 75.64 +#define AL_FORMAT_STEREO_DOUBLE_EXT 0x10013 75.65 +#endif 75.66 + 75.67 +#ifndef ALC_LOKI_audio_channel 75.68 +#define ALC_LOKI_audio_channel 1 75.69 +#define ALC_CHAN_MAIN_LOKI 0x500001 75.70 +#define ALC_CHAN_PCM_LOKI 0x500002 75.71 +#define ALC_CHAN_CD_LOKI 0x500003 75.72 +#endif 75.73 + 75.74 +#ifndef AL_EXT_MCFORMATS 75.75 +#define AL_EXT_MCFORMATS 1 75.76 +#define AL_FORMAT_QUAD8 0x1204 75.77 +#define AL_FORMAT_QUAD16 0x1205 75.78 +#define AL_FORMAT_QUAD32 0x1206 75.79 +#define AL_FORMAT_REAR8 0x1207 75.80 +#define AL_FORMAT_REAR16 0x1208 75.81 +#define AL_FORMAT_REAR32 0x1209 75.82 +#define AL_FORMAT_51CHN8 0x120A 75.83 +#define AL_FORMAT_51CHN16 0x120B 75.84 +#define AL_FORMAT_51CHN32 0x120C 75.85 +#define AL_FORMAT_61CHN8 0x120D 75.86 +#define AL_FORMAT_61CHN16 0x120E 75.87 +#define AL_FORMAT_61CHN32 0x120F 75.88 +#define AL_FORMAT_71CHN8 0x1210 75.89 +#define AL_FORMAT_71CHN16 0x1211 75.90 +#define AL_FORMAT_71CHN32 0x1212 75.91 +#endif 75.92 + 75.93 +#ifndef AL_EXT_MULAW_MCFORMATS 75.94 +#define AL_EXT_MULAW_MCFORMATS 1 75.95 +#define AL_FORMAT_MONO_MULAW 0x10014 75.96 +#define AL_FORMAT_STEREO_MULAW 0x10015 75.97 +#define AL_FORMAT_QUAD_MULAW 0x10021 75.98 +#define AL_FORMAT_REAR_MULAW 0x10022 75.99 +#define AL_FORMAT_51CHN_MULAW 0x10023 75.100 +#define AL_FORMAT_61CHN_MULAW 0x10024 75.101 +#define AL_FORMAT_71CHN_MULAW 0x10025 75.102 +#endif 75.103 + 75.104 +#ifndef AL_EXT_IMA4 75.105 +#define AL_EXT_IMA4 1 75.106 +#define AL_FORMAT_MONO_IMA4 0x1300 75.107 +#define AL_FORMAT_STEREO_IMA4 0x1301 75.108 +#endif 75.109 + 75.110 +#ifndef AL_EXT_STATIC_BUFFER 75.111 +#define AL_EXT_STATIC_BUFFER 1 75.112 +typedef ALvoid (AL_APIENTRY*PFNALBUFFERDATASTATICPROC)(const ALint,ALenum,ALvoid*,ALsizei,ALsizei); 75.113 +#ifdef AL_ALEXT_PROTOTYPES 75.114 +AL_API ALvoid AL_APIENTRY alBufferDataStatic(const ALint buffer, ALenum format, ALvoid *data, ALsizei len, ALsizei freq); 75.115 +#endif 75.116 +#endif 75.117 + 75.118 +#ifndef ALC_EXT_EFX 75.119 +#define ALC_EXT_EFX 1 75.120 +#include "efx.h" 75.121 +#endif 75.122 + 75.123 +#ifndef ALC_EXT_disconnect 75.124 +#define ALC_EXT_disconnect 1 75.125 +#define ALC_CONNECTED 0x313 75.126 +#endif 75.127 + 75.128 +#ifndef ALC_EXT_thread_local_context 75.129 +#define ALC_EXT_thread_local_context 1 75.130 +typedef ALCboolean (ALC_APIENTRY*PFNALCSETTHREADCONTEXTPROC)(ALCcontext *context); 75.131 +typedef ALCcontext* (ALC_APIENTRY*PFNALCGETTHREADCONTEXTPROC)(void); 75.132 +#ifdef AL_ALEXT_PROTOTYPES 75.133 +ALC_API ALCboolean ALC_APIENTRY alcSetThreadContext(ALCcontext *context); 75.134 +ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void); 75.135 +#endif 75.136 +#endif 75.137 + 75.138 +#ifndef AL_EXT_source_distance_model 75.139 +#define AL_EXT_source_distance_model 1 75.140 +#define AL_SOURCE_DISTANCE_MODEL 0x200 75.141 +#endif 75.142 + 75.143 +#ifndef AL_SOFT_buffer_sub_data 75.144 +#define AL_SOFT_buffer_sub_data 1 75.145 +#define AL_BYTE_RW_OFFSETS_SOFT 0x1031 75.146 +#define AL_SAMPLE_RW_OFFSETS_SOFT 0x1032 75.147 +typedef ALvoid (AL_APIENTRY*PFNALBUFFERSUBDATASOFTPROC)(ALuint,ALenum,const ALvoid*,ALsizei,ALsizei); 75.148 +#ifdef AL_ALEXT_PROTOTYPES 75.149 +AL_API ALvoid AL_APIENTRY alBufferSubDataSOFT(ALuint buffer,ALenum format,const ALvoid *data,ALsizei offset,ALsizei length); 75.150 +#endif 75.151 +#endif 75.152 + 75.153 +#ifndef AL_SOFT_loop_points 75.154 +#define AL_SOFT_loop_points 1 75.155 +#define AL_LOOP_POINTS_SOFT 0x2015 75.156 +#endif 75.157 + 75.158 +#ifndef AL_EXT_FOLDBACK 75.159 +#define AL_EXT_FOLDBACK 1 75.160 +#define AL_EXT_FOLDBACK_NAME "AL_EXT_FOLDBACK" 75.161 +#define AL_FOLDBACK_EVENT_BLOCK 0x4112 75.162 +#define AL_FOLDBACK_EVENT_START 0x4111 75.163 +#define AL_FOLDBACK_EVENT_STOP 0x4113 75.164 +#define AL_FOLDBACK_MODE_MONO 0x4101 75.165 +#define AL_FOLDBACK_MODE_STEREO 0x4102 75.166 +typedef void (AL_APIENTRY*LPALFOLDBACKCALLBACK)(ALenum,ALsizei); 75.167 +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTART)(ALenum,ALsizei,ALsizei,ALfloat*,LPALFOLDBACKCALLBACK); 75.168 +typedef void (AL_APIENTRY*LPALREQUESTFOLDBACKSTOP)(void); 75.169 +#ifdef AL_ALEXT_PROTOTYPES 75.170 +AL_API void AL_APIENTRY alRequestFoldbackStart(ALenum mode,ALsizei count,ALsizei length,ALfloat *mem,LPALFOLDBACKCALLBACK callback); 75.171 +AL_API void AL_APIENTRY alRequestFoldbackStop(void); 75.172 +#endif 75.173 +#endif 75.174 + 75.175 +#ifndef ALC_EXT_DEDICATED 75.176 +#define ALC_EXT_DEDICATED 1 75.177 +#define AL_DEDICATED_GAIN 0x0001 75.178 +#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001 75.179 +#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000 75.180 +#endif 75.181 + 75.182 +#ifdef __cplusplus 75.183 +} 75.184 +#endif 75.185 + 75.186 +#endif
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 76.2 +++ b/include/AL/efx-creative.h Tue Oct 25 13:02:31 2011 -0700 76.3 @@ -0,0 +1,3 @@ 76.4 +/* The tokens that would be defined here are already defined in efx.h. This 76.5 + * empty file is here to provide compatibility with Windows-based projects 76.6 + * that would include it. */
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 77.2 +++ b/include/AL/efx.h Tue Oct 25 13:02:31 2011 -0700 77.3 @@ -0,0 +1,758 @@ 77.4 +#ifndef AL_EFX_H 77.5 +#define AL_EFX_H 77.6 + 77.7 + 77.8 +#ifdef __cplusplus 77.9 +extern "C" { 77.10 +#endif 77.11 + 77.12 +#define ALC_EXT_EFX_NAME "ALC_EXT_EFX" 77.13 + 77.14 +#define ALC_EFX_MAJOR_VERSION 0x20001 77.15 +#define ALC_EFX_MINOR_VERSION 0x20002 77.16 +#define ALC_MAX_AUXILIARY_SENDS 0x20003 77.17 + 77.18 + 77.19 +/* Listener properties. */ 77.20 +#define AL_METERS_PER_UNIT 0x20004 77.21 + 77.22 +/* Source properties. */ 77.23 +#define AL_DIRECT_FILTER 0x20005 77.24 +#define AL_AUXILIARY_SEND_FILTER 0x20006 77.25 +#define AL_AIR_ABSORPTION_FACTOR 0x20007 77.26 +#define AL_ROOM_ROLLOFF_FACTOR 0x20008 77.27 +#define AL_CONE_OUTER_GAINHF 0x20009 77.28 +#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A 77.29 +#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B 77.30 +#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C 77.31 + 77.32 + 77.33 +/* Effect properties. */ 77.34 + 77.35 +/* Reverb effect parameters */ 77.36 +#define AL_REVERB_DENSITY 0x0001 77.37 +#define AL_REVERB_DIFFUSION 0x0002 77.38 +#define AL_REVERB_GAIN 0x0003 77.39 +#define AL_REVERB_GAINHF 0x0004 77.40 +#define AL_REVERB_DECAY_TIME 0x0005 77.41 +#define AL_REVERB_DECAY_HFRATIO 0x0006 77.42 +#define AL_REVERB_REFLECTIONS_GAIN 0x0007 77.43 +#define AL_REVERB_REFLECTIONS_DELAY 0x0008 77.44 +#define AL_REVERB_LATE_REVERB_GAIN 0x0009 77.45 +#define AL_REVERB_LATE_REVERB_DELAY 0x000A 77.46 +#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B 77.47 +#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C 77.48 +#define AL_REVERB_DECAY_HFLIMIT 0x000D 77.49 + 77.50 +/* EAX Reverb effect parameters */ 77.51 +#define AL_EAXREVERB_DENSITY 0x0001 77.52 +#define AL_EAXREVERB_DIFFUSION 0x0002 77.53 +#define AL_EAXREVERB_GAIN 0x0003 77.54 +#define AL_EAXREVERB_GAINHF 0x0004 77.55 +#define AL_EAXREVERB_GAINLF 0x0005 77.56 +#define AL_EAXREVERB_DECAY_TIME 0x0006 77.57 +#define AL_EAXREVERB_DECAY_HFRATIO 0x0007 77.58 +#define AL_EAXREVERB_DECAY_LFRATIO 0x0008 77.59 +#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009 77.60 +#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A 77.61 +#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B 77.62 +#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C 77.63 +#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D 77.64 +#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E 77.65 +#define AL_EAXREVERB_ECHO_TIME 0x000F 77.66 +#define AL_EAXREVERB_ECHO_DEPTH 0x0010 77.67 +#define AL_EAXREVERB_MODULATION_TIME 0x0011 77.68 +#define AL_EAXREVERB_MODULATION_DEPTH 0x0012 77.69 +#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013 77.70 +#define AL_EAXREVERB_HFREFERENCE 0x0014 77.71 +#define AL_EAXREVERB_LFREFERENCE 0x0015 77.72 +#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016 77.73 +#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017 77.74 + 77.75 +/* Chorus effect parameters */ 77.76 +#define AL_CHORUS_WAVEFORM 0x0001 77.77 +#define AL_CHORUS_PHASE 0x0002 77.78 +#define AL_CHORUS_RATE 0x0003 77.79 +#define AL_CHORUS_DEPTH 0x0004 77.80 +#define AL_CHORUS_FEEDBACK 0x0005 77.81 +#define AL_CHORUS_DELAY 0x0006 77.82 + 77.83 +/* Distortion effect parameters */ 77.84 +#define AL_DISTORTION_EDGE 0x0001 77.85 +#define AL_DISTORTION_GAIN 0x0002 77.86 +#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003 77.87 +#define AL_DISTORTION_EQCENTER 0x0004 77.88 +#define AL_DISTORTION_EQBANDWIDTH 0x0005 77.89 + 77.90 +/* Echo effect parameters */ 77.91 +#define AL_ECHO_DELAY 0x0001 77.92 +#define AL_ECHO_LRDELAY 0x0002 77.93 +#define AL_ECHO_DAMPING 0x0003 77.94 +#define AL_ECHO_FEEDBACK 0x0004 77.95 +#define AL_ECHO_SPREAD 0x0005 77.96 + 77.97 +/* Flanger effect parameters */ 77.98 +#define AL_FLANGER_WAVEFORM 0x0001 77.99 +#define AL_FLANGER_PHASE 0x0002 77.100 +#define AL_FLANGER_RATE 0x0003 77.101 +#define AL_FLANGER_DEPTH 0x0004 77.102 +#define AL_FLANGER_FEEDBACK 0x0005 77.103 +#define AL_FLANGER_DELAY 0x0006 77.104 + 77.105 +/* Frequency shifter effect parameters */ 77.106 +#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001 77.107 +#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002 77.108 +#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003 77.109 + 77.110 +/* Vocal morpher effect parameters */ 77.111 +#define AL_VOCAL_MORPHER_PHONEMEA 0x0001 77.112 +#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002 77.113 +#define AL_VOCAL_MORPHER_PHONEMEB 0x0003 77.114 +#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004 77.115 +#define AL_VOCAL_MORPHER_WAVEFORM 0x0005 77.116 +#define AL_VOCAL_MORPHER_RATE 0x0006 77.117 + 77.118 +/* Pitchshifter effect parameters */ 77.119 +#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001 77.120 +#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002 77.121 + 77.122 +/* Ringmodulator effect parameters */ 77.123 +#define AL_RING_MODULATOR_FREQUENCY 0x0001 77.124 +#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002 77.125 +#define AL_RING_MODULATOR_WAVEFORM 0x0003 77.126 + 77.127 +/* Autowah effect parameters */ 77.128 +#define AL_AUTOWAH_ATTACK_TIME 0x0001 77.129 +#define AL_AUTOWAH_RELEASE_TIME 0x0002 77.130 +#define AL_AUTOWAH_RESONANCE 0x0003 77.131 +#define AL_AUTOWAH_PEAK_GAIN 0x0004 77.132 + 77.133 +/* Compressor effect parameters */ 77.134 +#define AL_COMPRESSOR_ONOFF 0x0001 77.135 + 77.136 +/* Equalizer effect parameters */ 77.137 +#define AL_EQUALIZER_LOW_GAIN 0x0001 77.138 +#define AL_EQUALIZER_LOW_CUTOFF 0x0002 77.139 +#define AL_EQUALIZER_MID1_GAIN 0x0003 77.140 +#define AL_EQUALIZER_MID1_CENTER 0x0004 77.141 +#define AL_EQUALIZER_MID1_WIDTH 0x0005 77.142 +#define AL_EQUALIZER_MID2_GAIN 0x0006 77.143 +#define AL_EQUALIZER_MID2_CENTER 0x0007 77.144 +#define AL_EQUALIZER_MID2_WIDTH 0x0008 77.145 +#define AL_EQUALIZER_HIGH_GAIN 0x0009 77.146 +#define AL_EQUALIZER_HIGH_CUTOFF 0x000A 77.147 + 77.148 +/* Effect type */ 77.149 +#define AL_EFFECT_FIRST_PARAMETER 0x0000 77.150 +#define AL_EFFECT_LAST_PARAMETER 0x8000 77.151 +#define AL_EFFECT_TYPE 0x8001 77.152 + 77.153 +/* Effect types, used with the AL_EFFECT_TYPE property */ 77.154 +#define AL_EFFECT_NULL 0x0000 77.155 +#define AL_EFFECT_REVERB 0x0001 77.156 +#define AL_EFFECT_CHORUS 0x0002 77.157 +#define AL_EFFECT_DISTORTION 0x0003 77.158 +#define AL_EFFECT_ECHO 0x0004 77.159 +#define AL_EFFECT_FLANGER 0x0005 77.160 +#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 77.161 +#define AL_EFFECT_VOCAL_MORPHER 0x0007 77.162 +#define AL_EFFECT_PITCH_SHIFTER 0x0008 77.163 +#define AL_EFFECT_RING_MODULATOR 0x0009 77.164 +#define AL_EFFECT_AUTOWAH 0x000A 77.165 +#define AL_EFFECT_COMPRESSOR 0x000B 77.166 +#define AL_EFFECT_EQUALIZER 0x000C 77.167 +#define AL_EFFECT_EAXREVERB 0x8000 77.168 + 77.169 +/* Auxiliary Effect Slot properties. */ 77.170 +#define AL_EFFECTSLOT_EFFECT 0x0001 77.171 +#define AL_EFFECTSLOT_GAIN 0x0002 77.172 +#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003 77.173 + 77.174 +/* NULL Auxiliary Slot ID to disable a source send. */ 77.175 +#define AL_EFFECTSLOT_NULL 0x0000 77.176 + 77.177 + 77.178 +/* Filter properties. */ 77.179 + 77.180 +/* Lowpass filter parameters */ 77.181 +#define AL_LOWPASS_GAIN 0x0001 77.182 +#define AL_LOWPASS_GAINHF 0x0002 77.183 + 77.184 +/* Highpass filter parameters */ 77.185 +#define AL_HIGHPASS_GAIN 0x0001 77.186 +#define AL_HIGHPASS_GAINLF 0x0002 77.187 + 77.188 +/* Bandpass filter parameters */ 77.189 +#define AL_BANDPASS_GAIN 0x0001 77.190 +#define AL_BANDPASS_GAINLF 0x0002 77.191 +#define AL_BANDPASS_GAINHF 0x0003 77.192 + 77.193 +/* Filter type */ 77.194 +#define AL_FILTER_FIRST_PARAMETER 0x0000 77.195 +#define AL_FILTER_LAST_PARAMETER 0x8000 77.196 +#define AL_FILTER_TYPE 0x8001 77.197 + 77.198 +/* Filter types, used with the AL_FILTER_TYPE property */ 77.199 +#define AL_FILTER_NULL 0x0000 77.200 +#define AL_FILTER_LOWPASS 0x0001 77.201 +#define AL_FILTER_HIGHPASS 0x0002 77.202 +#define AL_FILTER_BANDPASS 0x0003 77.203 + 77.204 + 77.205 +/* Effect object function types. */ 77.206 +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); 77.207 +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*); 77.208 +typedef ALboolean (AL_APIENTRY *LPALISEFFECT)(ALuint); 77.209 +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); 77.210 +typedef void (AL_APIENTRY *LPALEFFECTIV)(ALuint, ALenum, ALint*); 77.211 +typedef void (AL_APIENTRY *LPALEFFECTF)(ALuint, ALenum, ALfloat); 77.212 +typedef void (AL_APIENTRY *LPALEFFECTFV)(ALuint, ALenum, ALfloat*); 77.213 +typedef void (AL_APIENTRY *LPALGETEFFECTI)(ALuint, ALenum, ALint*); 77.214 +typedef void (AL_APIENTRY *LPALGETEFFECTIV)(ALuint, ALenum, ALint*); 77.215 +typedef void (AL_APIENTRY *LPALGETEFFECTF)(ALuint, ALenum, ALfloat*); 77.216 +typedef void (AL_APIENTRY *LPALGETEFFECTFV)(ALuint, ALenum, ALfloat*); 77.217 + 77.218 +/* Filter object function types. */ 77.219 +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); 77.220 +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*); 77.221 +typedef ALboolean (AL_APIENTRY *LPALISFILTER)(ALuint); 77.222 +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); 77.223 +typedef void (AL_APIENTRY *LPALFILTERIV)(ALuint, ALenum, ALint*); 77.224 +typedef void (AL_APIENTRY *LPALFILTERF)(ALuint, ALenum, ALfloat); 77.225 +typedef void (AL_APIENTRY *LPALFILTERFV)(ALuint, ALenum, ALfloat*); 77.226 +typedef void (AL_APIENTRY *LPALGETFILTERI)(ALuint, ALenum, ALint*); 77.227 +typedef void (AL_APIENTRY *LPALGETFILTERIV)(ALuint, ALenum, ALint*); 77.228 +typedef void (AL_APIENTRY *LPALGETFILTERF)(ALuint, ALenum, ALfloat*); 77.229 +typedef void (AL_APIENTRY *LPALGETFILTERFV)(ALuint, ALenum, ALfloat*); 77.230 + 77.231 +/* Auxiliary Effect Slot object function types. */ 77.232 +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); 77.233 +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTS)(ALsizei, ALuint*); 77.234 +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOT)(ALuint); 77.235 +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint); 77.236 +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); 77.237 +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat); 77.238 +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); 77.239 +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTI)(ALuint, ALenum, ALint*); 77.240 +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIV)(ALuint, ALenum, ALint*); 77.241 +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTF)(ALuint, ALenum, ALfloat*); 77.242 +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFV)(ALuint, ALenum, ALfloat*); 77.243 + 77.244 +#ifdef AL_ALEXT_PROTOTYPES 77.245 +AL_API ALvoid AL_APIENTRY alGenEffects(ALsizei n, ALuint *effects); 77.246 +AL_API ALvoid AL_APIENTRY alDeleteEffects(ALsizei n, ALuint *effects); 77.247 +AL_API ALboolean AL_APIENTRY alIsEffect(ALuint effect); 77.248 +AL_API ALvoid AL_APIENTRY alEffecti(ALuint effect, ALenum param, ALint iValue); 77.249 +AL_API ALvoid AL_APIENTRY alEffectiv(ALuint effect, ALenum param, ALint *piValues); 77.250 +AL_API ALvoid AL_APIENTRY alEffectf(ALuint effect, ALenum param, ALfloat flValue); 77.251 +AL_API ALvoid AL_APIENTRY alEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); 77.252 +AL_API ALvoid AL_APIENTRY alGetEffecti(ALuint effect, ALenum param, ALint *piValue); 77.253 +AL_API ALvoid AL_APIENTRY alGetEffectiv(ALuint effect, ALenum param, ALint *piValues); 77.254 +AL_API ALvoid AL_APIENTRY alGetEffectf(ALuint effect, ALenum param, ALfloat *pflValue); 77.255 +AL_API ALvoid AL_APIENTRY alGetEffectfv(ALuint effect, ALenum param, ALfloat *pflValues); 77.256 + 77.257 +AL_API ALvoid AL_APIENTRY alGenFilters(ALsizei n, ALuint *filters); 77.258 +AL_API ALvoid AL_APIENTRY alDeleteFilters(ALsizei n, ALuint *filters); 77.259 +AL_API ALboolean AL_APIENTRY alIsFilter(ALuint filter); 77.260 +AL_API ALvoid AL_APIENTRY alFilteri(ALuint filter, ALenum param, ALint iValue); 77.261 +AL_API ALvoid AL_APIENTRY alFilteriv(ALuint filter, ALenum param, ALint *piValues); 77.262 +AL_API ALvoid AL_APIENTRY alFilterf(ALuint filter, ALenum param, ALfloat flValue); 77.263 +AL_API ALvoid AL_APIENTRY alFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); 77.264 +AL_API ALvoid AL_APIENTRY alGetFilteri(ALuint filter, ALenum param, ALint *piValue); 77.265 +AL_API ALvoid AL_APIENTRY alGetFilteriv(ALuint filter, ALenum param, ALint *piValues); 77.266 +AL_API ALvoid AL_APIENTRY alGetFilterf(ALuint filter, ALenum param, ALfloat *pflValue); 77.267 +AL_API ALvoid AL_APIENTRY alGetFilterfv(ALuint filter, ALenum param, ALfloat *pflValues); 77.268 + 77.269 +AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); 77.270 +AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots); 77.271 +AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot); 77.272 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint iValue); 77.273 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); 77.274 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat flValue); 77.275 +AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); 77.276 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *piValue); 77.277 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *piValues); 77.278 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *pflValue); 77.279 +AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *pflValues); 77.280 +#endif 77.281 + 77.282 +/* Filter ranges and defaults. */ 77.283 + 77.284 +/* Lowpass filter */ 77.285 +#define AL_LOWPASS_MIN_GAIN (0.0f) 77.286 +#define AL_LOWPASS_MAX_GAIN (1.0f) 77.287 +#define AL_LOWPASS_DEFAULT_GAIN (1.0f) 77.288 + 77.289 +#define AL_LOWPASS_MIN_GAINHF (0.0f) 77.290 +#define AL_LOWPASS_MAX_GAINHF (1.0f) 77.291 +#define AL_LOWPASS_DEFAULT_GAINHF (1.0f) 77.292 + 77.293 +/* Highpass filter */ 77.294 +#define AL_HIGHPASS_MIN_GAIN (0.0f) 77.295 +#define AL_HIGHPASS_MAX_GAIN (1.0f) 77.296 +#define AL_HIGHPASS_DEFAULT_GAIN (1.0f) 77.297 + 77.298 +#define AL_HIGHPASS_MIN_GAINLF (0.0f) 77.299 +#define AL_HIGHPASS_MAX_GAINLF (1.0f) 77.300 +#define AL_HIGHPASS_DEFAULT_GAINLF (1.0f) 77.301 + 77.302 +/* Bandpass filter */ 77.303 +#define AL_BANDPASS_MIN_GAIN (0.0f) 77.304 +#define AL_BANDPASS_MAX_GAIN (1.0f) 77.305 +#define AL_BANDPASS_DEFAULT_GAIN (1.0f) 77.306 + 77.307 +#define AL_BANDPASS_MIN_GAINHF (0.0f) 77.308 +#define AL_BANDPASS_MAX_GAINHF (1.0f) 77.309 +#define AL_BANDPASS_DEFAULT_GAINHF (1.0f) 77.310 + 77.311 +#define AL_BANDPASS_MIN_GAINLF (0.0f) 77.312 +#define AL_BANDPASS_MAX_GAINLF (1.0f) 77.313 +#define AL_BANDPASS_DEFAULT_GAINLF (1.0f) 77.314 + 77.315 + 77.316 +/* Effect parameter ranges and defaults. */ 77.317 + 77.318 +/* Standard reverb effect */ 77.319 +#define AL_REVERB_MIN_DENSITY (0.0f) 77.320 +#define AL_REVERB_MAX_DENSITY (1.0f) 77.321 +#define AL_REVERB_DEFAULT_DENSITY (1.0f) 77.322 + 77.323 +#define AL_REVERB_MIN_DIFFUSION (0.0f) 77.324 +#define AL_REVERB_MAX_DIFFUSION (1.0f) 77.325 +#define AL_REVERB_DEFAULT_DIFFUSION (1.0f) 77.326 + 77.327 +#define AL_REVERB_MIN_GAIN (0.0f) 77.328 +#define AL_REVERB_MAX_GAIN (1.0f) 77.329 +#define AL_REVERB_DEFAULT_GAIN (0.32f) 77.330 + 77.331 +#define AL_REVERB_MIN_GAINHF (0.0f) 77.332 +#define AL_REVERB_MAX_GAINHF (1.0f) 77.333 +#define AL_REVERB_DEFAULT_GAINHF (0.89f) 77.334 + 77.335 +#define AL_REVERB_MIN_DECAY_TIME (0.1f) 77.336 +#define AL_REVERB_MAX_DECAY_TIME (20.0f) 77.337 +#define AL_REVERB_DEFAULT_DECAY_TIME (1.49f) 77.338 + 77.339 +#define AL_REVERB_MIN_DECAY_HFRATIO (0.1f) 77.340 +#define AL_REVERB_MAX_DECAY_HFRATIO (2.0f) 77.341 +#define AL_REVERB_DEFAULT_DECAY_HFRATIO (0.83f) 77.342 + 77.343 +#define AL_REVERB_MIN_REFLECTIONS_GAIN (0.0f) 77.344 +#define AL_REVERB_MAX_REFLECTIONS_GAIN (3.16f) 77.345 +#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN (0.05f) 77.346 + 77.347 +#define AL_REVERB_MIN_REFLECTIONS_DELAY (0.0f) 77.348 +#define AL_REVERB_MAX_REFLECTIONS_DELAY (0.3f) 77.349 +#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY (0.007f) 77.350 + 77.351 +#define AL_REVERB_MIN_LATE_REVERB_GAIN (0.0f) 77.352 +#define AL_REVERB_MAX_LATE_REVERB_GAIN (10.0f) 77.353 +#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN (1.26f) 77.354 + 77.355 +#define AL_REVERB_MIN_LATE_REVERB_DELAY (0.0f) 77.356 +#define AL_REVERB_MAX_LATE_REVERB_DELAY (0.1f) 77.357 +#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY (0.011f) 77.358 + 77.359 +#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f) 77.360 +#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f) 77.361 +#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f) 77.362 + 77.363 +#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f) 77.364 +#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f) 77.365 +#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) 77.366 + 77.367 +#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE 77.368 +#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE 77.369 +#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE 77.370 + 77.371 +/* EAX reverb effect */ 77.372 +#define AL_EAXREVERB_MIN_DENSITY (0.0f) 77.373 +#define AL_EAXREVERB_MAX_DENSITY (1.0f) 77.374 +#define AL_EAXREVERB_DEFAULT_DENSITY (1.0f) 77.375 + 77.376 +#define AL_EAXREVERB_MIN_DIFFUSION (0.0f) 77.377 +#define AL_EAXREVERB_MAX_DIFFUSION (1.0f) 77.378 +#define AL_EAXREVERB_DEFAULT_DIFFUSION (1.0f) 77.379 + 77.380 +#define AL_EAXREVERB_MIN_GAIN (0.0f) 77.381 +#define AL_EAXREVERB_MAX_GAIN (1.0f) 77.382 +#define AL_EAXREVERB_DEFAULT_GAIN (0.32f) 77.383 + 77.384 +#define AL_EAXREVERB_MIN_GAINHF (0.0f) 77.385 +#define AL_EAXREVERB_MAX_GAINHF (1.0f) 77.386 +#define AL_EAXREVERB_DEFAULT_GAINHF (0.89f) 77.387 + 77.388 +#define AL_EAXREVERB_MIN_GAINLF (0.0f) 77.389 +#define AL_EAXREVERB_MAX_GAINLF (1.0f) 77.390 +#define AL_EAXREVERB_DEFAULT_GAINLF (1.0f) 77.391 + 77.392 +#define AL_EAXREVERB_MIN_DECAY_TIME (0.1f) 77.393 +#define AL_EAXREVERB_MAX_DECAY_TIME (20.0f) 77.394 +#define AL_EAXREVERB_DEFAULT_DECAY_TIME (1.49f) 77.395 + 77.396 +#define AL_EAXREVERB_MIN_DECAY_HFRATIO (0.1f) 77.397 +#define AL_EAXREVERB_MAX_DECAY_HFRATIO (2.0f) 77.398 +#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO (0.83f) 77.399 + 77.400 +#define AL_EAXREVERB_MIN_DECAY_LFRATIO (0.1f) 77.401 +#define AL_EAXREVERB_MAX_DECAY_LFRATIO (2.0f) 77.402 +#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO (1.0f) 77.403 + 77.404 +#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN (0.0f) 77.405 +#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN (3.16f) 77.406 +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN (0.05f) 77.407 + 77.408 +#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY (0.0f) 77.409 +#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY (0.3f) 77.410 +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY (0.007f) 77.411 + 77.412 +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ (0.0f) 77.413 + 77.414 +#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN (0.0f) 77.415 +#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN (10.0f) 77.416 +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN (1.26f) 77.417 + 77.418 +#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY (0.0f) 77.419 +#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY (0.1f) 77.420 +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY (0.011f) 77.421 + 77.422 +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ (0.0f) 77.423 + 77.424 +#define AL_EAXREVERB_MIN_ECHO_TIME (0.075f) 77.425 +#define AL_EAXREVERB_MAX_ECHO_TIME (0.25f) 77.426 +#define AL_EAXREVERB_DEFAULT_ECHO_TIME (0.25f) 77.427 + 77.428 +#define AL_EAXREVERB_MIN_ECHO_DEPTH (0.0f) 77.429 +#define AL_EAXREVERB_MAX_ECHO_DEPTH (1.0f) 77.430 +#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH (0.0f) 77.431 + 77.432 +#define AL_EAXREVERB_MIN_MODULATION_TIME (0.04f) 77.433 +#define AL_EAXREVERB_MAX_MODULATION_TIME (4.0f) 77.434 +#define AL_EAXREVERB_DEFAULT_MODULATION_TIME (0.25f) 77.435 + 77.436 +#define AL_EAXREVERB_MIN_MODULATION_DEPTH (0.0f) 77.437 +#define AL_EAXREVERB_MAX_MODULATION_DEPTH (1.0f) 77.438 +#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH (0.0f) 77.439 + 77.440 +#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF (0.892f) 77.441 +#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF (1.0f) 77.442 +#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF (0.994f) 77.443 + 77.444 +#define AL_EAXREVERB_MIN_HFREFERENCE (1000.0f) 77.445 +#define AL_EAXREVERB_MAX_HFREFERENCE (20000.0f) 77.446 +#define AL_EAXREVERB_DEFAULT_HFREFERENCE (5000.0f) 77.447 + 77.448 +#define AL_EAXREVERB_MIN_LFREFERENCE (20.0f) 77.449 +#define AL_EAXREVERB_MAX_LFREFERENCE (1000.0f) 77.450 +#define AL_EAXREVERB_DEFAULT_LFREFERENCE (250.0f) 77.451 + 77.452 +#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR (0.0f) 77.453 +#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR (10.0f) 77.454 +#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) 77.455 + 77.456 +#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE 77.457 +#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE 77.458 +#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE 77.459 + 77.460 +/* Chorus effect */ 77.461 +#define AL_CHORUS_WAVEFORM_SINUSOID (0) 77.462 +#define AL_CHORUS_WAVEFORM_TRIANGLE (1) 77.463 + 77.464 +#define AL_CHORUS_MIN_WAVEFORM (0) 77.465 +#define AL_CHORUS_MAX_WAVEFORM (1) 77.466 +#define AL_CHORUS_DEFAULT_WAVEFORM (1) 77.467 + 77.468 +#define AL_CHORUS_MIN_PHASE (-180) 77.469 +#define AL_CHORUS_MAX_PHASE (180) 77.470 +#define AL_CHORUS_DEFAULT_PHASE (90) 77.471 + 77.472 +#define AL_CHORUS_MIN_RATE (0.0f) 77.473 +#define AL_CHORUS_MAX_RATE (10.0f) 77.474 +#define AL_CHORUS_DEFAULT_RATE (1.1f) 77.475 + 77.476 +#define AL_CHORUS_MIN_DEPTH (0.0f) 77.477 +#define AL_CHORUS_MAX_DEPTH (1.0f) 77.478 +#define AL_CHORUS_DEFAULT_DEPTH (0.1f) 77.479 + 77.480 +#define AL_CHORUS_MIN_FEEDBACK (-1.0f) 77.481 +#define AL_CHORUS_MAX_FEEDBACK (1.0f) 77.482 +#define AL_CHORUS_DEFAULT_FEEDBACK (0.25f) 77.483 + 77.484 +#define AL_CHORUS_MIN_DELAY (0.0f) 77.485 +#define AL_CHORUS_MAX_DELAY (0.016f) 77.486 +#define AL_CHORUS_DEFAULT_DELAY (0.016f) 77.487 + 77.488 +/* Distortion effect */ 77.489 +#define AL_DISTORTION_MIN_EDGE (0.0f) 77.490 +#define AL_DISTORTION_MAX_EDGE (1.0f) 77.491 +#define AL_DISTORTION_DEFAULT_EDGE (0.2f) 77.492 + 77.493 +#define AL_DISTORTION_MIN_GAIN (0.01f) 77.494 +#define AL_DISTORTION_MAX_GAIN (1.0f) 77.495 +#define AL_DISTORTION_DEFAULT_GAIN (0.05f) 77.496 + 77.497 +#define AL_DISTORTION_MIN_LOWPASS_CUTOFF (80.0f) 77.498 +#define AL_DISTORTION_MAX_LOWPASS_CUTOFF (24000.0f) 77.499 +#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF (8000.0f) 77.500 + 77.501 +#define AL_DISTORTION_MIN_EQCENTER (80.0f) 77.502 +#define AL_DISTORTION_MAX_EQCENTER (24000.0f) 77.503 +#define AL_DISTORTION_DEFAULT_EQCENTER (3600.0f) 77.504 + 77.505 +#define AL_DISTORTION_MIN_EQBANDWIDTH (80.0f) 77.506 +#define AL_DISTORTION_MAX_EQBANDWIDTH (24000.0f) 77.507 +#define AL_DISTORTION_DEFAULT_EQBANDWIDTH (3600.0f) 77.508 + 77.509 +/* Echo effect */ 77.510 +#define AL_ECHO_MIN_DELAY (0.0f) 77.511 +#define AL_ECHO_MAX_DELAY (0.207f) 77.512 +#define AL_ECHO_DEFAULT_DELAY (0.1f) 77.513 + 77.514 +#define AL_ECHO_MIN_LRDELAY (0.0f) 77.515 +#define AL_ECHO_MAX_LRDELAY (0.404f) 77.516 +#define AL_ECHO_DEFAULT_LRDELAY (0.1f) 77.517 + 77.518 +#define AL_ECHO_MIN_DAMPING (0.0f) 77.519 +#define AL_ECHO_MAX_DAMPING (0.99f) 77.520 +#define AL_ECHO_DEFAULT_DAMPING (0.5f) 77.521 + 77.522 +#define AL_ECHO_MIN_FEEDBACK (0.0f) 77.523 +#define AL_ECHO_MAX_FEEDBACK (1.0f) 77.524 +#define AL_ECHO_DEFAULT_FEEDBACK (0.5f) 77.525 + 77.526 +#define AL_ECHO_MIN_SPREAD (-1.0f) 77.527 +#define AL_ECHO_MAX_SPREAD (1.0f) 77.528 +#define AL_ECHO_DEFAULT_SPREAD (-1.0f) 77.529 + 77.530 +/* Flanger effect */ 77.531 +#define AL_FLANGER_WAVEFORM_SINUSOID (0) 77.532 +#define AL_FLANGER_WAVEFORM_TRIANGLE (1) 77.533 + 77.534 +#define AL_FLANGER_MIN_WAVEFORM (0) 77.535 +#define AL_FLANGER_MAX_WAVEFORM (1) 77.536 +#define AL_FLANGER_DEFAULT_WAVEFORM (1) 77.537 + 77.538 +#define AL_FLANGER_MIN_PHASE (-180) 77.539 +#define AL_FLANGER_MAX_PHASE (180) 77.540 +#define AL_FLANGER_DEFAULT_PHASE (0) 77.541 + 77.542 +#define AL_FLANGER_MIN_RATE (0.0f) 77.543 +#define AL_FLANGER_MAX_RATE (10.0f) 77.544 +#define AL_FLANGER_DEFAULT_RATE (0.27f) 77.545 + 77.546 +#define AL_FLANGER_MIN_DEPTH (0.0f) 77.547 +#define AL_FLANGER_MAX_DEPTH (1.0f) 77.548 +#define AL_FLANGER_DEFAULT_DEPTH (1.0f) 77.549 + 77.550 +#define AL_FLANGER_MIN_FEEDBACK (-1.0f) 77.551 +#define AL_FLANGER_MAX_FEEDBACK (1.0f) 77.552 +#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f) 77.553 + 77.554 +#define AL_FLANGER_MIN_DELAY (0.0f) 77.555 +#define AL_FLANGER_MAX_DELAY (0.004f) 77.556 +#define AL_FLANGER_DEFAULT_DELAY (0.002f) 77.557 + 77.558 +/* Frequency shifter effect */ 77.559 +#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY (0.0f) 77.560 +#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY (24000.0f) 77.561 +#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY (0.0f) 77.562 + 77.563 +#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION (0) 77.564 +#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION (2) 77.565 +#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION (0) 77.566 + 77.567 +#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN (0) 77.568 +#define AL_FREQUENCY_SHIFTER_DIRECTION_UP (1) 77.569 +#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF (2) 77.570 + 77.571 +#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION (0) 77.572 +#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION (2) 77.573 +#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION (0) 77.574 + 77.575 +/* Vocal morpher effect */ 77.576 +#define AL_VOCAL_MORPHER_MIN_PHONEMEA (0) 77.577 +#define AL_VOCAL_MORPHER_MAX_PHONEMEA (29) 77.578 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA (0) 77.579 + 77.580 +#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24) 77.581 +#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING (24) 77.582 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING (0) 77.583 + 77.584 +#define AL_VOCAL_MORPHER_MIN_PHONEMEB (0) 77.585 +#define AL_VOCAL_MORPHER_MAX_PHONEMEB (29) 77.586 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB (10) 77.587 + 77.588 +#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24) 77.589 +#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING (24) 77.590 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING (0) 77.591 + 77.592 +#define AL_VOCAL_MORPHER_PHONEME_A (0) 77.593 +#define AL_VOCAL_MORPHER_PHONEME_E (1) 77.594 +#define AL_VOCAL_MORPHER_PHONEME_I (2) 77.595 +#define AL_VOCAL_MORPHER_PHONEME_O (3) 77.596 +#define AL_VOCAL_MORPHER_PHONEME_U (4) 77.597 +#define AL_VOCAL_MORPHER_PHONEME_AA (5) 77.598 +#define AL_VOCAL_MORPHER_PHONEME_AE (6) 77.599 +#define AL_VOCAL_MORPHER_PHONEME_AH (7) 77.600 +#define AL_VOCAL_MORPHER_PHONEME_AO (8) 77.601 +#define AL_VOCAL_MORPHER_PHONEME_EH (9) 77.602 +#define AL_VOCAL_MORPHER_PHONEME_ER (10) 77.603 +#define AL_VOCAL_MORPHER_PHONEME_IH (11) 77.604 +#define AL_VOCAL_MORPHER_PHONEME_IY (12) 77.605 +#define AL_VOCAL_MORPHER_PHONEME_UH (13) 77.606 +#define AL_VOCAL_MORPHER_PHONEME_UW (14) 77.607 +#define AL_VOCAL_MORPHER_PHONEME_B (15) 77.608 +#define AL_VOCAL_MORPHER_PHONEME_D (16) 77.609 +#define AL_VOCAL_MORPHER_PHONEME_F (17) 77.610 +#define AL_VOCAL_MORPHER_PHONEME_G (18) 77.611 +#define AL_VOCAL_MORPHER_PHONEME_J (19) 77.612 +#define AL_VOCAL_MORPHER_PHONEME_K (20) 77.613 +#define AL_VOCAL_MORPHER_PHONEME_L (21) 77.614 +#define AL_VOCAL_MORPHER_PHONEME_M (22) 77.615 +#define AL_VOCAL_MORPHER_PHONEME_N (23) 77.616 +#define AL_VOCAL_MORPHER_PHONEME_P (24) 77.617 +#define AL_VOCAL_MORPHER_PHONEME_R (25) 77.618 +#define AL_VOCAL_MORPHER_PHONEME_S (26) 77.619 +#define AL_VOCAL_MORPHER_PHONEME_T (27) 77.620 +#define AL_VOCAL_MORPHER_PHONEME_V (28) 77.621 +#define AL_VOCAL_MORPHER_PHONEME_Z (29) 77.622 + 77.623 +#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID (0) 77.624 +#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE (1) 77.625 +#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH (2) 77.626 + 77.627 +#define AL_VOCAL_MORPHER_MIN_WAVEFORM (0) 77.628 +#define AL_VOCAL_MORPHER_MAX_WAVEFORM (2) 77.629 +#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM (0) 77.630 + 77.631 +#define AL_VOCAL_MORPHER_MIN_RATE (0.0f) 77.632 +#define AL_VOCAL_MORPHER_MAX_RATE (10.0f) 77.633 +#define AL_VOCAL_MORPHER_DEFAULT_RATE (1.41f) 77.634 + 77.635 +/* Pitch shifter effect */ 77.636 +#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12) 77.637 +#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE (12) 77.638 +#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE (12) 77.639 + 77.640 +#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50) 77.641 +#define AL_PITCH_SHIFTER_MAX_FINE_TUNE (50) 77.642 +#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE (0) 77.643 + 77.644 +/* Ring modulator effect */ 77.645 +#define AL_RING_MODULATOR_MIN_FREQUENCY (0.0f) 77.646 +#define AL_RING_MODULATOR_MAX_FREQUENCY (8000.0f) 77.647 +#define AL_RING_MODULATOR_DEFAULT_FREQUENCY (440.0f) 77.648 + 77.649 +#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF (0.0f) 77.650 +#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF (24000.0f) 77.651 +#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF (800.0f) 77.652 + 77.653 +#define AL_RING_MODULATOR_SINUSOID (0) 77.654 +#define AL_RING_MODULATOR_SAWTOOTH (1) 77.655 +#define AL_RING_MODULATOR_SQUARE (2) 77.656 + 77.657 +#define AL_RING_MODULATOR_MIN_WAVEFORM (0) 77.658 +#define AL_RING_MODULATOR_MAX_WAVEFORM (2) 77.659 +#define AL_RING_MODULATOR_DEFAULT_WAVEFORM (0) 77.660 + 77.661 +/* Autowah effect */ 77.662 +#define AL_AUTOWAH_MIN_ATTACK_TIME (0.0001f) 77.663 +#define AL_AUTOWAH_MAX_ATTACK_TIME (1.0f) 77.664 +#define AL_AUTOWAH_DEFAULT_ATTACK_TIME (0.06f) 77.665 + 77.666 +#define AL_AUTOWAH_MIN_RELEASE_TIME (0.0001f) 77.667 +#define AL_AUTOWAH_MAX_RELEASE_TIME (1.0f) 77.668 +#define AL_AUTOWAH_DEFAULT_RELEASE_TIME (0.06f) 77.669 + 77.670 +#define AL_AUTOWAH_MIN_RESONANCE (2.0f) 77.671 +#define AL_AUTOWAH_MAX_RESONANCE (1000.0f) 77.672 +#define AL_AUTOWAH_DEFAULT_RESONANCE (1000.0f) 77.673 + 77.674 +#define AL_AUTOWAH_MIN_PEAK_GAIN (0.00003f) 77.675 +#define AL_AUTOWAH_MAX_PEAK_GAIN (31621.0f) 77.676 +#define AL_AUTOWAH_DEFAULT_PEAK_GAIN (11.22f) 77.677 + 77.678 +/* Compressor effect */ 77.679 +#define AL_COMPRESSOR_MIN_ONOFF (0) 77.680 +#define AL_COMPRESSOR_MAX_ONOFF (1) 77.681 +#define AL_COMPRESSOR_DEFAULT_ONOFF (1) 77.682 + 77.683 +/* Equalizer effect */ 77.684 +#define AL_EQUALIZER_MIN_LOW_GAIN (0.126f) 77.685 +#define AL_EQUALIZER_MAX_LOW_GAIN (7.943f) 77.686 +#define AL_EQUALIZER_DEFAULT_LOW_GAIN (1.0f) 77.687 + 77.688 +#define AL_EQUALIZER_MIN_LOW_CUTOFF (50.0f) 77.689 +#define AL_EQUALIZER_MAX_LOW_CUTOFF (800.0f) 77.690 +#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF (200.0f) 77.691 + 77.692 +#define AL_EQUALIZER_MIN_MID1_GAIN (0.126f) 77.693 +#define AL_EQUALIZER_MAX_MID1_GAIN (7.943f) 77.694 +#define AL_EQUALIZER_DEFAULT_MID1_GAIN (1.0f) 77.695 + 77.696 +#define AL_EQUALIZER_MIN_MID1_CENTER (200.0f) 77.697 +#define AL_EQUALIZER_MAX_MID1_CENTER (3000.0f) 77.698 +#define AL_EQUALIZER_DEFAULT_MID1_CENTER (500.0f) 77.699 + 77.700 +#define AL_EQUALIZER_MIN_MID1_WIDTH (0.01f) 77.701 +#define AL_EQUALIZER_MAX_MID1_WIDTH (1.0f) 77.702 +#define AL_EQUALIZER_DEFAULT_MID1_WIDTH (1.0f) 77.703 + 77.704 +#define AL_EQUALIZER_MIN_MID2_GAIN (0.126f) 77.705 +#define AL_EQUALIZER_MAX_MID2_GAIN (7.943f) 77.706 +#define AL_EQUALIZER_DEFAULT_MID2_GAIN (1.0f) 77.707 + 77.708 +#define AL_EQUALIZER_MIN_MID2_CENTER (1000.0f) 77.709 +#define AL_EQUALIZER_MAX_MID2_CENTER (8000.0f) 77.710 +#define AL_EQUALIZER_DEFAULT_MID2_CENTER (3000.0f) 77.711 + 77.712 +#define AL_EQUALIZER_MIN_MID2_WIDTH (0.01f) 77.713 +#define AL_EQUALIZER_MAX_MID2_WIDTH (1.0f) 77.714 +#define AL_EQUALIZER_DEFAULT_MID2_WIDTH (1.0f) 77.715 + 77.716 +#define AL_EQUALIZER_MIN_HIGH_GAIN (0.126f) 77.717 +#define AL_EQUALIZER_MAX_HIGH_GAIN (7.943f) 77.718 +#define AL_EQUALIZER_DEFAULT_HIGH_GAIN (1.0f) 77.719 + 77.720 +#define AL_EQUALIZER_MIN_HIGH_CUTOFF (4000.0f) 77.721 +#define AL_EQUALIZER_MAX_HIGH_CUTOFF (16000.0f) 77.722 +#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF (6000.0f) 77.723 + 77.724 + 77.725 +/* Source parameter value ranges and defaults. */ 77.726 +#define AL_MIN_AIR_ABSORPTION_FACTOR (0.0f) 77.727 +#define AL_MAX_AIR_ABSORPTION_FACTOR (10.0f) 77.728 +#define AL_DEFAULT_AIR_ABSORPTION_FACTOR (0.0f) 77.729 + 77.730 +#define AL_MIN_ROOM_ROLLOFF_FACTOR (0.0f) 77.731 +#define AL_MAX_ROOM_ROLLOFF_FACTOR (10.0f) 77.732 +#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR (0.0f) 77.733 + 77.734 +#define AL_MIN_CONE_OUTER_GAINHF (0.0f) 77.735 +#define AL_MAX_CONE_OUTER_GAINHF (1.0f) 77.736 +#define AL_DEFAULT_CONE_OUTER_GAINHF (1.0f) 77.737 + 77.738 +#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE 77.739 +#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE 77.740 +#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE 77.741 + 77.742 +#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE 77.743 +#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE 77.744 +#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE 77.745 + 77.746 +#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE 77.747 +#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE 77.748 +#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE 77.749 + 77.750 + 77.751 +/* Listener parameter value ranges and defaults. */ 77.752 +#define AL_MIN_METERS_PER_UNIT FLT_MIN 77.753 +#define AL_MAX_METERS_PER_UNIT FLT_MAX 77.754 +#define AL_DEFAULT_METERS_PER_UNIT (1.0f) 77.755 + 77.756 + 77.757 +#ifdef __cplusplus 77.758 +} /* extern "C" */ 77.759 +#endif 77.760 + 77.761 +#endif /* AL_EFX_H */
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 78.2 +++ b/openal.pc.in Tue Oct 25 13:02:31 2011 -0700 78.3 @@ -0,0 +1,11 @@ 78.4 +prefix=@prefix@ 78.5 +exec_prefix=@exec_prefix@ 78.6 +libdir=@libdir@ 78.7 +includedir=@includedir@ 78.8 + 78.9 +Name: OpenAL 78.10 +Description: OpenAL is a cross-platform 3D audio API 78.11 +Requires: @PKG_CONFIG_REQUIRES@ 78.12 +Version: @PACKAGE_VERSION@ 78.13 +Libs: -L${libdir} -l@LIBNAME@ @PKG_CONFIG_LIBS@ 78.14 +Cflags: -I${includedir} @PKG_CONFIG_CFLAGS@
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 79.2 +++ b/org/add-new-device.org Tue Oct 25 13:02:31 2011 -0700 79.3 @@ -0,0 +1,103 @@ 79.4 +#+title: all the steps to add a device to open-al 79.5 +#+author: Robert McIntyre 79.6 +#+email: rlm@mit.edu 79.7 +#+description: how to add a new device to open-al 79.8 +#+SETUPFILE: ../../aurellem/org/setup.org 79.9 +#+INCLUDE: ../../aurellem/org/level-0.org 79.10 + 79.11 + 79.12 +* How to add a new backend device 79.13 + 79.14 +* In Alc/backends/<your-device>.c 79.15 + 79.16 +#+begin_src C 79.17 +static const ALCchar <your-device>_device[] = <your-device-name>; 79.18 + 79.19 +ALCboolean alc_<your-device>_init(BackendFuncs *func_list) 79.20 +void alc_<your-device>_deinit(void) 79.21 + 79.22 +static ALCboolean <your-device>_open_playback(ALCdevice *device, const ALCchar *deviceName) 79.23 +static void <your-device>_close_playback(ALCdevice *device) 79.24 +static ALCboolean <your-device>_reset_playback(ALCdevice *device) 79.25 +static void <your-device>_stop_playback(ALCdevice *device) 79.26 +#+end_src 79.27 + 79.28 +#+begin_src C 79.29 +void alc_<your-device>_probe(enum DevProbe type) 79.30 +{ 79.31 + switch(type) 79.32 + { 79.33 + case DEVICE_PROBE: 79.34 + AppendDeviceList(<your-device>Device); 79.35 + break; 79.36 + case ALL_DEVICE_PROBE: 79.37 + AppendAllDeviceList(<your-device>Device); 79.38 + break; 79.39 + case CAPTURE_DEVICE_PROBE: 79.40 + break; 79.41 + } 79.42 +} 79.43 +#+end_src 79.44 + 79.45 +#+begin_src C 79.46 +static const BackendFuncs <your-device>_funcs = { 79.47 + <your-device>_open_playback, 79.48 + <your-device>_close_playback, 79.49 + <your-device>_reset_playback, 79.50 + <your-device>_stop_playback, 79.51 + NULL, 79.52 + NULL, 79.53 + NULL, 79.54 + NULL, 79.55 + NULL, 79.56 + NULL 79.57 +}; 79.58 +#+end_src 79.59 + 79.60 + 79.61 +* In OpenAL32/Include/alMain.h : 79.62 + 79.63 +#+begin_src C 79.64 +ALCboolean alc_<your-device>_init(BackendFuncs *func_list); 79.65 +void alc_<your-device>_deinit(void); 79.66 +void alc_<your-device>_probe(enum DevProbe type); 79.67 + 79.68 +#+end_src 79.69 + 79.70 +* In Alc/ALc.c : 79.71 + #+begin_src C 79.72 + { "<your-device>", alc_<your-device>_init, 79.73 + alc_<your-device>_deinit, alc_<your-device>_probe, EmptyFuncs }, 79.74 + 79.75 + #+end_src 79.76 + 79.77 +* In CMakeLists.txt 79.78 +#+begin_src cmake 79.79 +SET(ALC_OBJS Alc/ALc.c 79.80 + Alc/ALu.c 79.81 + Alc/alcConfig.c 79.82 + Alc/alcDedicated.c 79.83 + Alc/alcEcho.c 79.84 + Alc/alcModulator.c 79.85 + Alc/alcReverb.c 79.86 + Alc/alcRing.c 79.87 + Alc/alcThread.c 79.88 + Alc/bs2b.c 79.89 + Alc/helpers.c 79.90 + Alc/hrtf.c 79.91 + Alc/mixer.c 79.92 + Alc/panning.c 79.93 + # Default backends, always available 79.94 + Alc/backends/loopback.c 79.95 + Alc/backends/null.c 79.96 + # : add <your-device> device 79.97 + Alc/backends/<your-device>.c 79.98 +) 79.99 +#+end_src 79.100 + 79.101 + 79.102 +* In ~/.alsoftrc 79.103 + 79.104 +#+begin_src conf 79.105 +drivers = <your-device> 79.106 +#+end_src
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 80.2 +++ b/org/send.org Tue Oct 25 13:02:31 2011 -0700 80.3 @@ -0,0 +1,11 @@ 80.4 +#+title: send.c 80.5 +#+author: Robert McIntyre 80.6 +#+email: rlm@mit.edu 80.7 +#+description: some code I wrote to extend open-al 80.8 +#+SETUPFILE: ../../aurellem/org/setup.org 80.9 +#+INCLUDE: ../../aurellem/org/level-0.org 80.10 + 80.11 + 80.12 +#+include /home/r/proj/audio-send/Alc/backends/send.c src C 80.13 + 80.14 +
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 81.2 +++ b/record.c Tue Oct 25 13:02:31 2011 -0700 81.3 @@ -0,0 +1,1199 @@ 81.4 +/** 81.5 + * OpenAL cross platform audio library 81.6 + * Copyright (C) 2010 by Chris Robinson 81.7 + * This library is free software; you can redistribute it and/or 81.8 + * modify it under the terms of the GNU Library General Public 81.9 + * License as published by the Free Software Foundation; either 81.10 + * version 2 of the License, or (at your option) any later version. 81.11 + * 81.12 + * This library is distributed in the hope that it will be useful, 81.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 81.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 81.15 + * Library General Public License for more details. 81.16 + * 81.17 + * You should have received a copy of the GNU Library General Public 81.18 + * License along with this library; if not, write to the 81.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 81.20 + * Boston, MA 02111-1307, USA. 81.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 81.22 + */ 81.23 + 81.24 +#include "config.h" 81.25 +#include <stdlib.h> 81.26 +#include "alMain.h" 81.27 +#include "AL/al.h" 81.28 +#include "AL/alc.h" 81.29 +#include "alSource.h" 81.30 +#include <jni.h> 81.31 + 81.32 + 81.33 +typedef struct record_data { 81.34 + volatile int killNow; 81.35 + ALvoid *thread; 81.36 + ALuint robert; 81.37 + 81.38 + ALvoid *mainBuffer; 81.39 + ALvoid *auxBuffer; 81.40 + ALuint size; 81.41 + 81.42 + ALuint *unPauseIDs; 81.43 + int unPauseCount; 81.44 + ALboolean mainFull; 81.45 + ALboolean auxFull; 81.46 + ALboolean auxReady; 81.47 + ALboolean mainReady; 81.48 + 81.49 +} record_data; 81.50 + 81.51 + 81.52 + 81.53 + 81.54 +#define UNUSED(x) (void)(x) 81.55 +#define RUNONLY(n) \ 81.56 + {static int __runonce = n; \ 81.57 + if (__runonce-- <= 0){return;}} 81.58 + 81.59 +#define RUNAT(n) \ 81.60 + {static int __runat = n; \ 81.61 + if (0 != __runat--){return;}} 81.62 + 81.63 +/// al error handling code prototypes 81.64 + 81.65 +char* GetALErrorString(ALenum err); 81.66 +char* GetALCErrorString(ALenum err); 81.67 +void printError(void); 81.68 +void init(ALCdevice *); 81.69 +void init2(ALCdevice *); 81.70 +void later(ALCdevice *); 81.71 +void every(ALCdevice *); 81.72 +void every2(ALCdevice *); 81.73 +void step(ALCdevice *); 81.74 + 81.75 + 81.76 +//synchronization 81.77 +struct record_data; 81.78 +void syncContexts(ALCcontext *, ALCcontext *); 81.79 +void syncSources(ALsource *, ALsource *, ALCcontext *, ALCcontext *); 81.80 +void pauseMainContext(struct record_data *); 81.81 +void unPauseMainContext(struct record_data *); 81.82 +void pauseAllSources(ALCcontext *); 81.83 +static void saveAux(ALCdevice *); 81.84 +static void swapInAux(ALCdevice *); 81.85 +static void saveMain(ALCdevice *); 81.86 +static void swapInMain(ALCdevice *); 81.87 +void aux_alListenerf(ALenum param, ALfloat value); 81.88 +void aux_alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3); 81.89 + 81.90 + 81.91 +////////////// 81.92 + 81.93 + 81.94 + 81.95 +// remove all the sources from all the auxContexts 81.96 +// take the mainContext and for each context, COPY 81.97 +// the sources from the main context. 81.98 + 81.99 +// render each context and make their data available. 81.100 + 81.101 +// =alGenSources= (and =alGetError=) 81.102 +// attach each source to the shared buffer using =alSourcei= 81.103 + 81.104 + 81.105 +// need to make sure in the AudioRender class that we don't do 81.106 +// anything to sources while the audio is being rendered, so make sure 81.107 +// to maintain an "isDone" state as well. 81.108 + 81.109 +// Special device which allows simulation of multiple listeners 81.110 +// hearing the same set of sources. Provides access to the rendered 81.111 +// data for each listener. Designed to work with LWJGL. 81.112 + 81.113 +// first, the mainContext is the only context that is controlled by 81.114 +// LWJGL. 81.115 + 81.116 +// One context will be created for each listener that we want. 81.117 + 81.118 +// Then, at the start of each render loop, first PAUSE the sources on 81.119 +// all other contexts except the mainContext (this takes care of 81.120 +// sources in the mainContext being shut down.) 81.121 +// we will iterate through all 81.122 +// the active sources in our mainContext (the one which is controlled 81.123 +// through LWJGL), and take their sourceIDs. For each of these IDs 81.124 +// and for each other context, we'll check some internal structure to 81.125 +// see if we've already created a corresponding source. If that 81.126 +// source exits, we will SYNCH it with the source which belongs to the 81.127 +// mainContext. If it DOESN'T exist, we will CLONE the source from the 81.128 +// main context and establish it in the other context. 81.129 + 81.130 +// Each render loop consists of noting all of the active sources in 81.131 +// the mainContext and storing their IDs. Then, for each context, 81.132 +// the correspondig sources to the active sources in the mainContext 81.133 +// will be set to PLAY, and all sources in all other contexts will be 81.134 +// set to PAUSE. aluMixData will be called for each context in this 81.135 +// way. 81.136 + 81.137 +// approved by KittyCat 81.138 + 81.139 + 81.140 +// CAN get id appropiate for us in the sorce-repated openal functions 81.141 +// by quering *source->source 81.142 + 81.143 +// first, do it with only two listeners, two contexts, automatically 81.144 +// created. 81.145 + 81.146 +static ALCcontext* mainContext = NULL; 81.147 +static ALCcontext* auxContext = NULL; 81.148 + 81.149 + 81.150 +void aux_alListenerf(ALenum param, ALfloat value){ 81.151 + ALCcontext *current = alcGetCurrentContext(); 81.152 + alcMakeContextCurrent(auxContext); 81.153 + alListenerf(param, value); 81.154 + alcMakeContextCurrent(current); 81.155 +} 81.156 + 81.157 +void aux_alListener3f(ALenum param, ALfloat v1, ALfloat v2, ALfloat v3){ 81.158 + ALCcontext *current = alcGetCurrentContext(); 81.159 + alcMakeContextCurrent(auxContext); 81.160 + alListener3f(param, v1, v2, v3); 81.161 + alcMakeContextCurrent(current); 81.162 +} 81.163 + 81.164 + 81.165 + 81.166 +void pauseAllSources(ALCcontext *ctx){ 81.167 + ALCcontext *current = alcGetCurrentContext(); 81.168 + alcMakeContextCurrent(ctx); 81.169 + ALsource **src, **src_end; 81.170 + src = ctx->ActiveSources; 81.171 + src_end = src + ctx->ActiveSourceCount; 81.172 + while(src != src_end){ 81.173 + if (AL_PLAYING == (*src)->state){ 81.174 + //if (AL_TRUE){ 81.175 + ALuint source_id = (*src)->source; 81.176 + //printf("pausing ONE source\n"); 81.177 + alSourcePause(source_id); 81.178 + } 81.179 + src++; 81.180 + } 81.181 + alcMakeContextCurrent(current); 81.182 +} 81.183 + 81.184 + 81.185 +void init2(ALCdevice *Device){ 81.186 + UNUSED(Device); 81.187 + RUNONLY(1) 81.188 + // the mainContext only ever has a FIXED number of sources! 81.189 + // duplicate them ALL into auxContext! 81.190 + alcMakeContextCurrent(auxContext);{ 81.191 + UIntMap source_map= mainContext->SourceMap; 81.192 + ALuint num_sources = source_map.size; 81.193 + ALuint newSources[num_sources]; 81.194 + alGenSources(num_sources, newSources);} 81.195 + alcMakeContextCurrent(mainContext); 81.196 + 81.197 + 81.198 +} 81.199 + 81.200 + 81.201 + 81.202 + /* 81.203 +void syncSourcei(ALuint sourceID1, ALuint sourceID2, 81.204 + ALCcontext *ctx1, ALCcontext *ctx2, 81.205 + int numParams, ALenum *params){ 81.206 + ALint values[numParams]; 81.207 + ALCcontext current = alcGetCurrentContext(); 81.208 + // get values 81.209 + printf("getting values from source1\n"); 81.210 + alcMakeContextCurrent(ctx1); 81.211 + int i; 81.212 + for(i=0; i<numParams; i++){ 81.213 + alGetSourcei(sourceID1, params[i], values+i); 81.214 + printf("value is %d\n", values[i]); 81.215 + printError(); 81.216 + } 81.217 + // set values 81.218 + printf("setting values of source2\n"); 81.219 + alcMakeContextCurrent(ctx2); 81.220 + for (i=0; i<numParams; i++){ 81.221 + alSourcei(sourceID2, params[i], values[i]); 81.222 + printError(); 81.223 + } 81.224 + alcMakeContextCurrent(current); 81.225 + printError(); 81.226 +} 81.227 + */ 81.228 + 81.229 + 81.230 +#define _MAKE_SYNC(NAME, INIT_EXPR, GET_EXPR, SET_EXPR) \ 81.231 + void NAME (ALuint sourceID1, ALuint sourceID2, \ 81.232 + ALCcontext *ctx1, ALCcontext *ctx2, \ 81.233 + ALenum param){ \ 81.234 + INIT_EXPR; \ 81.235 + ALCcontext *current = alcGetCurrentContext(); \ 81.236 + alcMakeContextCurrent(ctx1); \ 81.237 + GET_EXPR; \ 81.238 + /*printError();*/ \ 81.239 + alcMakeContextCurrent(ctx2); \ 81.240 + SET_EXPR; \ 81.241 + /*printError();*/ \ 81.242 + alcMakeContextCurrent(current); \ 81.243 + } 81.244 + 81.245 +#define MAKE_SYNC(NAME, TYPE, GET, SET) \ 81.246 + _MAKE_SYNC(NAME, \ 81.247 + TYPE value, \ 81.248 + GET(sourceID1, param, &value), \ 81.249 + SET(sourceID2, param, value)) 81.250 + 81.251 +#define MAKE_SYNC3(NAME, TYPE, GET, SET) \ 81.252 + _MAKE_SYNC(NAME, \ 81.253 + TYPE value1; TYPE value2; TYPE value3;, \ 81.254 + GET(sourceID1, param, &value1, &value2, &value3), \ 81.255 + SET(sourceID2, param, value1, value2, value3)) 81.256 + 81.257 +MAKE_SYNC( syncSourcei, ALint, alGetSourcei, alSourcei); 81.258 +MAKE_SYNC( syncSourcef, ALfloat, alGetSourcef, alSourcef); 81.259 +MAKE_SYNC3(syncSource3i, ALint, alGetSource3i, alSource3i); 81.260 +MAKE_SYNC3(syncSource3f, ALfloat, alGetSource3f, alSource3f); 81.261 + 81.262 + 81.263 + 81.264 + 81.265 + 81.266 + 81.267 +#define DsyncSourcei(sourceID1, sourceID2, ctx1, ctx2, param) \ 81.268 + {/*printf("synci : " #param "\n");*/ \ 81.269 + syncSourcei(sourceID1, sourceID2, ctx1, ctx2, param);} 81.270 + 81.271 +#define DsyncSourcef(sourceID1, sourceID2, ctx1, ctx2, param) \ 81.272 + {/*printf("syncf : " #param "\n");*/ \ 81.273 + syncSourcef(sourceID1, sourceID2, ctx1, ctx2, param);} 81.274 + 81.275 +#define DsyncSource3i(sourceID1, sourceID2, ctx1, ctx2, param) \ 81.276 + {/*printf("sync3i : " #param "\n");*/ \ 81.277 + syncSource3i(sourceID1, sourceID2, ctx1, ctx2, param);} 81.278 + 81.279 +#define DsyncSource3f(sourceID1, sourceID2, ctx1, ctx2, param) \ 81.280 + {/*printf("sync3f : " #param "\n");*/ \ 81.281 + syncSource3f(sourceID1, sourceID2, ctx1, ctx2, param);} 81.282 + 81.283 +void printValid(ALuint sourceID){ 81.284 + alcMakeContextCurrent(auxContext); 81.285 + printf("source%d : %s\n", sourceID, alIsSource(sourceID) ? "VALID" : "INVALID"); 81.286 + alcMakeContextCurrent(mainContext); 81.287 +} 81.288 + 81.289 + 81.290 + 81.291 +void syncSources(ALsource *source1, ALsource *source2, 81.292 + ALCcontext *ctx1, ALCcontext *ctx2){ 81.293 + 81.294 + ALuint ID1 = source1->source; 81.295 + ALuint ID2 = source2->source; 81.296 + ALCcontext *current = alcGetCurrentContext(); 81.297 + //printf("***************\n"); 81.298 + //printf("SYNCHING source %d with source %d\n", ID1, ID2); 81.299 + 81.300 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_PITCH); 81.301 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_GAIN); 81.302 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MAX_DISTANCE); 81.303 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_ROLLOFF_FACTOR); 81.304 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_REFERENCE_DISTANCE); 81.305 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MIN_GAIN); 81.306 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_MAX_GAIN); 81.307 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_OUTER_GAIN); 81.308 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_INNER_ANGLE); 81.309 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_CONE_OUTER_ANGLE); 81.310 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_SEC_OFFSET); 81.311 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_SAMPLE_OFFSET); 81.312 + DsyncSourcef(ID1,ID2,ctx1,ctx2,AL_BYTE_OFFSET); 81.313 + 81.314 + DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_POSITION); 81.315 + DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_VELOCITY); 81.316 + DsyncSource3f(ID1,ID2,ctx1,ctx2,AL_DIRECTION); 81.317 + 81.318 + DsyncSourcei(ID1,ID2,ctx1,ctx2,AL_SOURCE_RELATIVE); 81.319 + DsyncSourcei(ID1,ID2,ctx1,ctx2,AL_LOOPING); 81.320 + 81.321 + 81.322 + 81.323 + 81.324 + 81.325 + // first, copy buffer patterns over. 81.326 + 81.327 + //source2->lSourceType = source1->lSourceType; 81.328 + //source2->NumChannels = source1->NumChannels; 81.329 + //source2->SampleSize = source1->SampleSize; 81.330 + //source2->Buffer = source1->Buffer; 81.331 + // source2->queue = source1->queue; 81.332 + // source2->BuffersInQueue = source1-> BuffersInQueue; 81.333 + // source2->BuffersPlayed = source1 -> BuffersPlayed; 81.334 + 81.335 + // then, duplicate the state. 81.336 + 81.337 + // handle static sources 81.338 + //printf("handling Buffers\n"); 81.339 + alcMakeContextCurrent(ctx1); 81.340 + ALint source_type; 81.341 + alGetSourcei(ID1, AL_SOURCE_TYPE, &source_type); 81.342 + //printError(); 81.343 + 81.344 + if (AL_STATIC == source_type){ 81.345 + //printf("setting STATIC source\n"); 81.346 + ALint buffer_id1; 81.347 + ALint buffer_id2; 81.348 + alGetSourcei(ID1, AL_BUFFER, &buffer_id1); 81.349 + alcMakeContextCurrent(ctx2); 81.350 + alGetSourcei(ID2, AL_BUFFER, &buffer_id2); 81.351 + if (buffer_id1 != buffer_id2){ 81.352 + //printf("setting source2's buffer from %d to %d\n", buffer_id2, buffer_id1); 81.353 + alSourcei(ID2, AL_BUFFER, buffer_id1); 81.354 + //printError(); 81.355 + } 81.356 + else { 81.357 + //printf("Buffers are already the same, doing nothing.\n"); 81.358 + } 81.359 + } 81.360 + else { 81.361 + // printf("not a static source!\n"); 81.362 + } 81.363 + 81.364 + 81.365 + 81.366 + 81.367 + 81.368 + 81.369 + alcMakeContextCurrent(ctx2); 81.370 + 81.371 + 81.372 + 81.373 + 81.374 + //printf("setting STATE\n"); 81.375 + alcMakeContextCurrent(ctx1); 81.376 + ALint state1; 81.377 + alGetSourcei(ID1, AL_SOURCE_STATE, &state1); 81.378 + //printError(); 81.379 + 81.380 + alcMakeContextCurrent(ctx2); 81.381 + ALint state2; 81.382 + alGetSourcei(ID2, AL_SOURCE_STATE, &state2); 81.383 + //printError(); 81.384 + if (state1 != state2){ 81.385 + switch (state1){ 81.386 + case AL_INITIAL : /*printf("INITIAL\n")*/;alSourceRewind(ID2);break; 81.387 + case AL_PLAYING : /*printf("PLAYING\n")*/;alSourcePlay(ID2);break; 81.388 + case AL_PAUSED : /*printf("PAUSED\n")*/;alSourcePause(ID2);break; 81.389 + case AL_STOPPED : /*printf("STOPPED\n")*/;alSourceStop(ID2);break; 81.390 + } 81.391 + } 81.392 + //printError(); 81.393 + 81.394 + 81.395 + 81.396 + alcMakeContextCurrent(current); 81.397 + 81.398 +} 81.399 + 81.400 + 81.401 +void syncContexts(ALCcontext *ctx1, ALCcontext *ctx2){ 81.402 + // if there aren't sufficient sources in ctx2 to mirror the sources 81.403 + // in ctx1, create them. 81.404 + ALCcontext *current = alcGetCurrentContext(); 81.405 + 81.406 + UIntMap *sourceMap1 = &(ctx1->SourceMap); 81.407 + UIntMap *sourceMap2 = &(ctx2->SourceMap); 81.408 + 81.409 + 81.410 + ALuint sources1 = sourceMap1->size; 81.411 + ALuint sources2 = sourceMap2->size; 81.412 + 81.413 + //printf("ctx1 has %d sources; ctx2 has %d sources\n", sources1, sources2); 81.414 + 81.415 + alcMakeContextCurrent(ctx2); 81.416 + if (sources2 < sources1){ 81.417 + ALuint numSources = sources1 - sources2; 81.418 + ALuint newSources[numSources]; 81.419 + alGenSources(numSources, newSources); 81.420 + printf("adjusting...\n"); 81.421 + printf("now ctx1 has %d sources; ctx2 has %d sources\n", 81.422 + sourceMap1->size, sourceMap2->size); 81.423 + } 81.424 + //printError(); 81.425 + 81.426 + 81.427 + alcMakeContextCurrent(current); 81.428 + 81.429 + 81.430 + // after this, ctx2 is gauranteed to have at least as many sources 81.431 + // as ctx1. Now, sync each source from ctx1 to the corresponding 81.432 + // source in ctx2. 81.433 + 81.434 + int i; 81.435 + 81.436 + 81.437 + 81.438 + for(i = 0; i < sourceMap1->size; i++){ 81.439 + syncSources((ALsource*)sourceMap1->array[i].value, 81.440 + (ALsource*)sourceMap2->array[i].value, 81.441 + ctx1, ctx2); 81.442 + } 81.443 + 81.444 + 81.445 + 81.446 + 81.447 + 81.448 +} 81.449 + 81.450 + 81.451 + 81.452 +void pauseMainContext(record_data *data){ 81.453 + //printf("pausing MainContext\n"); 81.454 + data->unPauseCount = 0; 81.455 + data->unPauseIDs = 81.456 + (ALuint*)realloc(data->unPauseIDs, 81.457 + sizeof(ALuint) * mainContext->ActiveSourceCount); 81.458 + 81.459 + ALsource **src, **src_end; 81.460 + src = mainContext->ActiveSources; 81.461 + src_end = src + mainContext->ActiveSourceCount; 81.462 + 81.463 + while(src != src_end){ 81.464 + 81.465 + if (AL_PLAYING == (*src)->state){ 81.466 + ALuint source_id = (*src)->source; 81.467 + data->unPauseIDs[data->unPauseCount++] = source_id; 81.468 + alSourcePause(source_id); 81.469 + } 81.470 + src++; 81.471 + } 81.472 +} 81.473 + 81.474 + 81.475 + 81.476 + 81.477 +void unPauseMainContext(record_data *data){ 81.478 + int i; 81.479 + for(i=0;i<data->unPauseCount;i++){ 81.480 + alSourcePlay(data->unPauseIDs[i]); 81.481 + } 81.482 +} 81.483 + 81.484 + 81.485 +// a device brings along with it multiple pieces of state 81.486 +// which have to be swapped in and out with each context. 81.487 + 81.488 +//static ALfloat DryBufferMain[BUFFERSIZE][MAXCHANNELS]; 81.489 +//static ALfloat DryBufferAux[BUFFERSIZE][MAXCHANNELS]; 81.490 +//static ALfloat PanningLUTMain[LUT_NUM][MAXCHANNELS]; 81.491 +//static ALfloat PanningLUTAux[LUT_NUM][MAXCHANNELS]; 81.492 +static ALfloat ClickRemovalMain[MAXCHANNELS]; 81.493 +static ALfloat ClickRemovalAux[MAXCHANNELS]; 81.494 +static ALfloat PendingClicksMain[MAXCHANNELS]; 81.495 +static ALfloat PendingClicksAux[MAXCHANNELS]; 81.496 + 81.497 + 81.498 + 81.499 +static void saveAux(ALCdevice *Device){ 81.500 + //memcpy(DryBufferAux, Device->DryBuffer, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); 81.501 + //memcpy(PanningLUTAux, Device->PanningLUT, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); 81.502 + memcpy(ClickRemovalAux, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); 81.503 + memcpy(PendingClicksAux, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); 81.504 +} 81.505 +static void swapInAux(ALCdevice *Device){ 81.506 + //memcpy(Device->DryBuffer, DryBufferAux, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); 81.507 + //memcpy(Device->PanningLUT, PanningLUTAux, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); 81.508 + memcpy(Device->ClickRemoval, ClickRemovalAux, sizeof(ALfloat)*MAXCHANNELS); 81.509 + memcpy(Device->PendingClicks, PendingClicksAux, sizeof(ALfloat)*MAXCHANNELS); 81.510 +} 81.511 + 81.512 + 81.513 +static void saveMain(ALCdevice *Device){ 81.514 + //memcpy(DryBufferMain, Device->DryBuffer, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); 81.515 + //memcpy(PanningLUTMain, Device->PanningLUT, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); 81.516 + memcpy(ClickRemovalMain, Device->ClickRemoval, sizeof(ALfloat)*MAXCHANNELS); 81.517 + memcpy(PendingClicksMain, Device->PendingClicks, sizeof(ALfloat)*MAXCHANNELS); 81.518 +} 81.519 +static void swapInMain(ALCdevice *Device){ 81.520 + //memcpy(Device->DryBuffer, DryBufferMain, sizeof(ALfloat)*BUFFERSIZE*MAXCHANNELS); 81.521 + //memcpy(Device->PanningLUT, PanningLUTMain, sizeof(ALfloat)*LUT_NUM*MAXCHANNELS); 81.522 + memcpy(Device->ClickRemoval, ClickRemovalMain, sizeof(ALfloat)*MAXCHANNELS); 81.523 + memcpy(Device->PendingClicks, PendingClicksMain, sizeof(ALfloat)*MAXCHANNELS); 81.524 +} 81.525 + 81.526 + 81.527 +static ALCcontext **currentContext; 81.528 +static ALuint currentNumContext; 81.529 +static void unLimitContext(ALCdevice *Device){ 81.530 + Device->Contexts = currentContext; 81.531 + Device->NumContexts = currentNumContext; 81.532 +} 81.533 + 81.534 +static void limitContext(ALCdevice *Device, ALCcontext *ctx){ 81.535 + currentContext = Device->Contexts; 81.536 + currentNumContext = Device->NumContexts; 81.537 + Device->Contexts = &ctx; 81.538 + Device->NumContexts = 1; 81.539 +} 81.540 + 81.541 + 81.542 +void every2(ALCdevice *Device){ 81.543 + 81.544 + record_data *data = (record_data*)Device->ExtraData; 81.545 + 81.546 + if (data->mainFull){ 81.547 + printf("data has not yet been extracted!\n"); 81.548 + return; 81.549 + } 81.550 + 81.551 + 81.552 + syncContexts(mainContext , auxContext); 81.553 + 81.554 + alcMakeContextCurrent(auxContext); 81.555 + limitContext(Device, auxContext); 81.556 + swapInAux(Device); 81.557 + aluMixData(Device, data->auxBuffer, Device->UpdateSize); 81.558 + saveAux(Device); 81.559 + unLimitContext(Device); 81.560 + 81.561 + 81.562 + alcMakeContextCurrent(mainContext); 81.563 + limitContext(Device, mainContext); 81.564 + swapInMain(Device); 81.565 + aluMixData(Device, data->mainBuffer, Device->UpdateSize); 81.566 + saveMain(Device); 81.567 + unLimitContext(Device); 81.568 + 81.569 + data->mainFull = AL_TRUE; 81.570 + data->auxFull = AL_TRUE; 81.571 + 81.572 +} 81.573 + 81.574 + 81.575 + 81.576 + 81.577 + 81.578 + 81.579 +void every(ALCdevice *Device){ 81.580 + UNUSED(Device); 81.581 + // by the time every() is called, mainContext and auxContext will 81.582 + // have been initiliazed. 81.583 + printf("+++++++\nevery is called\n"); 81.584 + // print sourceid for all sources. 81.585 + ALsource **src, **src_end; 81.586 + // LockDevice(Device); 81.587 + // pauseAllSources(auxContext); 81.588 + src = mainContext->ActiveSources; 81.589 + src_end = src + mainContext->ActiveSourceCount; 81.590 + UIntMap source_map ; 81.591 + int i; 81.592 + 81.593 + source_map= mainContext->SourceMap; 81.594 + printf("max sources in the mainContext is %d\n", source_map.maxsize); 81.595 + printf("current sources: %d\n", source_map.size); 81.596 + 81.597 + printf("their ID's are:\n"); 81.598 + for(i = 0; i < source_map.size; i++){ 81.599 + printf("%d, ",source_map.array[i].key); 81.600 + } 81.601 + printf("\n"); 81.602 + source_map= auxContext->SourceMap; 81.603 + printf("max sources in the auxContext is %d\n", source_map.maxsize); 81.604 + printf("current sources: %d\n", source_map.size); 81.605 + 81.606 + printf("their ID's are:\n"); 81.607 + for(i = 0; i < source_map.size; i++){ 81.608 + printf("%d, ",source_map.array[i].key); 81.609 + } 81.610 + printf("\n"); 81.611 + 81.612 + while(src != src_end){ 81.613 + 81.614 + if (AL_PLAYING == (*src)->state){ 81.615 + ALuint source_id = (*src)->source; 81.616 + printf("source %d is AL_PLAYING\n",source_id); 81.617 + } 81.618 + src++; 81.619 + 81.620 + } 81.621 + 81.622 + 81.623 + // UnlockDevice(Device); 81.624 +} 81.625 + 81.626 + 81.627 + 81.628 + 81.629 + 81.630 + 81.631 + 81.632 +// debug printing 81.633 + 81.634 +#define DEBUG 0 81.635 + 81.636 +#define dprintf(expr) {if (DEBUG) {printf(expr);}} 81.637 + 81.638 + 81.639 + 81.640 + 81.641 +static const ALCchar recordDevice[] = "Aurellem"; 81.642 + 81.643 + 81.644 + 81.645 + 81.646 + 81.647 + 81.648 +struct ALsource * cloneSource(struct ALsource *source); 81.649 + 81.650 +//struct ALsource * cloneSource(struct ALsource *source){ 81.651 +// ALuint[1] sourceID; 81.652 + 81.653 + 81.654 +//} 81.655 + 81.656 +int lock = 0; 81.657 + 81.658 +/* 81.659 +static ALuint RecordProc() 81.660 +{ 81.661 + if (0 == lock){return 0;} 81.662 + ALCdevice *Device = deviceInstance; 81.663 + dprintf("RLM: recordProc is begun!!\n"); 81.664 + printError(); 81.665 + static int MixCount = 0 ; 81.666 + if (Device->Connected) 81.667 + { 81.668 + // the device does not seem to be "ready" until this point. 81.669 + init(Device); 81.670 + //init2(Device); 81.671 + printf("\nMix Cycle %d\n", MixCount++); 81.672 + every(Device); 81.673 + every2(Device); 81.674 + //aluMixData(Device, NULL, Device->UpdateSize); 81.675 + } 81.676 + lock = 1; 81.677 + return 0; 81.678 +} 81.679 +*/ 81.680 + 81.681 + 81.682 + /* 81.683 +static ALuint RecordProc(ALvoid *ptr) 81.684 +{ 81.685 + 81.686 + printf("RLM: recordProc is begun!!\n"); 81.687 + ALCdevice *Device = (ALCdevice*)ptr; 81.688 + //printError(); 81.689 + record_data *data = (record_data*)Device->ExtraData; 81.690 + ALuint now, start; 81.691 + ALuint64 avail, done; 81.692 + const ALuint restTime = (ALuint64)Device->UpdateSize * 1000 / 81.693 + Device->Frequency / 2; 81.694 + 81.695 + done = 0; 81.696 + start = timeGetTime(); 81.697 + //static int MixCount = 0 ; 81.698 + 81.699 + 81.700 + if(!data->killNow && Device->Connected) 81.701 + { 81.702 + printf("sext level breakfast manuever!\n"); 81.703 + now = timeGetTime(); 81.704 + 81.705 + avail = (ALuint64)(now-start) * Device->Frequency / 1000; 81.706 + if(avail < done) 81.707 + { 81.708 + 81.709 + avail += (ALuint64)0xFFFFFFFFu*Device->Frequency/1000 - done; 81.710 + done = 0; 81.711 + } 81.712 + if(avail-done < Device->UpdateSize) 81.713 + { 81.714 + //Sleep(restTime); 81.715 + //continue; 81.716 + } 81.717 + 81.718 + while(avail-done >= Device->UpdateSize) 81.719 + { 81.720 + // the device does not seem to be "ready" until this point. 81.721 + init(Device); 81.722 + //init2(Device); 81.723 + //printf("\nMix Cycle %d\n", MixCount++); 81.724 + //every(Device); 81.725 + every2(Device); 81.726 + //later(Device); 81.727 + //printError(); 81.728 + //aluMixData(Device, NULL, Device->UpdateSize); 81.729 + //Sleep(3000); 81.730 + done += Device->UpdateSize; 81.731 + } 81.732 + } 81.733 + else { 81.734 + printf("WARNGING\n"); 81.735 + } 81.736 + 81.737 + return 0; 81.738 +} 81.739 +*/ 81.740 + 81.741 + 81.742 + 81.743 +static ALuint RecordProc(ALCdevice *Device) 81.744 +{ 81.745 + 81.746 + //printf("RLM: recordProc is begun!!\n"); 81.747 + // ALCdevice *Device = (ALCdevice*)ptr; 81.748 + 81.749 + record_data *data = (record_data*)Device->ExtraData; 81.750 + 81.751 + if(!data->killNow && Device->Connected) 81.752 + { 81.753 + 81.754 + if (AL_TRUE) 81.755 + { 81.756 + // the device does not seem to be "ready" until this point. 81.757 + init(Device); 81.758 + //init2(Device); 81.759 + //printf("\nMix Cycle %d\n", MixCount++); 81.760 + //every(Device); 81.761 + every2(Device); 81.762 + //later(Device); 81.763 + //printError(); 81.764 + //aluMixData(Device, NULL, Device->UpdateSize); 81.765 + //Sleep(3000); 81.766 + } 81.767 + } 81.768 + else { 81.769 + printf("WARNGING\n"); 81.770 + } 81.771 + 81.772 + return 0; 81.773 +} 81.774 + 81.775 + 81.776 +void init(ALCdevice *Device){ 81.777 + RUNONLY(1); 81.778 + printf("one time init\n"); 81.779 + printError(); 81.780 + printf("auxContext : %p\n", auxContext); 81.781 + auxContext = alcCreateContext(Device,NULL); 81.782 + printf("auxContext : %p\n", auxContext); 81.783 + printError(); 81.784 + printf("mainContext : %p\n", mainContext); 81.785 + mainContext = alcGetCurrentContext(); 81.786 + printf("mainContext : %p\n", mainContext); 81.787 + printError(); 81.788 + printf("setting listener properties\n"); 81.789 + alcMakeContextCurrent(auxContext); 81.790 + ALfloat val1; 81.791 + ALfloat val2; 81.792 + ALfloat val3; 81.793 + alGetListener3f(AL_POSITION, &val1, &val2, &val3); 81.794 + printf("location is [%f,%f,%f]\n", val1,val2,val3); 81.795 + alGetListener3f(AL_VELOCITY, &val1, &val2, &val3); 81.796 + printf("velocity is [%f,%f,%f]\n", val1,val2,val3); 81.797 + saveAux(Device); 81.798 + saveMain(Device); 81.799 +} 81.800 + 81.801 +void later(ALCdevice *Device){ 81.802 + // run only the third time it is called 81.803 + UNUSED(Device); 81.804 + RUNAT(3); 81.805 + printf("Suspending main Context....\n"); 81.806 + alcSuspendContext(mainContext); 81.807 + printError(); 81.808 + printf("Switching to aux Context...\n"); 81.809 + alcMakeContextCurrent(auxContext); 81.810 + printError(); 81.811 +} 81.812 + 81.813 + 81.814 + 81.815 +static ALCboolean record_open_playback(ALCdevice *device, const ALCchar *deviceName) 81.816 +{ 81.817 + record_data *data; 81.818 + // stop any buffering for stdout, so that I can 81.819 + // see the damm printf statements in my terminal immediatley 81.820 + setbuf(stdout, NULL); 81.821 + 81.822 + dprintf("open_playback is called.\n"); 81.823 + if(!deviceName) 81.824 + deviceName = recordDevice; 81.825 + else if(strcmp(deviceName, recordDevice) != 0) 81.826 + return ALC_FALSE; 81.827 + 81.828 + data = (record_data*)calloc(1, sizeof(*data)); 81.829 + 81.830 + device->szDeviceName = strdup(deviceName); 81.831 + data->robert = 5; 81.832 + device->ExtraData = data; 81.833 + 81.834 + return ALC_TRUE; 81.835 +} 81.836 + 81.837 +static void record_close_playback(ALCdevice *device) 81.838 +{ 81.839 + record_data *data = (record_data*)device->ExtraData; 81.840 + dprintf("RLM: close playback called\n"); 81.841 + free(data); 81.842 + device->ExtraData = NULL; 81.843 +} 81.844 + 81.845 + 81.846 + 81.847 + 81.848 + 81.849 +static ALCboolean record_reset_playback(ALCdevice *device) 81.850 +{ 81.851 + record_data *data = (record_data*)device->ExtraData; 81.852 + dprintf("RLM: reset playback called\n"); 81.853 + 81.854 + ALuint channels=0, bits=0; 81.855 + 81.856 + 81.857 + 81.858 + switch(device->FmtType) 81.859 + { 81.860 + case DevFmtByte: 81.861 + device->FmtType = DevFmtUByte; 81.862 + break; 81.863 + case DevFmtUShort: 81.864 + device->FmtType = DevFmtShort; 81.865 + break; 81.866 + case DevFmtUByte: 81.867 + case DevFmtShort: 81.868 + case DevFmtFloat: 81.869 + break; 81.870 + } 81.871 + bits = BytesFromDevFmt(device->FmtType) * 8; 81.872 + channels = ChannelsFromDevFmt(device->FmtChans); 81.873 + data->size = device->UpdateSize * channels * bits / 8; 81.874 + data->auxBuffer = malloc(data->size); 81.875 + data->mainBuffer = malloc(data->size); 81.876 + data->mainFull = AL_FALSE; 81.877 + data->auxFull = AL_FALSE; 81.878 + data->mainReady = AL_TRUE; 81.879 + data->auxReady = AL_TRUE; 81.880 + 81.881 + if(!data->mainBuffer || !data->auxBuffer) 81.882 + { 81.883 + ERR("Buffer malloc failed\n"); 81.884 + return ALC_FALSE; 81.885 + } 81.886 + 81.887 + //data->thread = StartThread(RecordProc, device); 81.888 + //data->thread = StartThread(noop, device); 81.889 + 81.890 + //TODO: shoudl free everything somewhere else! 81.891 + 81.892 + /* 81.893 + if(data->thread == NULL) 81.894 + { 81.895 + free(data->mainBuffer); 81.896 + free(data->auxBuffer); 81.897 + free(data->unPauseIDs); 81.898 + data->auxBuffer = NULL; 81.899 + data->mainBuffer = NULL; 81.900 + 81.901 + return ALC_FALSE; 81.902 + } 81.903 + */ 81.904 + return ALC_TRUE; 81.905 +} 81.906 + 81.907 + 81.908 + 81.909 +static void record_stop_playback(ALCdevice *device) 81.910 +{ 81.911 + record_data *data = (record_data*)device->ExtraData; 81.912 + dprintf("RLM: stop playback called\n"); 81.913 + printf("szName is %s \n", device->szDeviceName); 81.914 + printf("robert is %d \n", data->robert); 81.915 + 81.916 + 81.917 + if(!data->thread) 81.918 + return; 81.919 + 81.920 + data->killNow = 1; 81.921 + StopThread(data->thread); 81.922 + data->thread = NULL; 81.923 + 81.924 + data->killNow = 0; 81.925 +} 81.926 + 81.927 + 81.928 +static const BackendFuncs record_funcs = { 81.929 + record_open_playback, 81.930 + record_close_playback, 81.931 + record_reset_playback, 81.932 + record_stop_playback, 81.933 + NULL, 81.934 + NULL, /* These would be filled with functions to */ 81.935 + NULL, /* handle capturing audio if we did that. */ 81.936 + NULL, 81.937 + NULL, 81.938 + NULL 81.939 +}; 81.940 + 81.941 +ALCboolean alc_record_init(BackendFuncs *func_list) 81.942 +{ 81.943 + dprintf("RECORD: I'm InIT111\n"); 81.944 + *func_list = record_funcs; 81.945 + return ALC_TRUE; 81.946 +} 81.947 + 81.948 +void alc_record_deinit(void) 81.949 +{ 81.950 +} 81.951 + 81.952 +void alc_record_probe(enum DevProbe type) 81.953 +{ 81.954 + dprintf("RECORD: I'm being probed! :/\n"); 81.955 + 81.956 + switch(type) 81.957 + { 81.958 + case DEVICE_PROBE: 81.959 + AppendDeviceList(recordDevice); 81.960 + break; 81.961 + case ALL_DEVICE_PROBE: 81.962 + AppendAllDeviceList(recordDevice); 81.963 + break; 81.964 + case CAPTURE_DEVICE_PROBE: 81.965 + break; 81.966 + } 81.967 +} 81.968 + 81.969 + 81.970 + 81.971 + 81.972 +void printError(void){ 81.973 + ALenum error = alGetError(); 81.974 + printf("%s\n", GetALCErrorString(error)); 81.975 + printf("%s\n", GetALErrorString(error)); 81.976 +} 81.977 + 81.978 + 81.979 + 81.980 +char* GetALCErrorString(ALenum err) 81.981 +{ 81.982 + switch(err) 81.983 + { 81.984 + case ALC_NO_ERROR: 81.985 + return "AL_NO_ERROR"; 81.986 + break; 81.987 + 81.988 + case ALC_INVALID_DEVICE: 81.989 + return "ALC_INVALID_DEVICE"; 81.990 + break; 81.991 + 81.992 + case ALC_INVALID_CONTEXT: 81.993 + return "ALC_INVALID_CONTEXT"; 81.994 + break; 81.995 + 81.996 + case ALC_INVALID_ENUM: 81.997 + return "ALC_INVALID_ENUM"; 81.998 + break; 81.999 + 81.1000 + case ALC_INVALID_VALUE: 81.1001 + return "ALC_INVALID_VALUE"; 81.1002 + break; 81.1003 + 81.1004 + case ALC_OUT_OF_MEMORY: 81.1005 + return "ALC_OUT_OF_MEMORY"; 81.1006 + break; 81.1007 + }; 81.1008 + return "UNknown error."; 81.1009 +} 81.1010 + 81.1011 + 81.1012 + 81.1013 + 81.1014 + 81.1015 + 81.1016 + 81.1017 +char* GetALErrorString(ALenum err) 81.1018 +{ 81.1019 + switch(err) 81.1020 + { 81.1021 + case AL_NO_ERROR: 81.1022 + return "AL_NO_ERROR"; 81.1023 + break; 81.1024 + 81.1025 + case AL_INVALID_NAME: 81.1026 + return "AL_INVALID_NAME"; 81.1027 + break; 81.1028 + 81.1029 + case AL_INVALID_ENUM: 81.1030 + return "AL_INVALID_ENUM"; 81.1031 + break; 81.1032 + 81.1033 + case AL_INVALID_VALUE: 81.1034 + return "AL_INVALID_VALUE"; 81.1035 + break; 81.1036 + 81.1037 + case AL_INVALID_OPERATION: 81.1038 + return "AL_INVALID_OPERATION"; 81.1039 + break; 81.1040 + 81.1041 + case AL_OUT_OF_MEMORY: 81.1042 + return "AL_OUT_OF_MEMORY"; 81.1043 + break; 81.1044 + }; 81.1045 + return "UNknown error."; 81.1046 +} 81.1047 + 81.1048 + 81.1049 + 81.1050 + 81.1051 + 81.1052 + 81.1053 + 81.1054 +#include "com_aurellem_audioPlay_TestCall.h" 81.1055 + 81.1056 +JNIEXPORT void JNICALL Java_com_aurellem_audioPlay_TestCall_nprintGarbage 81.1057 +(JNIEnv *env, jclass clazz){ 81.1058 + UNUSED(env);UNUSED(clazz); 81.1059 + printf("Native! method* zzz\n"); 81.1060 + return; 81.1061 +} 81.1062 + 81.1063 +#include "com_aurellem_audioPlay_WavCaptureMaybe.h" 81.1064 + 81.1065 +JNIEXPORT void JNICALL Java_com_aurellem_audioPlay_WavCaptureMaybe_nrecord_1whatever 81.1066 +(JNIEnv *env, jclass clazz){ 81.1067 + UNUSED(env);UNUSED(clazz); 81.1068 + printf("record_aurellem_whatever!"); 81.1069 +} 81.1070 + 81.1071 + 81.1072 + 81.1073 + 81.1074 + 81.1075 + 81.1076 + 81.1077 + 81.1078 + 81.1079 + 81.1080 + 81.1081 + 81.1082 + 81.1083 + 81.1084 + 81.1085 + 81.1086 +//////////////////////////// Real JNI stuff //////////////////////////////// 81.1087 +void getMainSamples(ALCvoid *buffer){ 81.1088 + UNUSED(buffer); 81.1089 + // memcpy(mainBuffer, (ALubyte*) buffer, samples); 81.1090 +} 81.1091 + 81.1092 +void getAuxSamples(ALCvoid *buffer){ 81.1093 + UNUSED(buffer); 81.1094 + // memcpy(auxBuffer, (ALubyte*) buffer, samples); 81.1095 +} 81.1096 + 81.1097 +#include "com_jme3_capture_RecordAudioRenderer.h" 81.1098 + 81.1099 +/* 81.1100 + * Class: com_jme3_capture_RecordAudioRenderer 81.1101 + * Method: helloEveryone 81.1102 + * Signature: ()V 81.1103 + */ 81.1104 +JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_helloEveryone 81.1105 +(JNIEnv *env, jclass clazz){ 81.1106 + UNUSED(env);UNUSED(clazz); 81.1107 + printf("\n**************\nC from Java: I'm audioRecorder :)\n***********\n"); 81.1108 +} 81.1109 + 81.1110 + 81.1111 +/* 81.1112 + * Class: com_jme3_capture_RecordAudioRenderer 81.1113 + * Method: nstep 81.1114 + * Signature: ()V 81.1115 + */ 81.1116 +JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nstep 81.1117 +(JNIEnv *env, jclass clazz, jlong device){ 81.1118 + UNUSED(env);UNUSED(clazz);UNUSED(device); 81.1119 + //printf("C from Java: I'm audioRecorder -- nstep :)\n"); 81.1120 + RecordProc((ALCdevice*)((intptr_t)device)); 81.1121 +} 81.1122 + 81.1123 +/* 81.1124 + * Class: com_jme3_capture_RecordAudioRenderer 81.1125 + * Method: ngetMainSamples 81.1126 + * Signature: (JLjava/nio/ByteBuffer;I)V 81.1127 + */ 81.1128 +JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_ngetMainSamples 81.1129 +(JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position){ 81.1130 + UNUSED(clazz); 81.1131 + 81.1132 + ALvoid *buffer_address = 81.1133 + ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); 81.1134 + ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); 81.1135 + //printf("getMainSamples: device is %p\n", recorder); 81.1136 + record_data *data = (record_data*)recorder->ExtraData; 81.1137 + if (!data->mainFull){ 81.1138 + printf("data is not ready!\n"); 81.1139 + return; 81.1140 + } 81.1141 + memcpy(buffer_address, data->mainBuffer, data->size); 81.1142 + data->mainFull = AL_FALSE; 81.1143 +} 81.1144 + 81.1145 +/* 81.1146 + * Class: com_jme3_capture_RecordAudioRenderer 81.1147 + * Method: ngetAuxSamples 81.1148 + * Signature: (JLjava/nio/ByteBuffer;I)V 81.1149 + */ 81.1150 +JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_ngetAuxSamples 81.1151 + (JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position){ 81.1152 + UNUSED(clazz); 81.1153 + 81.1154 + ALvoid *buffer_address = 81.1155 + ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); 81.1156 + ALCdevice *recorder = (ALCdevice*) ((intptr_t)device); 81.1157 + //printf("getMainSamples: device is %p\n", recorder); 81.1158 + record_data *data = (record_data*)recorder->ExtraData; 81.1159 + 81.1160 + memcpy(buffer_address, data->auxBuffer, data->size); 81.1161 + 81.1162 +} 81.1163 + 81.1164 + 81.1165 +/* 81.1166 + * Class: com_jme3_capture_RecordAudioRenderer 81.1167 + * Method: nsetAuxListener3f 81.1168 + * Signature: (IFFF)V 81.1169 + */ 81.1170 +JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nsetAuxListener3f 81.1171 +(JNIEnv *env, jclass clazz, jint pname, jfloat v1, jfloat v2, jfloat v3){ 81.1172 + UNUSED(env);UNUSED(clazz); 81.1173 + aux_alListener3f(pname, v1, v2, v3); 81.1174 +} 81.1175 + 81.1176 +/* 81.1177 + * Class: com_jme3_capture_RecordAudioRenderer 81.1178 + * Method: nsetAuxListenerf 81.1179 + * Signature: (IF)V 81.1180 + */ 81.1181 +JNIEXPORT void JNICALL Java_com_jme3_capture_RecordAudioRenderer_nsetAuxListenerf 81.1182 +(JNIEnv *env, jclass clazz, jint pname, jfloat v1){ 81.1183 + UNUSED(env);UNUSED(clazz); 81.1184 + aux_alListenerf(pname, v1); 81.1185 +} 81.1186 + 81.1187 + 81.1188 + 81.1189 +/* 81.1190 +static void JNICALL Java_org_lwjgl_openal_ALC11_nalcCaptureSamples 81.1191 +(JNIEnv *env, jclass clazz, jlong device, jobject buffer, jint position, jint samples) { 81.1192 + ALvoid *buffer_address = 81.1193 + ((ALbyte *)(((char*)(*env)->GetDirectBufferAddress(env, buffer)) + position)); 81.1194 + alcCaptureSamples((ALCdevice*) ((intptr_t)device), buffer_address, samples); 81.1195 +} 81.1196 +*/ 81.1197 + 81.1198 + 81.1199 + 81.1200 + 81.1201 + 81.1202 +
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 82.2 +++ b/src/body/ear.clj Tue Oct 25 13:02:31 2011 -0700 82.3 @@ -0,0 +1,53 @@ 82.4 + 82.5 +(ns body.ear) 82.6 +(use 'cortex.world) 82.7 +(use 'cortex.import) 82.8 +(use 'clojure.contrib.def) 82.9 +(cortex.import/mega-import-jme3) 82.10 +(rlm.rlm-commands/help) 82.11 +(import java.nio.ByteBuffer) 82.12 +(import java.awt.image.BufferedImage) 82.13 +(import java.awt.Color) 82.14 +(import java.awt.Dimension) 82.15 +(import java.awt.Graphics) 82.16 +(import java.awt.Graphics2D) 82.17 +(import java.awt.event.WindowAdapter) 82.18 +(import java.awt.event.WindowEvent) 82.19 +(import java.awt.image.BufferedImage) 82.20 +(import java.nio.ByteBuffer) 82.21 +(import javax.swing.JFrame) 82.22 +(import javax.swing.JPanel) 82.23 +(import javax.swing.SwingUtilities) 82.24 +(import javax.swing.ImageIcon) 82.25 +(import javax.swing.JOptionPane) 82.26 +(import java.awt.image.ImageObserver) 82.27 +(in-ns 'body.ear) 82.28 +(import 'com.jme3.capture.SoundProcessor) 82.29 + 82.30 + 82.31 +(defn sound-processor 82.32 + "deals with converting ByteBuffers into Vectors of Bytes so that the 82.33 + continuation functions can be defined in terms of immutable stuff." 82.34 + [continuation] 82.35 + (proxy [SoundProcessor] [] 82.36 + (cleanup []) 82.37 + (process 82.38 + [#^ByteBuffer audioSamples numSamples] 82.39 + 82.40 + (let [byte-array (make-array Byte numSamples)] 82.41 + (.get audioSamples byte-array 0 numSamples) 82.42 + 82.43 + (continuation 82.44 + (vec byte-array)))))) 82.45 + 82.46 + 82.47 +(defn add-ear 82.48 + "add an ear to the world. The continuation function will be called 82.49 + on the FFT or the sounds which the ear hears in the given 82.50 + timeframe. Sound is 3D." 82.51 + [world ear continuation] 82.52 + (let [listener (Listener.) 82.53 + renderer (.getAudioRenderer world)] 82.54 + (.addListener renderer listener) 82.55 + (.registerSoundProcessor renderer listener (sound-processor continuation)) 82.56 + listener))
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 83.2 +++ b/todo.org Tue Oct 25 13:02:31 2011 -0700 83.3 @@ -0,0 +1,53 @@ 83.4 +* Tasks to do relating to the Aurellem recorder device. 83.5 + 83.6 + 83.7 + 83.8 +** Cleanup 83.9 +- [ ] come up with a good name for the recording device. 83.10 +- [X] shift stepping functions to =nstep= 83.11 +- [ ] make a new project that Uses openal-soft but is not inside it 83.12 +- [ ] transfer all of my stuff to this project (everntually, we'll hava a "record" artifact) 83.13 +- [ ] put everything into an org file 83.14 +- [ ] make a post on aurellem 83.15 +- [ ] make a post on jMonkeyEngine forums 83.16 + 83.17 +** New Features 83.18 +- [ ] enable multiple listeners / multiple data 83.19 +- [ ] add support for streaming sources. 83.20 + 83.21 + 83.22 +** Java Integration 83.23 +- [ ] watch out for playSourceInstance and make sure it's handled correctly! 83.24 +- [ ] figure out how to compile for all platforms 83.25 +- [ ] get jMonkeyEngine to auto-load the new artifacts. 83.26 +- [X] properly extend the AudioRenderer instead of copying everything over. 83.27 +- [ ] combine with video recorder to make an easy-to-use thing for the main case. 83.28 + 83.29 +** Clojure Integration 83.30 +- [ ] abstract to closure =(ear)= function. 83.31 + 83.32 +** Testing 83.33 +- [X] make sure it works for effects (NOT GOING TO DO!), jMonkeyEngine doesn't do it well. 83.34 +- [ ] make an automated test using two listeners that are in the exact same area. 83.35 + 83.36 + 83.37 +** Conversion to multiple listeners. 83.38 +- [ ] make every function call manage context switching automatically 83.39 +- [ ] gather up all data necessary for context switching in a struct. 83.40 +- [ ] nmake a map/list of these structures in the ExtraData device field. 83.41 +- [ ] 83.42 + 83.43 + 83.44 + 83.45 + 83.46 + 83.47 + 83.48 + 83.49 + 83.50 + 83.51 + 83.52 + 83.53 + 83.54 + 83.55 + 83.56 +
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 84.2 +++ b/update-jme.sh Tue Oct 25 13:02:31 2011 -0700 84.3 @@ -0,0 +1,15 @@ 84.4 +#!/bin/sh 84.5 + 84.6 + 84.7 +ln -sf /home/r/proj/audio-send/build/libopenal.so \ 84.8 + /home/r/proj/jMonkeyEngine3/lib/lwjgl/native/linux/audioSend/libopenal64.so; 84.9 + 84.10 +cp -v /home/r/proj/cortex/assets/Sounds/pure.wav /home/r/proj/jMonkeyEngine3/bin/Sound/Effects/pure.wav; 84.11 + 84.12 +cp -v /home/r/proj/cortex/assets/Sounds/dream.wav /home/r/proj/jMonkeyEngine3/bin/Sound/Effects/dream.wav; 84.13 + 84.14 +cp -v /home/r/proj/cortex/assets/Sounds/silence.wav /home/r/proj/jMonkeyEngine3/bin/Sound/Effects/silence.wav; 84.15 + 84.16 + 84.17 +cd /home/r/proj/jMonkeyEngine3/lib/lwjgl; 84.18 +jar uf jME3-lwjgl-natives.jar native/linux/audioSend/
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 85.2 +++ b/utils/openal-info.c Tue Oct 25 13:02:31 2011 -0700 85.3 @@ -0,0 +1,365 @@ 85.4 +/* 85.5 + * OpenAL Info Utility 85.6 + * 85.7 + * Copyright (c) 2010 by Chris Robinson <chris.kcat@gmail.com> 85.8 + * 85.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy 85.10 + * of this software and associated documentation files (the "Software"), to deal 85.11 + * in the Software without restriction, including without limitation the rights 85.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 85.13 + * copies of the Software, and to permit persons to whom the Software is 85.14 + * furnished to do so, subject to the following conditions: 85.15 + * 85.16 + * The above copyright notice and this permission notice shall be included in 85.17 + * all copies or substantial portions of the Software. 85.18 + * 85.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 85.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 85.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 85.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 85.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 85.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 85.25 + * THE SOFTWARE. 85.26 + */ 85.27 + 85.28 +#include <stdio.h> 85.29 +#include <string.h> 85.30 + 85.31 +#include "AL/alc.h" 85.32 +#include "AL/al.h" 85.33 +#include "AL/alext.h" 85.34 + 85.35 +#ifndef ALC_ENUMERATE_ALL_EXT 85.36 +#define ALC_DEFAULT_ALL_DEVICES_SPECIFIER 0x1012 85.37 +#define ALC_ALL_DEVICES_SPECIFIER 0x1013 85.38 +#endif 85.39 + 85.40 +#ifndef ALC_EXT_EFX 85.41 +#define ALC_EFX_MAJOR_VERSION 0x20001 85.42 +#define ALC_EFX_MINOR_VERSION 0x20002 85.43 +#define ALC_MAX_AUXILIARY_SENDS 0x20003 85.44 +#define AL_FILTER_TYPE 0x8001 85.45 +#define AL_FILTER_NULL 0x0000 85.46 +#define AL_FILTER_LOWPASS 0x0001 85.47 +#define AL_FILTER_HIGHPASS 0x0002 85.48 +#define AL_FILTER_BANDPASS 0x0003 85.49 +#define AL_EFFECT_TYPE 0x8001 85.50 +#define AL_EFFECT_NULL 0x0000 85.51 +#define AL_EFFECT_EAXREVERB 0x8000 85.52 +#define AL_EFFECT_REVERB 0x0001 85.53 +#define AL_EFFECT_CHORUS 0x0002 85.54 +#define AL_EFFECT_DISTORTION 0x0003 85.55 +#define AL_EFFECT_ECHO 0x0004 85.56 +#define AL_EFFECT_FLANGER 0x0005 85.57 +#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 85.58 +#define AL_EFFECT_VOCAL_MORPHER 0x0007 85.59 +#define AL_EFFECT_PITCH_SHIFTER 0x0008 85.60 +#define AL_EFFECT_RING_MODULATOR 0x0009 85.61 +#define AL_EFFECT_AUTOWAH 0x000A 85.62 +#define AL_EFFECT_COMPRESSOR 0x000B 85.63 +#define AL_EFFECT_EQUALIZER 0x000C 85.64 +typedef void (AL_APIENTRY *LPALGENFILTERS)(ALsizei, ALuint*); 85.65 +typedef void (AL_APIENTRY *LPALDELETEFILTERS)(ALsizei, ALuint*); 85.66 +typedef void (AL_APIENTRY *LPALFILTERI)(ALuint, ALenum, ALint); 85.67 +typedef void (AL_APIENTRY *LPALGENEFFECTS)(ALsizei, ALuint*); 85.68 +typedef void (AL_APIENTRY *LPALDELETEEFFECTS)(ALsizei, ALuint*); 85.69 +typedef void (AL_APIENTRY *LPALEFFECTI)(ALuint, ALenum, ALint); 85.70 +#endif 85.71 +static LPALGENFILTERS palGenFilters; 85.72 +static LPALDELETEFILTERS palDeleteFilters; 85.73 +static LPALFILTERI palFilteri; 85.74 +static LPALGENEFFECTS palGenEffects; 85.75 +static LPALDELETEEFFECTS palDeleteEffects; 85.76 +static LPALEFFECTI palEffecti; 85.77 + 85.78 +#ifndef ALC_EXT_DEDICATED 85.79 +#define AL_EFFECT_DEDICATED_DIALOGUE 0x9001 85.80 +#define AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT 0x9000 85.81 +#endif 85.82 + 85.83 + 85.84 +#define MAX_WIDTH 80 85.85 + 85.86 +static void printList(const char *list, char separator) 85.87 +{ 85.88 + size_t col = MAX_WIDTH, len; 85.89 + const char *indent = " "; 85.90 + const char *next; 85.91 + 85.92 + if(!list || *list == '\0') 85.93 + { 85.94 + fprintf(stdout, "\n%s!!! none !!!\n", indent); 85.95 + return; 85.96 + } 85.97 + 85.98 + do { 85.99 + next = strchr(list, separator); 85.100 + if(next) 85.101 + { 85.102 + len = next-list; 85.103 + do { 85.104 + next++; 85.105 + } while(*next == separator); 85.106 + } 85.107 + else 85.108 + len = strlen(list); 85.109 + 85.110 + if(len + col + 2 >= MAX_WIDTH) 85.111 + { 85.112 + fprintf(stdout, "\n%s", indent); 85.113 + col = strlen(indent); 85.114 + } 85.115 + else 85.116 + { 85.117 + fputc(' ', stdout); 85.118 + col++; 85.119 + } 85.120 + 85.121 + len = fwrite(list, 1, len, stdout); 85.122 + col += len; 85.123 + 85.124 + if(!next || *next == '\0') 85.125 + break; 85.126 + fputc(',', stdout); 85.127 + col++; 85.128 + 85.129 + list = next; 85.130 + } while(1); 85.131 + fputc('\n', stdout); 85.132 +} 85.133 + 85.134 +static void printDeviceList(const char *list) 85.135 +{ 85.136 + if(!list || *list == '\0') 85.137 + printf(" !!! none !!!\n"); 85.138 + else do { 85.139 + printf(" %s\n", list); 85.140 + list += strlen(list) + 1; 85.141 + } while(*list != '\0'); 85.142 +} 85.143 + 85.144 + 85.145 +static ALenum checkALErrors(int linenum) 85.146 +{ 85.147 + ALenum err = alGetError(); 85.148 + if(err != AL_NO_ERROR) 85.149 + printf("OpenAL Error: %s (0x%x), @ %d\n", alGetString(err), err, linenum); 85.150 + return err; 85.151 +} 85.152 +#define checkALErrors() checkALErrors(__LINE__) 85.153 + 85.154 +static ALCenum checkALCErrors(ALCdevice *device, int linenum) 85.155 +{ 85.156 + ALCenum err = alcGetError(device); 85.157 + if(err != ALC_NO_ERROR) 85.158 + printf("ALC Error: %s (0x%x), @ %d\n", alcGetString(device, err), err, linenum); 85.159 + return err; 85.160 +} 85.161 +#define checkALCErrors(x) checkALCErrors((x),__LINE__) 85.162 + 85.163 + 85.164 +static void printALCInfo(ALCdevice *device) 85.165 +{ 85.166 + ALCint major, minor; 85.167 + 85.168 + alcGetIntegerv(device, ALC_MAJOR_VERSION, 1, &major); 85.169 + alcGetIntegerv(device, ALC_MINOR_VERSION, 1, &minor); 85.170 + if(checkALCErrors(device) == ALC_NO_ERROR) 85.171 + printf("ALC version: %d.%d\n", major, minor); 85.172 + if(device) 85.173 + { 85.174 + printf("ALC extensions:"); 85.175 + printList(alcGetString(device, ALC_EXTENSIONS), ' '); 85.176 + checkALCErrors(device); 85.177 + } 85.178 +} 85.179 + 85.180 +static void printALInfo(void) 85.181 +{ 85.182 + printf("OpenAL vendor string: %s\n", alGetString(AL_VENDOR)); 85.183 + printf("OpenAL renderer string: %s\n", alGetString(AL_RENDERER)); 85.184 + printf("OpenAL version string: %s\n", alGetString(AL_VERSION)); 85.185 + printf("OpenAL extensions:"); 85.186 + printList(alGetString(AL_EXTENSIONS), ' '); 85.187 + checkALErrors(); 85.188 +} 85.189 + 85.190 +static void printEFXInfo(ALCdevice *device) 85.191 +{ 85.192 + ALCint major, minor, sends; 85.193 + ALuint obj; 85.194 + int i; 85.195 + const ALenum filters[] = { 85.196 + AL_FILTER_LOWPASS, AL_FILTER_HIGHPASS, AL_FILTER_BANDPASS, 85.197 + AL_FILTER_NULL 85.198 + }; 85.199 + char filterNames[] = "Low-pass,High-pass,Band-pass,"; 85.200 + const ALenum effects[] = { 85.201 + AL_EFFECT_EAXREVERB, AL_EFFECT_REVERB, AL_EFFECT_CHORUS, 85.202 + AL_EFFECT_DISTORTION, AL_EFFECT_ECHO, AL_EFFECT_FLANGER, 85.203 + AL_EFFECT_FREQUENCY_SHIFTER, AL_EFFECT_VOCAL_MORPHER, 85.204 + AL_EFFECT_PITCH_SHIFTER, AL_EFFECT_RING_MODULATOR, AL_EFFECT_AUTOWAH, 85.205 + AL_EFFECT_COMPRESSOR, AL_EFFECT_EQUALIZER, AL_EFFECT_NULL 85.206 + }; 85.207 + const ALenum dedeffects[] = { 85.208 + AL_EFFECT_DEDICATED_DIALOGUE, 85.209 + AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, AL_EFFECT_NULL 85.210 + }; 85.211 + char effectNames[] = "EAX Reverb,Reverb,Chorus,Distortion,Echo,Flanger," 85.212 + "Frequency Shifter,Vocal Morpher,Pitch Shifter," 85.213 + "Ring Modulator,Autowah,Compressor,Equalizer," 85.214 + "Dedicated Dialog,Dedicated LFE,"; 85.215 + char *current; 85.216 + 85.217 + if(alcIsExtensionPresent(device, "ALC_EXT_EFX") == AL_FALSE) 85.218 + { 85.219 + printf("EFX not available\n"); 85.220 + return; 85.221 + } 85.222 + 85.223 + alcGetIntegerv(device, ALC_EFX_MAJOR_VERSION, 1, &major); 85.224 + alcGetIntegerv(device, ALC_EFX_MINOR_VERSION, 1, &minor); 85.225 + if(checkALCErrors(device) == ALC_NO_ERROR) 85.226 + printf("EFX version: %d.%d\n", major, minor); 85.227 + alcGetIntegerv(device, ALC_MAX_AUXILIARY_SENDS, 1, &sends); 85.228 + if(checkALCErrors(device) == ALC_NO_ERROR) 85.229 + printf("Max auxiliary sends: %d\n", sends); 85.230 + 85.231 + palGenFilters = alGetProcAddress("alGenFilters"); 85.232 + palDeleteFilters = alGetProcAddress("alDeleteFilters"); 85.233 + palFilteri = alGetProcAddress("alFilteri"); 85.234 + palGenEffects = alGetProcAddress("alGenEffects"); 85.235 + palDeleteEffects = alGetProcAddress("alDeleteEffects"); 85.236 + palEffecti = alGetProcAddress("alEffecti"); 85.237 + if(checkALErrors() != AL_NO_ERROR || 85.238 + !palGenFilters || !palDeleteFilters || !palFilteri || 85.239 + !palGenEffects || !palDeleteEffects || !palEffecti) 85.240 + { 85.241 + printf("!!! Missing EFX functions !!!\n"); 85.242 + return; 85.243 + } 85.244 + 85.245 + palGenFilters(1, &obj); 85.246 + if(checkALErrors() == AL_NO_ERROR) 85.247 + { 85.248 + current = filterNames; 85.249 + for(i = 0;filters[i] != AL_FILTER_NULL;i++) 85.250 + { 85.251 + char *next = strchr(current, ','); 85.252 + 85.253 + palFilteri(obj, AL_FILTER_TYPE, filters[i]); 85.254 + if(alGetError() == AL_NO_ERROR) 85.255 + current = next+1; 85.256 + else 85.257 + memmove(current, next+1, strlen(next)); 85.258 + } 85.259 + palDeleteFilters(1, &obj); 85.260 + checkALErrors(); 85.261 + 85.262 + printf("Supported filters:"); 85.263 + printList(filterNames, ','); 85.264 + } 85.265 + 85.266 + palGenEffects(1, &obj); 85.267 + if(checkALErrors() == AL_NO_ERROR) 85.268 + { 85.269 + current = effectNames; 85.270 + for(i = 0;effects[i] != AL_EFFECT_NULL;i++) 85.271 + { 85.272 + char *next = strchr(current, ','); 85.273 + 85.274 + palEffecti(obj, AL_EFFECT_TYPE, effects[i]); 85.275 + if(alGetError() == AL_NO_ERROR) 85.276 + current = next+1; 85.277 + else 85.278 + memmove(current, next+1, strlen(next)); 85.279 + } 85.280 + if(alcIsExtensionPresent(device, "ALC_EXT_DEDICATED")) 85.281 + { 85.282 + for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++) 85.283 + { 85.284 + char *next = strchr(current, ','); 85.285 + 85.286 + palEffecti(obj, AL_EFFECT_TYPE, dedeffects[i]); 85.287 + if(alGetError() == AL_NO_ERROR) 85.288 + current = next+1; 85.289 + else 85.290 + memmove(current, next+1, strlen(next)); 85.291 + } 85.292 + } 85.293 + else 85.294 + { 85.295 + for(i = 0;dedeffects[i] != AL_EFFECT_NULL;i++) 85.296 + { 85.297 + char *next = strchr(current, ','); 85.298 + memmove(current, next+1, strlen(next)); 85.299 + } 85.300 + } 85.301 + palDeleteEffects(1, &obj); 85.302 + checkALErrors(); 85.303 + 85.304 + printf("Supported effects:"); 85.305 + printList(effectNames, ','); 85.306 + } 85.307 +} 85.308 + 85.309 +int main(int argc, char *argv[]) 85.310 +{ 85.311 + ALCdevice *device; 85.312 + ALCcontext *context; 85.313 + 85.314 + if(argc > 1 && (strcmp(argv[1], "--help") == 0 || 85.315 + strcmp(argv[1], "-h") == 0)) 85.316 + { 85.317 + printf("Usage: %s [playback device]\n", argv[0]); 85.318 + return 0; 85.319 + } 85.320 + 85.321 + printf("Available playback devices:\n"); 85.322 + if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE) 85.323 + printDeviceList(alcGetString(NULL, ALC_ALL_DEVICES_SPECIFIER)); 85.324 + else 85.325 + printDeviceList(alcGetString(NULL, ALC_DEVICE_SPECIFIER)); 85.326 + printf("Available capture devices:\n"); 85.327 + printDeviceList(alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER)); 85.328 + 85.329 + if(alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE) 85.330 + printf("Default playback device: %s\n", 85.331 + alcGetString(NULL, ALC_DEFAULT_ALL_DEVICES_SPECIFIER)); 85.332 + else 85.333 + printf("Default playback device: %s\n", 85.334 + alcGetString(NULL, ALC_DEFAULT_DEVICE_SPECIFIER)); 85.335 + printf("Default capture device: %s\n", 85.336 + alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)); 85.337 + 85.338 + printALCInfo(NULL); 85.339 + 85.340 + device = alcOpenDevice((argc>1) ? argv[1] : NULL); 85.341 + if(!device) 85.342 + { 85.343 + printf("\n!!! Failed to open %s !!!\n\n", ((argc>1) ? argv[1] : "default device")); 85.344 + return 1; 85.345 + } 85.346 + 85.347 + printf("\n** Info for device \"%s\" **\n", alcGetString(device, ALC_DEVICE_SPECIFIER)); 85.348 + printALCInfo(device); 85.349 + 85.350 + context = alcCreateContext(device, NULL); 85.351 + if(!context || alcMakeContextCurrent(context) == ALC_FALSE) 85.352 + { 85.353 + if(context) 85.354 + alcDestroyContext(context); 85.355 + alcCloseDevice(device); 85.356 + printf("\n!!! Failed to set a context !!!\n\n"); 85.357 + return 1; 85.358 + } 85.359 + 85.360 + printALInfo(); 85.361 + printEFXInfo(device); 85.362 + 85.363 + alcMakeContextCurrent(NULL); 85.364 + alcDestroyContext(context); 85.365 + alcCloseDevice(device); 85.366 + 85.367 + return 0; 85.368 +}