Mercurial > audio-send
diff Alc/mixer.c @ 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 |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/Alc/mixer.c Tue Oct 25 13:02:31 2011 -0700 1.3 @@ -0,0 +1,848 @@ 1.4 +/** 1.5 + * OpenAL cross platform audio library 1.6 + * Copyright (C) 1999-2007 by authors. 1.7 + * This library is free software; you can redistribute it and/or 1.8 + * modify it under the terms of the GNU Library General Public 1.9 + * License as published by the Free Software Foundation; either 1.10 + * version 2 of the License, or (at your option) any later version. 1.11 + * 1.12 + * This library is distributed in the hope that it will be useful, 1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.15 + * Library General Public License for more details. 1.16 + * 1.17 + * You should have received a copy of the GNU Library General Public 1.18 + * License along with this library; if not, write to the 1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 1.20 + * Boston, MA 02111-1307, USA. 1.21 + * Or go to http://www.gnu.org/copyleft/lgpl.html 1.22 + */ 1.23 + 1.24 +#include "config.h" 1.25 + 1.26 +#include <math.h> 1.27 +#include <stdlib.h> 1.28 +#include <string.h> 1.29 +#include <ctype.h> 1.30 +#include <assert.h> 1.31 + 1.32 +#include "alMain.h" 1.33 +#include "AL/al.h" 1.34 +#include "AL/alc.h" 1.35 +#include "alSource.h" 1.36 +#include "alBuffer.h" 1.37 +#include "alListener.h" 1.38 +#include "alAuxEffectSlot.h" 1.39 +#include "alu.h" 1.40 +#include "bs2b.h" 1.41 + 1.42 + 1.43 +static __inline ALdouble point32(const ALfloat *vals, ALint step, ALint frac) 1.44 +{ return vals[0]; (void)step; (void)frac; } 1.45 +static __inline ALdouble lerp32(const ALfloat *vals, ALint step, ALint frac) 1.46 +{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)); } 1.47 +static __inline ALdouble cubic32(const ALfloat *vals, ALint step, ALint frac) 1.48 +{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], 1.49 + frac * (1.0/FRACTIONONE)); } 1.50 + 1.51 +static __inline ALdouble point16(const ALshort *vals, ALint step, ALint frac) 1.52 +{ return vals[0] * (1.0/32767.0); (void)step; (void)frac; } 1.53 +static __inline ALdouble lerp16(const ALshort *vals, ALint step, ALint frac) 1.54 +{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/32767.0); } 1.55 +static __inline ALdouble cubic16(const ALshort *vals, ALint step, ALint frac) 1.56 +{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], 1.57 + frac * (1.0/FRACTIONONE)) * (1.0/32767.0); } 1.58 + 1.59 +static __inline ALdouble point8(const ALbyte *vals, ALint step, ALint frac) 1.60 +{ return vals[0] * (1.0/127.0); (void)step; (void)frac; } 1.61 +static __inline ALdouble lerp8(const ALbyte *vals, ALint step, ALint frac) 1.62 +{ return lerp(vals[0], vals[step], frac * (1.0/FRACTIONONE)) * (1.0/127.0); } 1.63 +static __inline ALdouble cubic8(const ALbyte *vals, ALint step, ALint frac) 1.64 +{ return cubic(vals[-step], vals[0], vals[step], vals[step+step], 1.65 + frac * (1.0/FRACTIONONE)) * (1.0/127.0); } 1.66 + 1.67 +#ifdef __GNUC__ 1.68 +#define LIKELY(x) __builtin_expect(!!(x), 1) 1.69 +#define UNLIKELY(x) __builtin_expect(!!(x), 0) 1.70 +#else 1.71 +#define LIKELY(x) (x) 1.72 +#define UNLIKELY(x) (x) 1.73 +#endif 1.74 + 1.75 +#if defined(__ARM_NEON__) && defined(HAVE_ARM_NEON_H) 1.76 +#include <arm_neon.h> 1.77 + 1.78 +static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2], 1.79 + ALfloat (*RESTRICT Coeffs)[2], 1.80 + ALfloat left, ALfloat right) 1.81 +{ 1.82 + ALuint c; 1.83 + float32x4_t leftright4; 1.84 + { 1.85 + float32x2_t leftright2 = vdup_n_f32(0.0); 1.86 + leftright2 = vset_lane_f32(left, leftright2, 0); 1.87 + leftright2 = vset_lane_f32(right, leftright2, 1); 1.88 + leftright4 = vcombine_f32(leftright2, leftright2); 1.89 + } 1.90 + for(c = 0;c < HRIR_LENGTH;c += 2) 1.91 + { 1.92 + const ALuint o0 = (Offset+c)&HRIR_MASK; 1.93 + const ALuint o1 = (o0+1)&HRIR_MASK; 1.94 + float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]), 1.95 + vld1_f32((float32_t*)&Values[o1][0])); 1.96 + float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]); 1.97 + 1.98 + vals = vmlaq_f32(vals, coefs, leftright4); 1.99 + 1.100 + vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals)); 1.101 + vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals)); 1.102 + } 1.103 +} 1.104 + 1.105 +#else 1.106 + 1.107 +static __inline void ApplyCoeffs(ALuint Offset, ALfloat (*RESTRICT Values)[2], 1.108 + ALfloat (*RESTRICT Coeffs)[2], 1.109 + ALfloat left, ALfloat right) 1.110 +{ 1.111 + ALuint c; 1.112 + for(c = 0;c < HRIR_LENGTH;c++) 1.113 + { 1.114 + const ALuint off = (Offset+c)&HRIR_MASK; 1.115 + Values[off][0] += Coeffs[c][0] * left; 1.116 + Values[off][1] += Coeffs[c][1] * right; 1.117 + } 1.118 +} 1.119 + 1.120 +#endif 1.121 + 1.122 +#define DECL_TEMPLATE(T, sampler) \ 1.123 +static void Mix_Hrtf_##T##_##sampler(ALsource *Source, ALCdevice *Device, \ 1.124 + const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \ 1.125 + ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \ 1.126 +{ \ 1.127 + const ALuint NumChannels = Source->NumChannels; \ 1.128 + const T *RESTRICT data = srcdata; \ 1.129 + const ALint *RESTRICT DelayStep = Source->Params.HrtfDelayStep; \ 1.130 + ALfloat (*RESTRICT DryBuffer)[MAXCHANNELS]; \ 1.131 + ALfloat *RESTRICT ClickRemoval, *RESTRICT PendingClicks; \ 1.132 + ALfloat (*RESTRICT CoeffStep)[2] = Source->Params.HrtfCoeffStep; \ 1.133 + ALuint pos, frac; \ 1.134 + FILTER *DryFilter; \ 1.135 + ALuint BufferIdx; \ 1.136 + ALuint increment; \ 1.137 + ALuint i, out, c; \ 1.138 + ALfloat value; \ 1.139 + \ 1.140 + increment = Source->Params.Step; \ 1.141 + \ 1.142 + DryBuffer = Device->DryBuffer; \ 1.143 + ClickRemoval = Device->ClickRemoval; \ 1.144 + PendingClicks = Device->PendingClicks; \ 1.145 + DryFilter = &Source->Params.iirFilter; \ 1.146 + \ 1.147 + pos = 0; \ 1.148 + frac = *DataPosFrac; \ 1.149 + \ 1.150 + for(i = 0;i < NumChannels;i++) \ 1.151 + { \ 1.152 + ALfloat (*RESTRICT TargetCoeffs)[2] = Source->Params.HrtfCoeffs[i]; \ 1.153 + ALuint *RESTRICT TargetDelay = Source->Params.HrtfDelay[i]; \ 1.154 + ALfloat *RESTRICT History = Source->HrtfHistory[i]; \ 1.155 + ALfloat (*RESTRICT Values)[2] = Source->HrtfValues[i]; \ 1.156 + ALint Counter = maxu(Source->HrtfCounter, OutPos) - OutPos; \ 1.157 + ALuint Offset = Source->HrtfOffset + OutPos; \ 1.158 + ALfloat Coeffs[HRIR_LENGTH][2]; \ 1.159 + ALuint Delay[2]; \ 1.160 + ALfloat left, right; \ 1.161 + \ 1.162 + pos = 0; \ 1.163 + frac = *DataPosFrac; \ 1.164 + \ 1.165 + for(c = 0;c < HRIR_LENGTH;c++) \ 1.166 + { \ 1.167 + Coeffs[c][0] = TargetCoeffs[c][0] - (CoeffStep[c][0]*Counter); \ 1.168 + Coeffs[c][1] = TargetCoeffs[c][1] - (CoeffStep[c][1]*Counter); \ 1.169 + } \ 1.170 + \ 1.171 + Delay[0] = TargetDelay[0] - (DelayStep[0]*Counter) + 32768; \ 1.172 + Delay[1] = TargetDelay[1] - (DelayStep[1]*Counter) + 32768; \ 1.173 + \ 1.174 + if(LIKELY(OutPos == 0)) \ 1.175 + { \ 1.176 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.177 + value = lpFilter2PC(DryFilter, i, value); \ 1.178 + \ 1.179 + History[Offset&SRC_HISTORY_MASK] = value; \ 1.180 + left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \ 1.181 + right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \ 1.182 + \ 1.183 + ClickRemoval[FRONT_LEFT] -= Values[(Offset+1)&HRIR_MASK][0] + \ 1.184 + Coeffs[0][0] * left; \ 1.185 + ClickRemoval[FRONT_RIGHT] -= Values[(Offset+1)&HRIR_MASK][1] + \ 1.186 + Coeffs[0][1] * right; \ 1.187 + } \ 1.188 + for(BufferIdx = 0;BufferIdx < BufferSize && Counter > 0;BufferIdx++) \ 1.189 + { \ 1.190 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.191 + value = lpFilter2P(DryFilter, i, value); \ 1.192 + \ 1.193 + History[Offset&SRC_HISTORY_MASK] = value; \ 1.194 + left = History[(Offset-(Delay[0]>>16))&SRC_HISTORY_MASK]; \ 1.195 + right = History[(Offset-(Delay[1]>>16))&SRC_HISTORY_MASK]; \ 1.196 + \ 1.197 + Delay[0] += DelayStep[0]; \ 1.198 + Delay[1] += DelayStep[1]; \ 1.199 + \ 1.200 + Values[Offset&HRIR_MASK][0] = 0.0f; \ 1.201 + Values[Offset&HRIR_MASK][1] = 0.0f; \ 1.202 + Offset++; \ 1.203 + \ 1.204 + for(c = 0;c < HRIR_LENGTH;c++) \ 1.205 + { \ 1.206 + const ALuint off = (Offset+c)&HRIR_MASK; \ 1.207 + Values[off][0] += Coeffs[c][0] * left; \ 1.208 + Values[off][1] += Coeffs[c][1] * right; \ 1.209 + Coeffs[c][0] += CoeffStep[c][0]; \ 1.210 + Coeffs[c][1] += CoeffStep[c][1]; \ 1.211 + } \ 1.212 + \ 1.213 + DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \ 1.214 + DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \ 1.215 + \ 1.216 + frac += increment; \ 1.217 + pos += frac>>FRACTIONBITS; \ 1.218 + frac &= FRACTIONMASK; \ 1.219 + OutPos++; \ 1.220 + Counter--; \ 1.221 + } \ 1.222 + \ 1.223 + Delay[0] >>= 16; \ 1.224 + Delay[1] >>= 16; \ 1.225 + for(;BufferIdx < BufferSize;BufferIdx++) \ 1.226 + { \ 1.227 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.228 + value = lpFilter2P(DryFilter, i, value); \ 1.229 + \ 1.230 + History[Offset&SRC_HISTORY_MASK] = value; \ 1.231 + left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \ 1.232 + right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \ 1.233 + \ 1.234 + Values[Offset&HRIR_MASK][0] = 0.0f; \ 1.235 + Values[Offset&HRIR_MASK][1] = 0.0f; \ 1.236 + Offset++; \ 1.237 + \ 1.238 + ApplyCoeffs(Offset, Values, Coeffs, left, right); \ 1.239 + DryBuffer[OutPos][FRONT_LEFT] += Values[Offset&HRIR_MASK][0]; \ 1.240 + DryBuffer[OutPos][FRONT_RIGHT] += Values[Offset&HRIR_MASK][1]; \ 1.241 + \ 1.242 + frac += increment; \ 1.243 + pos += frac>>FRACTIONBITS; \ 1.244 + frac &= FRACTIONMASK; \ 1.245 + OutPos++; \ 1.246 + } \ 1.247 + if(LIKELY(OutPos == SamplesToDo)) \ 1.248 + { \ 1.249 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.250 + value = lpFilter2PC(DryFilter, i, value); \ 1.251 + \ 1.252 + History[Offset&SRC_HISTORY_MASK] = value; \ 1.253 + left = History[(Offset-Delay[0])&SRC_HISTORY_MASK]; \ 1.254 + right = History[(Offset-Delay[1])&SRC_HISTORY_MASK]; \ 1.255 + \ 1.256 + PendingClicks[FRONT_LEFT] += Values[(Offset+1)&HRIR_MASK][0] + \ 1.257 + Coeffs[0][0] * left; \ 1.258 + PendingClicks[FRONT_RIGHT] += Values[(Offset+1)&HRIR_MASK][1] + \ 1.259 + Coeffs[0][1] * right; \ 1.260 + } \ 1.261 + OutPos -= BufferSize; \ 1.262 + } \ 1.263 + \ 1.264 + for(out = 0;out < Device->NumAuxSends;out++) \ 1.265 + { \ 1.266 + ALeffectslot *Slot = Source->Params.Send[out].Slot; \ 1.267 + ALfloat WetSend; \ 1.268 + ALfloat *RESTRICT WetBuffer; \ 1.269 + ALfloat *RESTRICT WetClickRemoval; \ 1.270 + ALfloat *RESTRICT WetPendingClicks; \ 1.271 + FILTER *WetFilter; \ 1.272 + \ 1.273 + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \ 1.274 + continue; \ 1.275 + \ 1.276 + WetBuffer = Slot->WetBuffer; \ 1.277 + WetClickRemoval = Slot->ClickRemoval; \ 1.278 + WetPendingClicks = Slot->PendingClicks; \ 1.279 + WetFilter = &Source->Params.Send[out].iirFilter; \ 1.280 + WetSend = Source->Params.Send[out].WetGain; \ 1.281 + \ 1.282 + for(i = 0;i < NumChannels;i++) \ 1.283 + { \ 1.284 + pos = 0; \ 1.285 + frac = *DataPosFrac; \ 1.286 + \ 1.287 + if(LIKELY(OutPos == 0)) \ 1.288 + { \ 1.289 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 1.290 + value = lpFilter1PC(WetFilter, i, value); \ 1.291 + \ 1.292 + WetClickRemoval[0] -= value * WetSend; \ 1.293 + } \ 1.294 + for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \ 1.295 + { \ 1.296 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 1.297 + value = lpFilter1P(WetFilter, i, value); \ 1.298 + \ 1.299 + WetBuffer[OutPos] += value * WetSend; \ 1.300 + \ 1.301 + frac += increment; \ 1.302 + pos += frac>>FRACTIONBITS; \ 1.303 + frac &= FRACTIONMASK; \ 1.304 + OutPos++; \ 1.305 + } \ 1.306 + if(LIKELY(OutPos == SamplesToDo)) \ 1.307 + { \ 1.308 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 1.309 + value = lpFilter1PC(WetFilter, i, value); \ 1.310 + \ 1.311 + WetPendingClicks[0] += value * WetSend; \ 1.312 + } \ 1.313 + OutPos -= BufferSize; \ 1.314 + } \ 1.315 + } \ 1.316 + *DataPosInt += pos; \ 1.317 + *DataPosFrac = frac; \ 1.318 +} 1.319 + 1.320 +DECL_TEMPLATE(ALfloat, point32) 1.321 +DECL_TEMPLATE(ALfloat, lerp32) 1.322 +DECL_TEMPLATE(ALfloat, cubic32) 1.323 + 1.324 +DECL_TEMPLATE(ALshort, point16) 1.325 +DECL_TEMPLATE(ALshort, lerp16) 1.326 +DECL_TEMPLATE(ALshort, cubic16) 1.327 + 1.328 +DECL_TEMPLATE(ALbyte, point8) 1.329 +DECL_TEMPLATE(ALbyte, lerp8) 1.330 +DECL_TEMPLATE(ALbyte, cubic8) 1.331 + 1.332 +#undef DECL_TEMPLATE 1.333 + 1.334 + 1.335 +#define DECL_TEMPLATE(T, sampler) \ 1.336 +static void Mix_##T##_##sampler(ALsource *Source, ALCdevice *Device, \ 1.337 + const ALvoid *srcdata, ALuint *DataPosInt, ALuint *DataPosFrac, \ 1.338 + ALuint OutPos, ALuint SamplesToDo, ALuint BufferSize) \ 1.339 +{ \ 1.340 + const ALuint NumChannels = Source->NumChannels; \ 1.341 + const T *RESTRICT data = srcdata; \ 1.342 + ALfloat (*DryBuffer)[MAXCHANNELS]; \ 1.343 + ALfloat *ClickRemoval, *PendingClicks; \ 1.344 + ALuint pos, frac; \ 1.345 + ALfloat DrySend[MAXCHANNELS][MAXCHANNELS]; \ 1.346 + FILTER *DryFilter; \ 1.347 + ALuint BufferIdx; \ 1.348 + ALuint increment; \ 1.349 + ALuint i, out, c; \ 1.350 + ALfloat value; \ 1.351 + \ 1.352 + increment = Source->Params.Step; \ 1.353 + \ 1.354 + DryBuffer = Device->DryBuffer; \ 1.355 + ClickRemoval = Device->ClickRemoval; \ 1.356 + PendingClicks = Device->PendingClicks; \ 1.357 + DryFilter = &Source->Params.iirFilter; \ 1.358 + for(i = 0;i < NumChannels;i++) \ 1.359 + { \ 1.360 + for(c = 0;c < MAXCHANNELS;c++) \ 1.361 + DrySend[i][c] = Source->Params.DryGains[i][c]; \ 1.362 + } \ 1.363 + \ 1.364 + pos = 0; \ 1.365 + frac = *DataPosFrac; \ 1.366 + \ 1.367 + for(i = 0;i < NumChannels;i++) \ 1.368 + { \ 1.369 + pos = 0; \ 1.370 + frac = *DataPosFrac; \ 1.371 + \ 1.372 + if(OutPos == 0) \ 1.373 + { \ 1.374 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.375 + \ 1.376 + value = lpFilter2PC(DryFilter, i, value); \ 1.377 + for(c = 0;c < MAXCHANNELS;c++) \ 1.378 + ClickRemoval[c] -= value*DrySend[i][c]; \ 1.379 + } \ 1.380 + for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \ 1.381 + { \ 1.382 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.383 + \ 1.384 + value = lpFilter2P(DryFilter, i, value); \ 1.385 + for(c = 0;c < MAXCHANNELS;c++) \ 1.386 + DryBuffer[OutPos][c] += value*DrySend[i][c]; \ 1.387 + \ 1.388 + frac += increment; \ 1.389 + pos += frac>>FRACTIONBITS; \ 1.390 + frac &= FRACTIONMASK; \ 1.391 + OutPos++; \ 1.392 + } \ 1.393 + if(OutPos == SamplesToDo) \ 1.394 + { \ 1.395 + value = sampler(data + pos*NumChannels + i, NumChannels, frac); \ 1.396 + \ 1.397 + value = lpFilter2PC(DryFilter, i, value); \ 1.398 + for(c = 0;c < MAXCHANNELS;c++) \ 1.399 + PendingClicks[c] += value*DrySend[i][c]; \ 1.400 + } \ 1.401 + OutPos -= BufferSize; \ 1.402 + } \ 1.403 + \ 1.404 + for(out = 0;out < Device->NumAuxSends;out++) \ 1.405 + { \ 1.406 + ALeffectslot *Slot = Source->Params.Send[out].Slot; \ 1.407 + ALfloat WetSend; \ 1.408 + ALfloat *WetBuffer; \ 1.409 + ALfloat *WetClickRemoval; \ 1.410 + ALfloat *WetPendingClicks; \ 1.411 + FILTER *WetFilter; \ 1.412 + \ 1.413 + if(!Slot || Slot->effect.type == AL_EFFECT_NULL) \ 1.414 + continue; \ 1.415 + \ 1.416 + WetBuffer = Slot->WetBuffer; \ 1.417 + WetClickRemoval = Slot->ClickRemoval; \ 1.418 + WetPendingClicks = Slot->PendingClicks; \ 1.419 + WetFilter = &Source->Params.Send[out].iirFilter; \ 1.420 + WetSend = Source->Params.Send[out].WetGain; \ 1.421 + \ 1.422 + for(i = 0;i < NumChannels;i++) \ 1.423 + { \ 1.424 + pos = 0; \ 1.425 + frac = *DataPosFrac; \ 1.426 + \ 1.427 + if(OutPos == 0) \ 1.428 + { \ 1.429 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 1.430 + \ 1.431 + value = lpFilter1PC(WetFilter, i, value); \ 1.432 + WetClickRemoval[0] -= value * WetSend; \ 1.433 + } \ 1.434 + for(BufferIdx = 0;BufferIdx < BufferSize;BufferIdx++) \ 1.435 + { \ 1.436 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 1.437 + \ 1.438 + value = lpFilter1P(WetFilter, i, value); \ 1.439 + WetBuffer[OutPos] += value * WetSend; \ 1.440 + \ 1.441 + frac += increment; \ 1.442 + pos += frac>>FRACTIONBITS; \ 1.443 + frac &= FRACTIONMASK; \ 1.444 + OutPos++; \ 1.445 + } \ 1.446 + if(OutPos == SamplesToDo) \ 1.447 + { \ 1.448 + value = sampler(data + pos*NumChannels + i, NumChannels,frac);\ 1.449 + \ 1.450 + value = lpFilter1PC(WetFilter, i, value); \ 1.451 + WetPendingClicks[0] += value * WetSend; \ 1.452 + } \ 1.453 + OutPos -= BufferSize; \ 1.454 + } \ 1.455 + } \ 1.456 + *DataPosInt += pos; \ 1.457 + *DataPosFrac = frac; \ 1.458 +} 1.459 + 1.460 +DECL_TEMPLATE(ALfloat, point32) 1.461 +DECL_TEMPLATE(ALfloat, lerp32) 1.462 +DECL_TEMPLATE(ALfloat, cubic32) 1.463 + 1.464 +DECL_TEMPLATE(ALshort, point16) 1.465 +DECL_TEMPLATE(ALshort, lerp16) 1.466 +DECL_TEMPLATE(ALshort, cubic16) 1.467 + 1.468 +DECL_TEMPLATE(ALbyte, point8) 1.469 +DECL_TEMPLATE(ALbyte, lerp8) 1.470 +DECL_TEMPLATE(ALbyte, cubic8) 1.471 + 1.472 +#undef DECL_TEMPLATE 1.473 + 1.474 + 1.475 +#define DECL_TEMPLATE(sampler) \ 1.476 +static MixerFunc Select_##sampler(enum FmtType FmtType) \ 1.477 +{ \ 1.478 + switch(FmtType) \ 1.479 + { \ 1.480 + case FmtByte: \ 1.481 + return Mix_ALbyte_##sampler##8; \ 1.482 + case FmtShort: \ 1.483 + return Mix_ALshort_##sampler##16; \ 1.484 + case FmtFloat: \ 1.485 + return Mix_ALfloat_##sampler##32; \ 1.486 + } \ 1.487 + return NULL; \ 1.488 +} 1.489 + 1.490 +DECL_TEMPLATE(point) 1.491 +DECL_TEMPLATE(lerp) 1.492 +DECL_TEMPLATE(cubic) 1.493 + 1.494 +#undef DECL_TEMPLATE 1.495 + 1.496 +MixerFunc SelectMixer(ALbuffer *Buffer, enum Resampler Resampler) 1.497 +{ 1.498 + switch(Resampler) 1.499 + { 1.500 + case POINT_RESAMPLER: 1.501 + return Select_point(Buffer->FmtType); 1.502 + case LINEAR_RESAMPLER: 1.503 + return Select_lerp(Buffer->FmtType); 1.504 + case CUBIC_RESAMPLER: 1.505 + return Select_cubic(Buffer->FmtType); 1.506 + case RESAMPLER_MIN: 1.507 + case RESAMPLER_MAX: 1.508 + break; 1.509 + } 1.510 + return NULL; 1.511 +} 1.512 + 1.513 +#define DECL_TEMPLATE(sampler) \ 1.514 +static MixerFunc Select_Hrtf_##sampler(enum FmtType FmtType) \ 1.515 +{ \ 1.516 + switch(FmtType) \ 1.517 + { \ 1.518 + case FmtByte: \ 1.519 + return Mix_Hrtf_ALbyte_##sampler##8; \ 1.520 + case FmtShort: \ 1.521 + return Mix_Hrtf_ALshort_##sampler##16; \ 1.522 + case FmtFloat: \ 1.523 + return Mix_Hrtf_ALfloat_##sampler##32; \ 1.524 + } \ 1.525 + return NULL; \ 1.526 +} 1.527 + 1.528 +DECL_TEMPLATE(point) 1.529 +DECL_TEMPLATE(lerp) 1.530 +DECL_TEMPLATE(cubic) 1.531 + 1.532 +#undef DECL_TEMPLATE 1.533 + 1.534 +MixerFunc SelectHrtfMixer(ALbuffer *Buffer, enum Resampler Resampler) 1.535 +{ 1.536 + switch(Resampler) 1.537 + { 1.538 + case POINT_RESAMPLER: 1.539 + return Select_Hrtf_point(Buffer->FmtType); 1.540 + case LINEAR_RESAMPLER: 1.541 + return Select_Hrtf_lerp(Buffer->FmtType); 1.542 + case CUBIC_RESAMPLER: 1.543 + return Select_Hrtf_cubic(Buffer->FmtType); 1.544 + case RESAMPLER_MIN: 1.545 + case RESAMPLER_MAX: 1.546 + break; 1.547 + } 1.548 + return NULL; 1.549 +} 1.550 + 1.551 + 1.552 +ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo) 1.553 +{ 1.554 + ALbufferlistitem *BufferListItem; 1.555 + ALuint DataPosInt, DataPosFrac; 1.556 + ALuint BuffersPlayed; 1.557 + ALboolean Looping; 1.558 + ALuint increment; 1.559 + enum Resampler Resampler; 1.560 + ALenum State; 1.561 + ALuint OutPos; 1.562 + ALuint FrameSize; 1.563 + ALint64 DataSize64; 1.564 + ALuint i; 1.565 + 1.566 + /* Get source info */ 1.567 + State = Source->state; 1.568 + BuffersPlayed = Source->BuffersPlayed; 1.569 + DataPosInt = Source->position; 1.570 + DataPosFrac = Source->position_fraction; 1.571 + Looping = Source->bLooping; 1.572 + increment = Source->Params.Step; 1.573 + Resampler = Source->Resampler; 1.574 + FrameSize = Source->NumChannels * Source->SampleSize; 1.575 + 1.576 + /* Get current buffer queue item */ 1.577 + BufferListItem = Source->queue; 1.578 + for(i = 0;i < BuffersPlayed;i++) 1.579 + BufferListItem = BufferListItem->next; 1.580 + 1.581 + OutPos = 0; 1.582 + do { 1.583 + const ALuint BufferPrePadding = ResamplerPrePadding[Resampler]; 1.584 + const ALuint BufferPadding = ResamplerPadding[Resampler]; 1.585 + ALubyte StackData[STACK_DATA_SIZE]; 1.586 + ALubyte *SrcData = StackData; 1.587 + ALuint SrcDataSize = 0; 1.588 + ALuint BufferSize; 1.589 + 1.590 + /* Figure out how many buffer bytes will be needed */ 1.591 + DataSize64 = SamplesToDo-OutPos+1; 1.592 + DataSize64 *= increment; 1.593 + DataSize64 += DataPosFrac+FRACTIONMASK; 1.594 + DataSize64 >>= FRACTIONBITS; 1.595 + DataSize64 += BufferPadding+BufferPrePadding; 1.596 + DataSize64 *= FrameSize; 1.597 + 1.598 + BufferSize = ((DataSize64 > STACK_DATA_SIZE) ? STACK_DATA_SIZE : DataSize64); 1.599 + BufferSize -= BufferSize%FrameSize; 1.600 + 1.601 + if(Source->lSourceType == AL_STATIC) 1.602 + { 1.603 + const ALbuffer *ALBuffer = Source->Buffer; 1.604 + const ALubyte *Data = ALBuffer->data; 1.605 + ALuint DataSize; 1.606 + ALuint pos; 1.607 + 1.608 + /* If current pos is beyond the loop range, do not loop */ 1.609 + if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd) 1.610 + { 1.611 + Looping = AL_FALSE; 1.612 + 1.613 + if(DataPosInt >= BufferPrePadding) 1.614 + pos = (DataPosInt-BufferPrePadding)*FrameSize; 1.615 + else 1.616 + { 1.617 + DataSize = (BufferPrePadding-DataPosInt)*FrameSize; 1.618 + DataSize = minu(BufferSize, DataSize); 1.619 + 1.620 + memset(&SrcData[SrcDataSize], 0, DataSize); 1.621 + SrcDataSize += DataSize; 1.622 + BufferSize -= DataSize; 1.623 + 1.624 + pos = 0; 1.625 + } 1.626 + 1.627 + /* Copy what's left to play in the source buffer, and clear the 1.628 + * rest of the temp buffer */ 1.629 + DataSize = ALBuffer->size - pos; 1.630 + DataSize = minu(BufferSize, DataSize); 1.631 + 1.632 + memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize); 1.633 + SrcDataSize += DataSize; 1.634 + BufferSize -= DataSize; 1.635 + 1.636 + memset(&SrcData[SrcDataSize], 0, BufferSize); 1.637 + SrcDataSize += BufferSize; 1.638 + BufferSize -= BufferSize; 1.639 + } 1.640 + else 1.641 + { 1.642 + ALuint LoopStart = ALBuffer->LoopStart; 1.643 + ALuint LoopEnd = ALBuffer->LoopEnd; 1.644 + 1.645 + if(DataPosInt >= LoopStart) 1.646 + { 1.647 + pos = DataPosInt-LoopStart; 1.648 + while(pos < BufferPrePadding) 1.649 + pos += LoopEnd-LoopStart; 1.650 + pos -= BufferPrePadding; 1.651 + pos += LoopStart; 1.652 + pos *= FrameSize; 1.653 + } 1.654 + else if(DataPosInt >= BufferPrePadding) 1.655 + pos = (DataPosInt-BufferPrePadding)*FrameSize; 1.656 + else 1.657 + { 1.658 + DataSize = (BufferPrePadding-DataPosInt)*FrameSize; 1.659 + DataSize = minu(BufferSize, DataSize); 1.660 + 1.661 + memset(&SrcData[SrcDataSize], 0, DataSize); 1.662 + SrcDataSize += DataSize; 1.663 + BufferSize -= DataSize; 1.664 + 1.665 + pos = 0; 1.666 + } 1.667 + 1.668 + /* Copy what's left of this loop iteration, then copy repeats 1.669 + * of the loop section */ 1.670 + DataSize = LoopEnd*FrameSize - pos; 1.671 + DataSize = minu(BufferSize, DataSize); 1.672 + 1.673 + memcpy(&SrcData[SrcDataSize], &Data[pos], DataSize); 1.674 + SrcDataSize += DataSize; 1.675 + BufferSize -= DataSize; 1.676 + 1.677 + DataSize = (LoopEnd-LoopStart) * FrameSize; 1.678 + while(BufferSize > 0) 1.679 + { 1.680 + DataSize = minu(BufferSize, DataSize); 1.681 + 1.682 + memcpy(&SrcData[SrcDataSize], &Data[LoopStart*FrameSize], DataSize); 1.683 + SrcDataSize += DataSize; 1.684 + BufferSize -= DataSize; 1.685 + } 1.686 + } 1.687 + } 1.688 + else 1.689 + { 1.690 + /* Crawl the buffer queue to fill in the temp buffer */ 1.691 + ALbufferlistitem *BufferListIter = BufferListItem; 1.692 + ALuint pos; 1.693 + 1.694 + if(DataPosInt >= BufferPrePadding) 1.695 + pos = (DataPosInt-BufferPrePadding)*FrameSize; 1.696 + else 1.697 + { 1.698 + pos = (BufferPrePadding-DataPosInt)*FrameSize; 1.699 + while(pos > 0) 1.700 + { 1.701 + if(!BufferListIter->prev && !Looping) 1.702 + { 1.703 + ALuint DataSize = minu(BufferSize, pos); 1.704 + 1.705 + memset(&SrcData[SrcDataSize], 0, DataSize); 1.706 + SrcDataSize += DataSize; 1.707 + BufferSize -= DataSize; 1.708 + 1.709 + pos = 0; 1.710 + break; 1.711 + } 1.712 + 1.713 + if(BufferListIter->prev) 1.714 + BufferListIter = BufferListIter->prev; 1.715 + else 1.716 + { 1.717 + while(BufferListIter->next) 1.718 + BufferListIter = BufferListIter->next; 1.719 + } 1.720 + 1.721 + if(BufferListIter->buffer) 1.722 + { 1.723 + if((ALuint)BufferListIter->buffer->size > pos) 1.724 + { 1.725 + pos = BufferListIter->buffer->size - pos; 1.726 + break; 1.727 + } 1.728 + pos -= BufferListIter->buffer->size; 1.729 + } 1.730 + } 1.731 + } 1.732 + 1.733 + while(BufferListIter && BufferSize > 0) 1.734 + { 1.735 + const ALbuffer *ALBuffer; 1.736 + if((ALBuffer=BufferListIter->buffer) != NULL) 1.737 + { 1.738 + const ALubyte *Data = ALBuffer->data; 1.739 + ALuint DataSize = ALBuffer->size; 1.740 + 1.741 + /* Skip the data already played */ 1.742 + if(DataSize <= pos) 1.743 + pos -= DataSize; 1.744 + else 1.745 + { 1.746 + Data += pos; 1.747 + DataSize -= pos; 1.748 + pos -= pos; 1.749 + 1.750 + DataSize = minu(BufferSize, DataSize); 1.751 + memcpy(&SrcData[SrcDataSize], Data, DataSize); 1.752 + SrcDataSize += DataSize; 1.753 + BufferSize -= DataSize; 1.754 + } 1.755 + } 1.756 + BufferListIter = BufferListIter->next; 1.757 + if(!BufferListIter && Looping) 1.758 + BufferListIter = Source->queue; 1.759 + else if(!BufferListIter) 1.760 + { 1.761 + memset(&SrcData[SrcDataSize], 0, BufferSize); 1.762 + SrcDataSize += BufferSize; 1.763 + BufferSize -= BufferSize; 1.764 + } 1.765 + } 1.766 + } 1.767 + 1.768 + /* Figure out how many samples we can mix. */ 1.769 + DataSize64 = SrcDataSize / FrameSize; 1.770 + DataSize64 -= BufferPadding+BufferPrePadding; 1.771 + DataSize64 <<= FRACTIONBITS; 1.772 + DataSize64 -= increment; 1.773 + DataSize64 -= DataPosFrac; 1.774 + 1.775 + BufferSize = (ALuint)((DataSize64+(increment-1)) / increment); 1.776 + BufferSize = minu(BufferSize, (SamplesToDo-OutPos)); 1.777 + 1.778 + SrcData += BufferPrePadding*FrameSize; 1.779 + Source->Params.DoMix(Source, Device, SrcData, &DataPosInt, &DataPosFrac, 1.780 + OutPos, SamplesToDo, BufferSize); 1.781 + OutPos += BufferSize; 1.782 + 1.783 + /* Handle looping sources */ 1.784 + while(1) 1.785 + { 1.786 + const ALbuffer *ALBuffer; 1.787 + ALuint DataSize = 0; 1.788 + ALuint LoopStart = 0; 1.789 + ALuint LoopEnd = 0; 1.790 + 1.791 + if((ALBuffer=BufferListItem->buffer) != NULL) 1.792 + { 1.793 + DataSize = ALBuffer->size / FrameSize; 1.794 + LoopStart = ALBuffer->LoopStart; 1.795 + LoopEnd = ALBuffer->LoopEnd; 1.796 + if(LoopEnd > DataPosInt) 1.797 + break; 1.798 + } 1.799 + 1.800 + if(Looping && Source->lSourceType == AL_STATIC) 1.801 + { 1.802 + BufferListItem = Source->queue; 1.803 + DataPosInt = ((DataPosInt-LoopStart)%(LoopEnd-LoopStart)) + LoopStart; 1.804 + break; 1.805 + } 1.806 + 1.807 + if(DataSize > DataPosInt) 1.808 + break; 1.809 + 1.810 + if(BufferListItem->next) 1.811 + { 1.812 + BufferListItem = BufferListItem->next; 1.813 + BuffersPlayed++; 1.814 + } 1.815 + else if(Looping) 1.816 + { 1.817 + BufferListItem = Source->queue; 1.818 + BuffersPlayed = 0; 1.819 + } 1.820 + else 1.821 + { 1.822 + State = AL_STOPPED; 1.823 + BufferListItem = Source->queue; 1.824 + BuffersPlayed = Source->BuffersInQueue; 1.825 + DataPosInt = 0; 1.826 + DataPosFrac = 0; 1.827 + break; 1.828 + } 1.829 + 1.830 + DataPosInt -= DataSize; 1.831 + } 1.832 + } while(State == AL_PLAYING && OutPos < SamplesToDo); 1.833 + 1.834 + /* Update source info */ 1.835 + Source->state = State; 1.836 + Source->BuffersPlayed = BuffersPlayed; 1.837 + Source->position = DataPosInt; 1.838 + Source->position_fraction = DataPosFrac; 1.839 + Source->Buffer = BufferListItem->buffer; 1.840 + Source->HrtfOffset += OutPos; 1.841 + if(State == AL_PLAYING) 1.842 + { 1.843 + Source->HrtfCounter = maxu(Source->HrtfCounter, OutPos) - OutPos; 1.844 + Source->HrtfMoving = AL_TRUE; 1.845 + } 1.846 + else 1.847 + { 1.848 + Source->HrtfCounter = 0; 1.849 + Source->HrtfMoving = AL_FALSE; 1.850 + } 1.851 +}