aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/mixer.c
diff options
context:
space:
mode:
Diffstat (limited to 'Alc/mixer.c')
-rw-r--r--Alc/mixer.c272
1 files changed, 196 insertions, 76 deletions
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 7f64bad9..732f3b2b 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -72,16 +72,23 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
}
-#define DO_MIX_MONO(data,sampler) do { \
+#define DECL_MIX_MONO(T,sampler) \
+static void MixMono_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
+ const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, ALuint DataEnd, \
+ ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
+{ \
ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
ALfloat *ClickRemoval, *PendingClicks; \
ALuint pos, frac; \
ALfloat DrySend[OUTPUTCHANNELS]; \
FILTER *DryFilter; \
ALuint BufferIdx; \
+ ALuint increment; \
ALuint i, out; \
ALfloat value; \
\
+ increment = Source->Params.Step; \
+ \
DryBuffer = Device->DryBuffer; \
ClickRemoval = Device->ClickRemoval; \
PendingClicks = Device->PendingClicks; \
@@ -89,8 +96,8 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
for(i = 0;i < OUTPUTCHANNELS;i++) \
DrySend[i] = Source->Params.DryGains[i]; \
\
- pos = DataPosInt; \
- frac = DataPosFrac; \
+ pos = *DataPosInt; \
+ frac = *DataPosFrac; \
\
if(j == 0) \
{ \
@@ -131,7 +138,7 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
{ \
ALuint p = pos; \
ALuint f = frac; \
- if(p >= LoopEnd) \
+ if(p >= DataEnd) \
{ \
ALuint64 pos64 = pos; \
pos64 <<= FRACTIONBITS; \
@@ -171,8 +178,8 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
- pos = DataPosInt; \
- frac = DataPosFrac; \
+ pos = *DataPosInt; \
+ frac = *DataPosFrac; \
j -= BufferSize; \
\
if(j == 0) \
@@ -200,7 +207,7 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
{ \
ALuint p = pos; \
ALuint f = frac; \
- if(p >= LoopEnd) \
+ if(p >= DataEnd) \
{ \
ALuint64 pos64 = pos; \
pos64 <<= FRACTIONBITS; \
@@ -215,11 +222,30 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
WetPendingClicks[0] += value*WetSend; \
} \
} \
- DataPosInt = pos; \
- DataPosFrac = frac; \
-} while(0)
+ *DataPosInt = pos; \
+ *DataPosFrac = frac; \
+}
+
+DECL_MIX_MONO(ALfloat, point32)
+DECL_MIX_MONO(ALfloat, lerp32)
+DECL_MIX_MONO(ALfloat, cos_lerp32)
+
+DECL_MIX_MONO(ALshort, point16)
+DECL_MIX_MONO(ALshort, lerp16)
+DECL_MIX_MONO(ALshort, cos_lerp16)
-#define DO_MIX_STEREO(data,sampler) do { \
+
+#define DECL_MIX_STEREO(T,sampler) \
+static void MixStereo_##T##_##sampler(ALsource *Source, ALCdevice *Device, \
+ const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, ALuint DataEnd, \
+ ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
+{ \
+ static const ALuint Channels = 2; \
+ static const Channel chans[] = { \
+ FRONT_LEFT, FRONT_RIGHT, \
+ SIDE_LEFT, SIDE_RIGHT, \
+ BACK_LEFT, BACK_RIGHT \
+ }; \
const ALfloat scaler = 1.0f/Channels; \
ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
ALfloat *ClickRemoval, *PendingClicks; \
@@ -227,9 +253,12 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
ALfloat DrySend[OUTPUTCHANNELS]; \
FILTER *DryFilter; \
ALuint BufferIdx; \
+ ALuint increment; \
ALuint i, out; \
ALfloat value; \
\
+ increment = Source->Params.Step; \
+ \
DryBuffer = Device->DryBuffer; \
ClickRemoval = Device->ClickRemoval; \
PendingClicks = Device->PendingClicks; \
@@ -237,8 +266,8 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
for(i = 0;i < OUTPUTCHANNELS;i++) \
DrySend[i] = Source->Params.DryGains[i]; \
\
- pos = DataPosInt; \
- frac = DataPosFrac; \
+ pos = *DataPosInt; \
+ frac = *DataPosFrac; \
\
if(j == 0) \
{ \
@@ -275,7 +304,7 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
{ \
ALuint p = pos; \
ALuint f = frac; \
- if(p >= LoopEnd) \
+ if(p >= DataEnd) \
{ \
ALuint64 pos64 = pos; \
pos64 <<= FRACTIONBITS; \
@@ -314,8 +343,8 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
- pos = DataPosInt; \
- frac = DataPosFrac; \
+ pos = *DataPosInt; \
+ frac = *DataPosFrac; \
j -= BufferSize; \
\
if(j == 0) \
@@ -349,7 +378,7 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
{ \
ALuint p = pos; \
ALuint f = frac; \
- if(p >= LoopEnd) \
+ if(p >= DataEnd) \
{ \
ALuint64 pos64 = pos; \
pos64 <<= FRACTIONBITS; \
@@ -368,11 +397,26 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
} \
} \
} \
- DataPosInt = pos; \
- DataPosFrac = frac; \
-} while(0)
+ *DataPosInt = pos; \
+ *DataPosFrac = frac; \
+}
+
+DECL_MIX_STEREO(ALfloat, point32)
+DECL_MIX_STEREO(ALfloat, lerp32)
+DECL_MIX_STEREO(ALfloat, cos_lerp32)
-#define DO_MIX_MC(data,sampler) do { \
+DECL_MIX_STEREO(ALshort, point16)
+DECL_MIX_STEREO(ALshort, lerp16)
+DECL_MIX_STEREO(ALshort, cos_lerp16)
+
+
+
+#define DECL_MIX_MC(T,chans,sampler) \
+static void MixMC_##T##_##chans##_##sampler(ALsource *Source, ALCdevice *Device,\
+ const T *data, ALuint *DataPosInt, ALuint *DataPosFrac, ALuint DataEnd, \
+ ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
+{ \
+ static const ALuint Channels = sizeof(chans)/sizeof(chans[0]); \
const ALfloat scaler = 1.0f/Channels; \
ALfloat (*DryBuffer)[OUTPUTCHANNELS]; \
ALfloat *ClickRemoval, *PendingClicks; \
@@ -380,9 +424,12 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
ALfloat DrySend[OUTPUTCHANNELS]; \
FILTER *DryFilter; \
ALuint BufferIdx; \
+ ALuint increment; \
ALuint i, out; \
ALfloat value; \
\
+ increment = Source->Params.Step; \
+ \
DryBuffer = Device->DryBuffer; \
ClickRemoval = Device->ClickRemoval; \
PendingClicks = Device->PendingClicks; \
@@ -390,8 +437,8 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
for(i = 0;i < OUTPUTCHANNELS;i++) \
DrySend[i] = Source->Params.DryGains[i]; \
\
- pos = DataPosInt; \
- frac = DataPosFrac; \
+ pos = *DataPosInt; \
+ frac = *DataPosFrac; \
\
if(j == 0) \
{ \
@@ -424,7 +471,7 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
{ \
ALuint p = pos; \
ALuint f = frac; \
- if(p >= LoopEnd) \
+ if(p >= DataEnd) \
{ \
ALuint64 pos64 = pos; \
pos64 <<= FRACTIONBITS; \
@@ -461,8 +508,8 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
WetFilter = &Source->Params.Send[out].iirFilter; \
WetSend = Source->Params.Send[out].WetGain; \
\
- pos = DataPosInt; \
- frac = DataPosFrac; \
+ pos = *DataPosInt; \
+ frac = *DataPosFrac; \
j -= BufferSize; \
\
if(j == 0) \
@@ -496,7 +543,7 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
{ \
ALuint p = pos; \
ALuint f = frac; \
- if(p >= LoopEnd) \
+ if(p >= DataEnd) \
{ \
ALuint64 pos64 = pos; \
pos64 <<= FRACTIONBITS; \
@@ -515,73 +562,133 @@ static __inline ALfloat cos_lerp16(ALfloat val1, ALfloat val2, ALint frac)
} \
} \
} \
- DataPosInt = pos; \
- DataPosFrac = frac; \
-} while(0)
+ *DataPosInt = pos; \
+ *DataPosFrac = frac; \
+}
+static const Channel QuadChans[] = { FRONT_LEFT, FRONT_RIGHT,
+ BACK_LEFT, BACK_RIGHT };
+DECL_MIX_MC(ALfloat, QuadChans, point32)
+DECL_MIX_MC(ALfloat, QuadChans, lerp32)
+DECL_MIX_MC(ALfloat, QuadChans, cos_lerp32)
-#define MIX_MONO(sampler) do { \
- if(Bytes == 4) \
- DO_MIX_MONO(Data.p32,sampler##32); \
- else if(Bytes == 2) \
- DO_MIX_MONO(Data.p16,sampler##16); \
-} while(0)
+DECL_MIX_MC(ALshort, QuadChans, point16)
+DECL_MIX_MC(ALshort, QuadChans, lerp16)
+DECL_MIX_MC(ALshort, QuadChans, cos_lerp16)
-#define MIX_STEREO(sampler) do { \
- const int chans[] = { \
- FRONT_LEFT, FRONT_RIGHT, \
- SIDE_LEFT, SIDE_RIGHT, \
- BACK_LEFT, BACK_RIGHT \
- }; \
- \
- if(Bytes == 4) \
- DO_MIX_STEREO(Data.p32,sampler##32); \
- else if(Bytes == 2) \
- DO_MIX_STEREO(Data.p16,sampler##16); \
-} while(0)
-#define MIX_MC(sampler,...) do { \
- const int chans[] = { __VA_ARGS__ }; \
- \
- if(Bytes == 4) \
- DO_MIX_MC(Data.p32,sampler##32); \
- else if(Bytes == 2) \
- DO_MIX_MC(Data.p16,sampler##16); \
-} while(0)
+static const Channel X51Chans[] = { FRONT_LEFT, FRONT_RIGHT,
+ FRONT_CENTER, LFE,
+ BACK_LEFT, BACK_RIGHT };
+DECL_MIX_MC(ALfloat, X51Chans, point32)
+DECL_MIX_MC(ALfloat, X51Chans, lerp32)
+DECL_MIX_MC(ALfloat, X51Chans, cos_lerp32)
+
+DECL_MIX_MC(ALshort, X51Chans, point16)
+DECL_MIX_MC(ALshort, X51Chans, lerp16)
+DECL_MIX_MC(ALshort, X51Chans, cos_lerp16)
-#define MIX(sampler) do { \
+static const Channel X61Chans[] = { FRONT_LEFT, FRONT_RIGHT,
+ FRONT_CENTER, LFE,
+ BACK_CENTER,
+ SIDE_LEFT, SIDE_RIGHT };
+DECL_MIX_MC(ALfloat, X61Chans, point32)
+DECL_MIX_MC(ALfloat, X61Chans, lerp32)
+DECL_MIX_MC(ALfloat, X61Chans, cos_lerp32)
+
+DECL_MIX_MC(ALshort, X61Chans, point16)
+DECL_MIX_MC(ALshort, X61Chans, lerp16)
+DECL_MIX_MC(ALshort, X61Chans, cos_lerp16)
+
+
+static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
+ FRONT_CENTER, LFE,
+ BACK_LEFT, BACK_RIGHT,
+ SIDE_LEFT, SIDE_RIGHT };
+DECL_MIX_MC(ALfloat, X71Chans, point32)
+DECL_MIX_MC(ALfloat, X71Chans, lerp32)
+DECL_MIX_MC(ALfloat, X71Chans, cos_lerp32)
+
+DECL_MIX_MC(ALshort, X71Chans, point16)
+DECL_MIX_MC(ALshort, X71Chans, lerp16)
+DECL_MIX_MC(ALshort, X71Chans, cos_lerp16)
+
+
+#define DECL_MIX(sampler) \
+static void Mix_##sampler(ALsource *Source, ALCdevice *Device, \
+ const ALvoid *Data, ALuint *DataPosInt, ALuint *DataPosFrac, ALuint DataEnd,\
+ ALuint Channels, ALuint Bytes, \
+ ALuint j, ALuint SamplesToDo, ALuint BufferSize) \
+{ \
switch(Channels) \
{ \
case 1: /* Mono */ \
- MIX_MONO(sampler); \
+ if(Bytes == 4) \
+ MixMono_ALfloat_##sampler##32(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
+ else if(Bytes == 2) \
+ MixMono_ALshort_##sampler##16(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
break; \
case 2: /* Stereo */ \
- MIX_STEREO(sampler); \
+ if(Bytes == 4) \
+ MixStereo_ALfloat_##sampler##32(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
+ else if(Bytes == 2) \
+ MixStereo_ALshort_##sampler##16(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
break; \
case 4: /* Quad */ \
- MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
- BACK_LEFT, BACK_RIGHT); \
+ if(Bytes == 4) \
+ MixMC_ALfloat_QuadChans_##sampler##32(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
+ else if(Bytes == 2) \
+ MixMC_ALshort_QuadChans_##sampler##16(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
break; \
case 6: /* 5.1 */ \
- MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
- FRONT_CENTER, LFE, \
- BACK_LEFT, BACK_RIGHT); \
+ if(Bytes == 4) \
+ MixMC_ALfloat_X51Chans_##sampler##32(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
+ else if(Bytes == 2) \
+ MixMC_ALshort_X51Chans_##sampler##16(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
break; \
case 7: /* 6.1 */ \
- MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
- FRONT_CENTER, LFE, \
- BACK_CENTER, \
- SIDE_LEFT, SIDE_RIGHT); \
+ if(Bytes == 4) \
+ MixMC_ALfloat_X61Chans_##sampler##32(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
+ else if(Bytes == 2) \
+ MixMC_ALshort_X61Chans_##sampler##16(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
break; \
case 8: /* 7.1 */ \
- MIX_MC(sampler, FRONT_LEFT, FRONT_RIGHT, \
- FRONT_CENTER, LFE, \
- BACK_LEFT, BACK_RIGHT, \
- SIDE_LEFT, SIDE_RIGHT); \
+ if(Bytes == 4) \
+ MixMC_ALfloat_X71Chans_##sampler##32(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
+ else if(Bytes == 2) \
+ MixMC_ALshort_X71Chans_##sampler##16(Source, Device, \
+ Data, DataPosInt, DataPosFrac, DataEnd, \
+ j, SamplesToDo, BufferSize); \
break; \
} \
-} while(0)
+}
+
+DECL_MIX(point)
+DECL_MIX(lerp)
+DECL_MIX(cos_lerp)
ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
@@ -687,15 +794,28 @@ ALvoid MixSource(ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
switch(Source->Resampler)
{
case POINT_RESAMPLER:
- MIX(point); break;
+ Mix_point(Source, Device,
+ Data.p8, &DataPosInt, &DataPosFrac, LoopEnd,
+ Channels, Bytes,
+ j, SamplesToDo, BufferSize);
+ break;
case LINEAR_RESAMPLER:
- MIX(lerp); break;
+ Mix_lerp(Source, Device,
+ Data.p8, &DataPosInt, &DataPosFrac, LoopEnd,
+ Channels, Bytes,
+ j, SamplesToDo, BufferSize);
+ break;
case COSINE_RESAMPLER:
- MIX(cos_lerp); break;
+ Mix_cos_lerp(Source, Device,
+ Data.p8, &DataPosInt, &DataPosFrac, LoopEnd,
+ Channels, Bytes,
+ j, SamplesToDo, BufferSize);
+ break;
case RESAMPLER_MIN:
case RESAMPLER_MAX:
break;
}
+ j += BufferSize;
skipmix:
/* Handle looping sources */