aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/mixer.c')
-rw-r--r--Alc/mixer.c462
1 files changed, 326 insertions, 136 deletions
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 6a4abfc6..712075f1 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -13,8 +13,8 @@
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Or go to http://www.gnu.org/copyleft/lgpl.html
*/
@@ -34,11 +34,255 @@
#include "alListener.h"
#include "alAuxEffectSlot.h"
#include "alu.h"
-#include "bs2b.h"
+#include "mixer_defs.h"
+
+
+static_assert((INT_MAX>>FRACTIONBITS)/MAX_PITCH > BUFFERSIZE,
+ "MAX_PITCH and/or BUFFERSIZE are too large for FRACTIONBITS!");
extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
+alignas(16) union ResamplerCoeffs ResampleCoeffs;
+
+
+enum Resampler {
+ PointResampler,
+ LinearResampler,
+ FIR4Resampler,
+ FIR8Resampler,
+ BSincResampler,
+
+ ResamplerDefault = LinearResampler
+};
+
+/* FIR8 requires 3 extra samples before the current position, and 4 after. */
+static_assert(MAX_PRE_SAMPLES >= 3, "MAX_PRE_SAMPLES must be at least 3!");
+static_assert(MAX_POST_SAMPLES >= 4, "MAX_POST_SAMPLES must be at least 4!");
+
+
+static HrtfMixerFunc MixHrtfSamples = MixHrtf_C;
+static MixerFunc MixSamples = Mix_C;
+static ResamplerFunc ResampleSamples = Resample_point32_C;
+
+static inline HrtfMixerFunc SelectHrtfMixer(void)
+{
+#ifdef HAVE_SSE
+ if((CPUCapFlags&CPU_CAP_SSE))
+ return MixHrtf_SSE;
+#endif
+#ifdef HAVE_NEON
+ if((CPUCapFlags&CPU_CAP_NEON))
+ return MixHrtf_Neon;
+#endif
+
+ return MixHrtf_C;
+}
+
+static inline MixerFunc SelectMixer(void)
+{
+#ifdef HAVE_SSE
+ if((CPUCapFlags&CPU_CAP_SSE))
+ return Mix_SSE;
+#endif
+#ifdef HAVE_NEON
+ if((CPUCapFlags&CPU_CAP_NEON))
+ return Mix_Neon;
+#endif
+
+ return Mix_C;
+}
+
+static inline ResamplerFunc SelectResampler(enum Resampler resampler)
+{
+ switch(resampler)
+ {
+ case PointResampler:
+ return Resample_point32_C;
+ case LinearResampler:
+#ifdef HAVE_SSE4_1
+ if((CPUCapFlags&CPU_CAP_SSE4_1))
+ return Resample_lerp32_SSE41;
+#endif
+#ifdef HAVE_SSE2
+ if((CPUCapFlags&CPU_CAP_SSE2))
+ return Resample_lerp32_SSE2;
+#endif
+ return Resample_lerp32_C;
+ case FIR4Resampler:
+#ifdef HAVE_SSE4_1
+ if((CPUCapFlags&CPU_CAP_SSE4_1))
+ return Resample_fir4_32_SSE41;
+#endif
+#ifdef HAVE_SSE3
+ if((CPUCapFlags&CPU_CAP_SSE3))
+ return Resample_fir4_32_SSE3;
+#endif
+ return Resample_fir4_32_C;
+ case FIR8Resampler:
+#ifdef HAVE_SSE4_1
+ if((CPUCapFlags&CPU_CAP_SSE4_1))
+ return Resample_fir8_32_SSE41;
+#endif
+#ifdef HAVE_SSE3
+ if((CPUCapFlags&CPU_CAP_SSE3))
+ return Resample_fir8_32_SSE3;
+#endif
+ return Resample_fir8_32_C;
+ case BSincResampler:
+#ifdef HAVE_SSE
+ if((CPUCapFlags&CPU_CAP_SSE))
+ return Resample_bsinc32_SSE;
+#endif
+ return Resample_bsinc32_C;
+ }
+
+ return Resample_point32_C;
+}
+
+
+/* The sinc resampler makes use of a Kaiser window to limit the needed sample
+ * points to 4 and 8, respectively.
+ */
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+static inline double Sinc(double x)
+{
+ if(x == 0.0) return 1.0;
+ return sin(x*M_PI) / (x*M_PI);
+}
+
+/* The zero-order modified Bessel function of the first kind, used for the
+ * Kaiser window.
+ *
+ * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k)
+ * = sum_{k=0}^inf ((x / 2)^k / k!)^2
+ */
+static double BesselI_0(double x)
+{
+ double term, sum, x2, y, last_sum;
+ int k;
+
+ /* Start at k=1 since k=0 is trivial. */
+ term = 1.0;
+ sum = 1.0;
+ x2 = x / 2.0;
+ k = 1;
+
+ /* Let the integration converge until the term of the sum is no longer
+ * significant.
+ */
+ do {
+ y = x2 / k;
+ k ++;
+ last_sum = sum;
+ term *= y * y;
+ sum += term;
+ } while(sum != last_sum);
+ return sum;
+}
+
+/* Calculate a Kaiser window from the given beta value and a normalized k
+ * [-1, 1].
+ *
+ * w(k) = { I_0(B sqrt(1 - k^2)) / I_0(B), -1 <= k <= 1
+ * { 0, elsewhere.
+ *
+ * Where k can be calculated as:
+ *
+ * k = i / l, where -l <= i <= l.
+ *
+ * or:
+ *
+ * k = 2 i / M - 1, where 0 <= i <= M.
+ */
+static inline double Kaiser(double b, double k)
+{
+ if(k <= -1.0 || k >= 1.0) return 0.0;
+ return BesselI_0(b * sqrt(1.0 - (k*k))) / BesselI_0(b);
+}
+
+static inline double CalcKaiserBeta(double rejection)
+{
+ if(rejection > 50.0)
+ return 0.1102 * (rejection - 8.7);
+ if(rejection >= 21.0)
+ return (0.5842 * pow(rejection - 21.0, 0.4)) +
+ (0.07886 * (rejection - 21.0));
+ return 0.0;
+}
+
+static float SincKaiser(double r, double x)
+{
+ /* Limit rippling to -60dB. */
+ return (float)(Kaiser(CalcKaiserBeta(60.0), x / r) * Sinc(x));
+}
+
+
+void aluInitMixer(void)
+{
+ enum Resampler resampler = ResamplerDefault;
+ const char *str;
+ ALuint i;
+
+ if(ConfigValueStr(NULL, NULL, "resampler", &str))
+ {
+ if(strcasecmp(str, "point") == 0 || strcasecmp(str, "none") == 0)
+ resampler = PointResampler;
+ else if(strcasecmp(str, "linear") == 0)
+ resampler = LinearResampler;
+ else if(strcasecmp(str, "sinc4") == 0)
+ resampler = FIR4Resampler;
+ else if(strcasecmp(str, "sinc8") == 0)
+ resampler = FIR8Resampler;
+ else if(strcasecmp(str, "bsinc") == 0)
+ resampler = BSincResampler;
+ else if(strcasecmp(str, "cubic") == 0)
+ {
+ WARN("Resampler option \"cubic\" is deprecated, using sinc4\n");
+ resampler = FIR4Resampler;
+ }
+ else
+ {
+ char *end;
+ long n = strtol(str, &end, 0);
+ if(*end == '\0' && (n == PointResampler || n == LinearResampler || n == FIR4Resampler))
+ resampler = n;
+ else
+ WARN("Invalid resampler: %s\n", str);
+ }
+ }
+
+ if(resampler == FIR8Resampler)
+ for(i = 0;i < FRACTIONONE;i++)
+ {
+ ALdouble mu = (ALdouble)i / FRACTIONONE;
+ ResampleCoeffs.FIR8[i][0] = SincKaiser(4.0, mu - -3.0);
+ ResampleCoeffs.FIR8[i][1] = SincKaiser(4.0, mu - -2.0);
+ ResampleCoeffs.FIR8[i][2] = SincKaiser(4.0, mu - -1.0);
+ ResampleCoeffs.FIR8[i][3] = SincKaiser(4.0, mu - 0.0);
+ ResampleCoeffs.FIR8[i][4] = SincKaiser(4.0, mu - 1.0);
+ ResampleCoeffs.FIR8[i][5] = SincKaiser(4.0, mu - 2.0);
+ ResampleCoeffs.FIR8[i][6] = SincKaiser(4.0, mu - 3.0);
+ ResampleCoeffs.FIR8[i][7] = SincKaiser(4.0, mu - 4.0);
+ }
+ else if(resampler == FIR4Resampler)
+ for(i = 0;i < FRACTIONONE;i++)
+ {
+ ALdouble mu = (ALdouble)i / FRACTIONONE;
+ ResampleCoeffs.FIR4[i][0] = SincKaiser(2.0, mu - -1.0);
+ ResampleCoeffs.FIR4[i][1] = SincKaiser(2.0, mu - 0.0);
+ ResampleCoeffs.FIR4[i][2] = SincKaiser(2.0, mu - 1.0);
+ ResampleCoeffs.FIR4[i][3] = SincKaiser(2.0, mu - 2.0);
+ }
+
+ MixHrtfSamples = SelectHrtfMixer();
+ MixSamples = SelectMixer();
+ ResampleSamples = SelectResampler(resampler);
+}
+
static inline ALfloat Sample_ALbyte(ALbyte val)
{ return val * (1.0f/127.0f); }
@@ -50,7 +294,7 @@ static inline ALfloat Sample_ALfloat(ALfloat val)
{ return val; }
#define DECL_TEMPLATE(T) \
-static void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
+static inline void Load_##T(ALfloat *dst, const T *src, ALuint srcstep, ALuint samples)\
{ \
ALuint i; \
for(i = 0;i < samples;i++) \
@@ -63,7 +307,7 @@ DECL_TEMPLATE(ALfloat)
#undef DECL_TEMPLATE
-static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
+static void LoadSamples(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtType srctype, ALuint samples)
{
switch(srctype)
{
@@ -79,7 +323,7 @@ static void LoadData(ALfloat *dst, const ALvoid *src, ALuint srcstep, enum FmtTy
}
}
-static void SilenceData(ALfloat *dst, ALuint samples)
+static inline void SilenceSamples(ALfloat *dst, ALuint samples)
{
ALuint i;
for(i = 0;i < samples;i++)
@@ -95,20 +339,24 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
switch(type)
{
case AF_None:
+ ALfilterState_processPassthru(lpfilter, src, numsamples);
+ ALfilterState_processPassthru(hpfilter, src, numsamples);
break;
case AF_LowPass:
ALfilterState_process(lpfilter, dst, src, numsamples);
+ ALfilterState_processPassthru(hpfilter, dst, numsamples);
return dst;
case AF_HighPass:
+ ALfilterState_processPassthru(lpfilter, src, numsamples);
ALfilterState_process(hpfilter, dst, src, numsamples);
return dst;
case AF_BandPass:
for(i = 0;i < numsamples;)
{
- ALfloat temp[64];
- ALuint todo = minu(64, numsamples-i);
+ ALfloat temp[256];
+ ALuint todo = minu(256, numsamples-i);
ALfilterState_process(lpfilter, temp, src+i, todo);
ALfilterState_process(hpfilter, dst+i, temp, todo);
@@ -120,38 +368,38 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
}
-ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
+ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
{
- ALsource *Source = src->Source;
+ ResamplerFunc Resample;
ALbufferlistitem *BufferListItem;
ALuint DataPosInt, DataPosFrac;
ALboolean Looping;
ALuint increment;
- enum Resampler Resampler;
ALenum State;
ALuint OutPos;
ALuint NumChannels;
ALuint SampleSize;
ALint64 DataSize64;
+ ALuint IrSize;
ALuint chan, j;
/* Get source info */
State = Source->state;
- BufferListItem = Source->current_buffer;
+ BufferListItem = ATOMIC_LOAD(&Source->current_buffer);
DataPosInt = Source->position;
DataPosFrac = Source->position_fraction;
Looping = Source->Looping;
- increment = src->Step;
- Resampler = (increment==FRACTIONONE) ? PointResampler : Source->Resampler;
NumChannels = Source->NumChannels;
SampleSize = Source->SampleSize;
+ increment = voice->Step;
- /* Get current buffer queue item */
+ IrSize = (Device->Hrtf ? GetHrtfIrSize(Device->Hrtf) : 0);
+
+ Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
+ Resample_copy32_C : ResampleSamples);
OutPos = 0;
do {
- const ALuint BufferPrePadding = ResamplerPrePadding[Resampler];
- const ALuint BufferPadding = ResamplerPadding[Resampler];
ALuint SrcBufferSize, DstBufferSize;
/* Figure out how many buffer samples will be needed */
@@ -159,13 +407,13 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
DataSize64 *= increment;
DataSize64 += DataPosFrac+FRACTIONMASK;
DataSize64 >>= FRACTIONBITS;
- DataSize64 += BufferPadding+BufferPrePadding;
+ DataSize64 += MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
SrcBufferSize = (ALuint)mini64(DataSize64, BUFFERSIZE);
/* Figure out how many samples we can actually mix from this. */
DataSize64 = SrcBufferSize;
- DataSize64 -= BufferPadding+BufferPrePadding;
+ DataSize64 -= MAX_POST_SAMPLES+MAX_PRE_SAMPLES;
DataSize64 <<= FRACTIONBITS;
DataSize64 -= DataPosFrac;
@@ -181,7 +429,11 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
{
const ALfloat *ResampledData;
ALfloat *SrcData = Device->SourceData;
- ALuint SrcDataSize = 0;
+ ALuint SrcDataSize;
+
+ /* Load the previous samples into the source data first. */
+ memcpy(SrcData, voice->PrevSamples[chan], MAX_PRE_SAMPLES*sizeof(ALfloat));
+ SrcDataSize = MAX_PRE_SAMPLES;
if(Source->SourceType == AL_STATIC)
{
@@ -190,33 +442,24 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
ALuint DataSize;
ALuint pos;
+ /* Offset buffer data to current channel */
+ Data += chan*SampleSize;
+
/* If current pos is beyond the loop range, do not loop */
if(Looping == AL_FALSE || DataPosInt >= (ALuint)ALBuffer->LoopEnd)
{
Looping = AL_FALSE;
- if(DataPosInt >= BufferPrePadding)
- pos = DataPosInt - BufferPrePadding;
- else
- {
- DataSize = BufferPrePadding - DataPosInt;
- DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
- SilenceData(&SrcData[SrcDataSize], DataSize);
- SrcDataSize += DataSize;
-
- pos = 0;
- }
-
- /* Copy what's left to play in the source buffer, and clear the
- * rest of the temp buffer */
+ /* Load what's left to play from the source buffer, and
+ * clear the rest of the temp buffer */
+ pos = DataPosInt;
DataSize = minu(SrcBufferSize - SrcDataSize, ALBuffer->SampleLen - pos);
- LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
- NumChannels, ALBuffer->FmtType, DataSize);
+ LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
+ NumChannels, ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
- SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
+ SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
SrcDataSize += SrcBufferSize - SrcDataSize;
}
else
@@ -224,34 +467,14 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
ALuint LoopStart = ALBuffer->LoopStart;
ALuint LoopEnd = ALBuffer->LoopEnd;
- if(DataPosInt >= LoopStart)
- {
- pos = DataPosInt-LoopStart;
- while(pos < BufferPrePadding)
- pos += LoopEnd-LoopStart;
- pos -= BufferPrePadding;
- pos += LoopStart;
- }
- else if(DataPosInt >= BufferPrePadding)
- pos = DataPosInt - BufferPrePadding;
- else
- {
- DataSize = BufferPrePadding - DataPosInt;
- DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
-
- SilenceData(&SrcData[SrcDataSize], DataSize);
- SrcDataSize += DataSize;
-
- pos = 0;
- }
-
- /* Copy what's left of this loop iteration, then copy repeats
- * of the loop section */
+ /* Load what's left of this loop iteration, then load
+ * repeats of the loop section */
+ pos = DataPosInt;
DataSize = LoopEnd - pos;
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
- LoadData(&SrcData[SrcDataSize], &Data[(pos*NumChannels + chan)*SampleSize],
- NumChannels, ALBuffer->FmtType, DataSize);
+ LoadSamples(&SrcData[SrcDataSize], &Data[pos * NumChannels*SampleSize],
+ NumChannels, ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
DataSize = LoopEnd-LoopStart;
@@ -259,8 +482,8 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
{
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
- LoadData(&SrcData[SrcDataSize], &Data[(LoopStart*NumChannels + chan)*SampleSize],
- NumChannels, ALBuffer->FmtType, DataSize);
+ LoadSamples(&SrcData[SrcDataSize], &Data[LoopStart * NumChannels*SampleSize],
+ NumChannels, ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
}
}
@@ -269,45 +492,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
{
/* Crawl the buffer queue to fill in the temp buffer */
ALbufferlistitem *tmpiter = BufferListItem;
- ALuint pos;
-
- if(DataPosInt >= BufferPrePadding)
- pos = DataPosInt - BufferPrePadding;
- else
- {
- pos = BufferPrePadding - DataPosInt;
- while(pos > 0)
- {
- ALbufferlistitem *prev;
- if((prev=tmpiter->prev) != NULL)
- tmpiter = prev;
- else if(Looping)
- {
- while(tmpiter->next)
- tmpiter = tmpiter->next;
- }
- else
- {
- ALuint DataSize = minu(SrcBufferSize - SrcDataSize, pos);
-
- SilenceData(&SrcData[SrcDataSize], DataSize);
- SrcDataSize += DataSize;
-
- pos = 0;
- break;
- }
-
- if(tmpiter->buffer)
- {
- if((ALuint)tmpiter->buffer->SampleLen > pos)
- {
- pos = tmpiter->buffer->SampleLen - pos;
- break;
- }
- pos -= tmpiter->buffer->SampleLen;
- }
- }
- }
+ ALuint pos = DataPosInt;
while(tmpiter && SrcBufferSize > SrcDataSize)
{
@@ -327,29 +512,35 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
pos -= pos;
DataSize = minu(SrcBufferSize - SrcDataSize, DataSize);
- LoadData(&SrcData[SrcDataSize], Data, NumChannels,
- ALBuffer->FmtType, DataSize);
+ LoadSamples(&SrcData[SrcDataSize], Data, NumChannels,
+ ALBuffer->FmtType, DataSize);
SrcDataSize += DataSize;
}
}
tmpiter = tmpiter->next;
if(!tmpiter && Looping)
- tmpiter = Source->queue;
+ tmpiter = ATOMIC_LOAD(&Source->queue);
else if(!tmpiter)
{
- SilenceData(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
+ SilenceSamples(&SrcData[SrcDataSize], SrcBufferSize - SrcDataSize);
SrcDataSize += SrcBufferSize - SrcDataSize;
}
}
}
+ /* Store the last source samples used for next time. */
+ memcpy(voice->PrevSamples[chan],
+ &SrcData[(increment*DstBufferSize + DataPosFrac)>>FRACTIONBITS],
+ MAX_PRE_SAMPLES*sizeof(ALfloat)
+ );
+
/* Now resample, then filter and mix to the appropriate outputs. */
- ResampledData = src->Resample(
- &SrcData[BufferPrePadding], DataPosFrac, increment,
+ ResampledData = Resample(&voice->SincState,
+ &SrcData[MAX_PRE_SAMPLES], DataPosFrac, increment,
Device->ResampledData, DstBufferSize
);
{
- DirectParams *parms = &src->Direct;
+ DirectParams *parms = &voice->Direct;
const ALfloat *samples;
samples = DoFilters(
@@ -357,20 +548,18 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
Device->FilteredData, ResampledData, DstBufferSize,
parms->Filters[chan].ActiveType
);
- if(!src->IsHrtf)
- src->Dry.Mix(parms->OutBuffer, samples, &parms->Mix.Gains[chan],
- parms->Counter, OutPos, DstBufferSize);
+ if(!voice->IsHrtf)
+ MixSamples(samples, parms->OutChannels, parms->OutBuffer, parms->Gains[chan],
+ parms->Counter, OutPos, DstBufferSize);
else
- src->Dry.HrtfMix(
- parms->OutBuffer, samples, parms->Counter, src->Offset,
- OutPos, parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan],
- &parms->Mix.Hrtf.State[chan], DstBufferSize
- );
+ MixHrtfSamples(parms->OutBuffer, samples, parms->Counter, voice->Offset,
+ OutPos, IrSize, &parms->Hrtf[chan].Params,
+ &parms->Hrtf[chan].State, DstBufferSize);
}
for(j = 0;j < Device->NumAuxSends;j++)
{
- SendParams *parms = &src->Send[j];
+ SendParams *parms = &voice->Send[j];
const ALfloat *samples;
if(!parms->OutBuffer)
@@ -381,8 +570,8 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
Device->FilteredData, ResampledData, DstBufferSize,
parms->Filters[chan].ActiveType
);
- src->WetMix(parms->OutBuffer, samples, &parms->Gain,
- parms->Counter, OutPos, DstBufferSize);
+ MixSamples(samples, 1, parms->OutBuffer, &parms->Gains[chan],
+ parms->Counter, OutPos, DstBufferSize);
}
}
/* Update positions */
@@ -391,10 +580,10 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
DataPosFrac &= FRACTIONMASK;
OutPos += DstBufferSize;
- src->Offset += DstBufferSize;
- src->Direct.Counter = maxu(src->Direct.Counter, DstBufferSize) - DstBufferSize;
+ voice->Offset += DstBufferSize;
+ voice->Direct.Counter = maxu(voice->Direct.Counter, DstBufferSize) - DstBufferSize;
for(j = 0;j < Device->NumAuxSends;j++)
- src->Send[j].Counter = maxu(src->Send[j].Counter, DstBufferSize) - DstBufferSize;
+ voice->Send[j].Counter = maxu(voice->Send[j].Counter, DstBufferSize) - DstBufferSize;
/* Handle looping sources */
while(1)
@@ -423,17 +612,18 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
if(DataSize > DataPosInt)
break;
- if(BufferListItem->next)
- BufferListItem = BufferListItem->next;
- else if(Looping)
- BufferListItem = Source->queue;
- else
+ if(!(BufferListItem=BufferListItem->next))
{
- State = AL_STOPPED;
- BufferListItem = NULL;
- DataPosInt = 0;
- DataPosFrac = 0;
- break;
+ if(Looping)
+ BufferListItem = ATOMIC_LOAD(&Source->queue);
+ else
+ {
+ State = AL_STOPPED;
+ BufferListItem = NULL;
+ DataPosInt = 0;
+ DataPosFrac = 0;
+ break;
+ }
}
DataPosInt -= DataSize;
@@ -442,7 +632,7 @@ ALvoid MixSource(ALactivesource *src, ALCdevice *Device, ALuint SamplesToDo)
/* Update source info */
Source->state = State;
- Source->current_buffer = BufferListItem;
+ ATOMIC_STORE(&Source->current_buffer, BufferListItem);
Source->position = DataPosInt;
Source->position_fraction = DataPosFrac;
}