changeset 0:f9476ff7637e

initial forking of open-al to create multiple listeners
author Robert McIntyre <rlm@mit.edu>
date Tue, 25 Oct 2011 13:02:31 -0700
parents
children c41d773a85fb
files .hgignore Alc/ALc.c Alc/ALu.c Alc/alcConfig.c Alc/alcDedicated.c Alc/alcEcho.c Alc/alcModulator.c Alc/alcReverb.c Alc/alcRing.c Alc/alcThread.c Alc/backends/alsa.c Alc/backends/coreaudio.c Alc/backends/dsound.c Alc/backends/loopback.c Alc/backends/mmdevapi.c Alc/backends/null.c Alc/backends/opensl.c Alc/backends/oss.c Alc/backends/portaudio.c Alc/backends/pulseaudio.c Alc/backends/send.c Alc/backends/sndio.c Alc/backends/solaris.c Alc/backends/wave.c Alc/backends/winmm.c Alc/bs2b.c Alc/helpers.c Alc/hrtf.c Alc/hrtf_tables.inc Alc/mixer.c Alc/panning.c Alc/utils.c CMakeLists-works.txt CMakeLists.txt COPYING OpenAL32/Include/alAuxEffectSlot.h OpenAL32/Include/alBuffer.h OpenAL32/Include/alEffect.h OpenAL32/Include/alError.h OpenAL32/Include/alFilter.h OpenAL32/Include/alListener.h OpenAL32/Include/alMain.h OpenAL32/Include/alSource.h OpenAL32/Include/alState.h OpenAL32/Include/alThunk.h OpenAL32/Include/alu.h OpenAL32/Include/bs2b.h OpenAL32/Include/com_aurellem_capture_AudioSend.h OpenAL32/alAuxEffectSlot.c OpenAL32/alBuffer.c OpenAL32/alEffect.c OpenAL32/alError.c OpenAL32/alExtension.c OpenAL32/alFilter.c OpenAL32/alListener.c OpenAL32/alSource.c OpenAL32/alState.c OpenAL32/alThunk.c README RecordAudioRenderer.java XCompile.txt alsoftrc.sample bugs-in-openal.org cleanup-message.txt cmake/CheckCCompilerFlag.cmake cmake/CheckSharedFunctionExists.cmake config.h.in device_details.org ear.html ear.org html/add-new-device.html html/send.html include/AL/al.h include/AL/alc.h include/AL/alext.h include/AL/efx-creative.h include/AL/efx.h openal.pc.in org/add-new-device.org org/send.org record.c src/body/ear.clj todo.org update-jme.sh utils/openal-info.c
diffstat 85 files changed, 36393 insertions(+), 0 deletions(-) [+]
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, &param);
  27.231 +    }
  27.232 +    else
  27.233 +    {
  27.234 +        param.sched_priority = 0;
  27.235 +        failed = !!pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
  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 &raquo;"/> 
   69.96 +    </form>
   69.97 +    -->
   69.98 +  </div>
   69.99 +
  69.100 +  <h1>aurellem <em>&#x2609;</em></h1>
  69.101 +  <ul class="nav">
  69.102 +    <li><a href="/">read the blog &raquo;</a></li>
  69.103 +    <!-- li><a href="#">learn about us &raquo;</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 &raquo;"/> 
   71.96 +    </form>
   71.97 +    -->
   71.98 +  </div>
   71.99 +
  71.100 +  <h1>aurellem <em>&#x2609;</em></h1>
  71.101 +  <ul class="nav">
  71.102 +    <li><a href="/">read the blog &raquo;</a></li>
  71.103 +    <!-- li><a href="#">learn about us &raquo;</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/&lt;your-device&gt;.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/&lt;your-device&gt;.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> &lt;your-device&gt;_device[] = &lt;your-device-name&gt;;
  71.148 +
  71.149 +<span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> <span style="color: #f0dfaf;">alc_</span>&lt;your-device&gt;_init(BackendFuncs *func_list)
  71.150 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_</span>&lt;your-device&gt;_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> &lt;your-device&gt;_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> &lt;your-device&gt;_close_playback(ALCdevice *device)
  71.154 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">ALCboolean</span> &lt;your-device&gt;_reset_playback(ALCdevice *device)
  71.155 +<span style="color: #f0dfaf; font-weight: bold;">static</span> <span style="color: #dfdfbf; font-weight: bold;">void</span> &lt;your-device&gt;_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>&lt;your-device&gt;_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(&lt;your-device&gt;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(&lt;your-device&gt;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> &lt;your-device&gt;_funcs = {
  71.183 +    &lt;your-device&gt;_open_playback,
  71.184 +    &lt;your-device&gt;_close_playback,
  71.185 +    &lt;your-device&gt;_reset_playback,
  71.186 +    &lt;your-device&gt;_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>&lt;your-device&gt;_init(BackendFuncs *func_list);
  71.213 +<span style="color: #dfdfbf; font-weight: bold;">void</span> <span style="color: #f0dfaf;">alc_</span>&lt;your-device&gt;_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>&lt;your-device&gt;_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;">"&lt;your-device&gt;"</span>, alc_&lt;your-device&gt;_init, 
  71.233 +         alc_&lt;your-device&gt;_deinit, alc_&lt;your-device&gt;_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 &lt;your-device&gt; device
  71.269 +              Alc/backends/&lt;your-device&gt;.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> = &lt;your-device&gt;
  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 &raquo;"/> 
   72.96 +    </form>
   72.97 +    -->
   72.98 +  </div>
   72.99 +
  72.100 +  <h1>aurellem <em>&#x2609;</em></h1>
  72.101 +  <ul class="nav">
  72.102 +    <li><a href="/">read the blog &raquo;</a></li>
  72.103 +    <!-- li><a href="#">learn about us &raquo;</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;">&lt;stdlib.h&gt;</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;">&lt;jni.h&gt;</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, &amp;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, &amp;value1, &amp;value2, &amp;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-&gt;source;
  72.204 +  <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">slave</span> = slaveSource-&gt;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, &amp;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, &amp;master_buffer);
  72.237 +    alcMakeContextCurrent(slaveCtx);
  72.238 +    alGetSourcei(slave, AL_BUFFER, &amp;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, &amp;masterState);
  72.250 +  alcMakeContextCurrent(slaveCtx);
  72.251 +  alGetSourcei(slave, AL_SOURCE_STATE, &amp;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> = &amp;(master-&gt;SourceMap);
  72.272 +  <span style="color: #dfdfbf; font-weight: bold;">UIntMap</span> *<span style="color: #f0dfaf;">slaveSourceMap</span> = &amp;(slave-&gt;SourceMap);
  72.273 +  <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">numMasterSources</span> = masterSourceMap-&gt;size;
  72.274 +  <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">numSlaveSources</span> = slaveSourceMap-&gt;size;
  72.275 +
  72.276 +  alcMakeContextCurrent(slave);
  72.277 +  <span style="color: #f0dfaf; font-weight: bold;">if</span> (numSlaveSources &lt; 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 &lt; masterSourceMap-&gt;size; i++){
  72.288 +    syncSources((<span style="color: #dfdfbf; font-weight: bold;">ALsource</span>*)masterSourceMap-&gt;array[i].value,
  72.289 +                (<span style="color: #dfdfbf; font-weight: bold;">ALsource</span>*)slaveSourceMap-&gt;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-&gt;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-&gt;numContexts &gt;= data-&gt;maxContexts){
  72.299 +    <span style="color: #dfdfbf; font-weight: bold;">ALuint</span> <span style="color: #f0dfaf;">newMaxContexts</span> = data-&gt;maxContexts*2 + 1;
  72.300 +    data-&gt;contexts = realloc(data-&gt;contexts, newMaxContexts*<span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(context_data));
  72.301 +    data-&gt;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-&gt;renderBuffer = malloc(data-&gt;size);
  72.307 +  ctxData-&gt;ctx = context;
  72.308 +
  72.309 +  data-&gt;contexts[data-&gt;numContexts] = ctxData;
  72.310 +  data-&gt;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-&gt;ClickRemoval, ctxData-&gt;ClickRemoval, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)*MAXCHANNELS);
  72.321 +  memcpy(Device-&gt;PendingClicks, ctxData-&gt;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-&gt;ClickRemoval, Device-&gt;ClickRemoval, <span style="color: #f0dfaf; font-weight: bold;">sizeof</span>(ALfloat)*MAXCHANNELS);
  72.326 +  memcpy(ctxData-&gt;PendingClicks, Device-&gt;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-&gt;Contexts;
  72.338 +  currentNumContext  = Device-&gt;NumContexts;
  72.339 +  Device-&gt;Contexts = &amp;ctx;
  72.340 +  Device-&gt;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-&gt;Contexts = currentContext;
  72.345 +  Device-&gt;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-&gt;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-&gt;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 &lt; data-&gt;numContexts; i++){
  72.367 +    syncContexts(data-&gt;contexts[0]-&gt;ctx , data-&gt;contexts[i]-&gt;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 &gt; Device-&gt;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-&gt;UpdateSize);
  72.373 +    samples = (<span style="color: #dfdfbf; font-weight: bold;">int</span>) Device-&gt;UpdateSize;
  72.374 +  }
  72.375 +
  72.376 +  <span style="color: #f0dfaf; font-weight: bold;">for</span> (i = 0; i &lt; data-&gt;numContexts; i++){
  72.377 +    <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span> = data-&gt;contexts[i];
  72.378 +    <span style="color: #dfdfbf; font-weight: bold;">ALCcontext</span> *<span style="color: #f0dfaf;">ctx</span> = ctxData-&gt;ctx;
  72.379 +    alcMakeContextCurrent(ctx);
  72.380 +    limitContext(Device, ctx);
  72.381 +    swapInContext(Device, ctxData);
  72.382 +    aluMixData(Device, ctxData-&gt;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)-&gt;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-&gt;ExtraData;
  72.419 +  <span style="color: #f0dfaf; font-weight: bold;">if</span> ((<span style="color: #dfdfbf; font-weight: bold;">ALuint</span>)n &gt; data-&gt;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 &gt; data-&gt;size){
  72.421 +    samples = (<span style="color: #dfdfbf; font-weight: bold;">int</span>) data-&gt;size;
  72.422 +  }
  72.423 +  memcpy(buffer_address, data-&gt;contexts[n]-&gt;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-&gt;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 &gt; data-&gt;numContexts){<span style="color: #f0dfaf; font-weight: bold;">return</span>;}
  72.455 +  alcMakeContextCurrent(data-&gt;contexts[contextNum]-&gt;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-&gt;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 &gt; data-&gt;numContexts){<span style="color: #f0dfaf; font-weight: bold;">return</span>;}
  72.476 +  alcMakeContextCurrent(data-&gt;contexts[contextNum]-&gt;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-&gt;szDeviceName = strdup(deviceName);
  72.514 +  device-&gt;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-&gt;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 &lt; data-&gt;numContexts; i++){
  72.526 +    <span style="color: #dfdfbf; font-weight: bold;">context_data</span> *<span style="color: #f0dfaf;">ctxData</span> = data-&gt;contexts[i];
  72.527 +    alcDestroyContext(ctxData-&gt;ctx);
  72.528 +    free(ctxData-&gt;renderBuffer);
  72.529 +    free(ctxData);
  72.530 +  }
  72.531 +  free(data);
  72.532 +  device-&gt;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-&gt;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-&gt;FmtType = DevFmtShort;
  72.540 +  bits = BytesFromDevFmt(device-&gt;FmtType) * 8;
  72.541 +  channels = ChannelsFromDevFmt(device-&gt;FmtChans);
  72.542 +  data-&gt;size = device-&gt;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 +}