aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/ALu.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2011-04-14 21:03:37 -0700
committerChris Robinson <[email protected]>2011-04-14 21:03:37 -0700
commit678d0b87d0be1aa84a07dff82652f2867d046921 (patch)
tree8fb3b7a468b3e8d03d4304813b2d368fb8253a26 /Alc/ALu.c
parent319dfce300d85d0fa2c26dbbbfc3d3a953dbcb76 (diff)
Apply the device matrix to the multi-channel source matrix
Mono sources and effects already output according to the available output device channels. Multiplying the device matrix with the source matrix results in a matrix that has the same effect as applying the source matrix followed by the device matrix, so all the channel remixing can be done in one place.
Diffstat (limited to 'Alc/ALu.c')
-rw-r--r--Alc/ALu.c146
1 files changed, 74 insertions, 72 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 7ac6f2fe..8c4dba3c 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -82,6 +82,7 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
ALbufferlistitem *BufferListItem;
enum DevFmtChannels DevChans;
enum FmtChannels Channels;
+ ALfloat SrcMatrix[MAXCHANNELS][MAXCHANNELS];
ALfloat DryGain, DryGainHF;
ALfloat WetGain[MAX_SENDS];
ALfloat WetGainHF[MAX_SENDS];
@@ -154,19 +155,18 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
{
ALuint i2;
for(i2 = 0;i2 < MAXCHANNELS;i2++)
- ALSource->Params.DryGains[i][i2] = 0.0f;
+ SrcMatrix[i][i2] = 0.0f;
}
-
switch(Channels)
{
case FmtMono:
- ALSource->Params.DryGains[0][FRONT_CENTER] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_CENTER] = DryGain * ListenerGain;
break;
case FmtStereo:
if(DupStereo == AL_FALSE)
{
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
}
else
{
@@ -174,82 +174,99 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext)
{
case DevFmtMono:
case DevFmtStereo:
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
break;
case DevFmtQuad:
case DevFmtX51:
DryGain *= aluSqrt(2.0f/4.0f);
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[0][BACK_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][BACK_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][BACK_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][BACK_RIGHT] = DryGain * ListenerGain;
break;
case DevFmtX61:
DryGain *= aluSqrt(2.0f/4.0f);
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[0][SIDE_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][SIDE_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][SIDE_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][SIDE_RIGHT] = DryGain * ListenerGain;
break;
case DevFmtX71:
DryGain *= aluSqrt(2.0f/6.0f);
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[0][BACK_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][BACK_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[0][SIDE_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][SIDE_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][BACK_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][BACK_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][SIDE_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][SIDE_RIGHT] = DryGain * ListenerGain;
break;
}
}
break;
case FmtRear:
- ALSource->Params.DryGains[0][BACK_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][BACK_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][BACK_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][BACK_RIGHT] = DryGain * ListenerGain;
break;
case FmtQuad:
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[2][BACK_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[3][BACK_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[2][BACK_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[3][BACK_RIGHT] = DryGain * ListenerGain;
break;
case FmtX51:
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[2][FRONT_CENTER] = DryGain * ListenerGain;
- ALSource->Params.DryGains[3][LFE] = DryGain * ListenerGain;
- ALSource->Params.DryGains[4][BACK_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[5][BACK_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[2][FRONT_CENTER] = DryGain * ListenerGain;
+ SrcMatrix[3][LFE] = DryGain * ListenerGain;
+ SrcMatrix[4][BACK_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[5][BACK_RIGHT] = DryGain * ListenerGain;
break;
case FmtX61:
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[2][FRONT_CENTER] = DryGain * ListenerGain;
- ALSource->Params.DryGains[3][LFE] = DryGain * ListenerGain;
- ALSource->Params.DryGains[4][BACK_CENTER] = DryGain * ListenerGain;
- ALSource->Params.DryGains[5][SIDE_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[6][SIDE_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[2][FRONT_CENTER] = DryGain * ListenerGain;
+ SrcMatrix[3][LFE] = DryGain * ListenerGain;
+ SrcMatrix[4][BACK_CENTER] = DryGain * ListenerGain;
+ SrcMatrix[5][SIDE_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[6][SIDE_RIGHT] = DryGain * ListenerGain;
break;
case FmtX71:
- ALSource->Params.DryGains[0][FRONT_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[1][FRONT_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[2][FRONT_CENTER] = DryGain * ListenerGain;
- ALSource->Params.DryGains[3][LFE] = DryGain * ListenerGain;
- ALSource->Params.DryGains[4][BACK_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[5][BACK_RIGHT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[6][SIDE_LEFT] = DryGain * ListenerGain;
- ALSource->Params.DryGains[7][SIDE_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[0][FRONT_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[1][FRONT_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[2][FRONT_CENTER] = DryGain * ListenerGain;
+ SrcMatrix[3][LFE] = DryGain * ListenerGain;
+ SrcMatrix[4][BACK_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[5][BACK_RIGHT] = DryGain * ListenerGain;
+ SrcMatrix[6][SIDE_LEFT] = DryGain * ListenerGain;
+ SrcMatrix[7][SIDE_RIGHT] = DryGain * ListenerGain;
break;
}
+ for(i = 0;i < MAXCHANNELS;i++)
+ {
+ ALuint j, k;
+ for(j = 0;j < MAXCHANNELS;j++)
+ {
+ ALfloat (*DevMatrix)[MAXCHANNELS] = ALContext->Device->ChannelMatrix;
+ ALSource->Params.DryGains[i][j] = 0.0f;
+ for(k = 0;k < MAXCHANNELS;k++)
+ {
+ /* Matrix mult: O[i][j] += A[i][k] * B[k][j]
+ * However, our device matrix is transposed, so we do:
+ * O[i][j] += A[i][k] * B[j][k]
+ */
+ ALSource->Params.DryGains[i][j] += SrcMatrix[i][k] * DevMatrix[j][k];
+ }
+ }
+ }
for(i = 0;i < NumSends;i++)
{
@@ -736,19 +753,13 @@ static const Channel X71Chans[] = { FRONT_LEFT, FRONT_RIGHT,
static void Write_##T##_##chans(ALCdevice *device, T *buffer, ALuint SamplesToDo)\
{ \
ALfloat (*DryBuffer)[MAXCHANNELS] = device->DryBuffer; \
- ALfloat (*Matrix)[MAXCHANNELS] = device->ChannelMatrix; \
const ALuint *ChanMap = device->DevChannels; \
- ALuint i, j, c; \
+ ALuint i, j; \
\
for(i = 0;i < SamplesToDo;i++) \
{ \
for(j = 0;j < N;j++) \
- { \
- ALfloat samp = 0.0f; \
- for(c = 0;c < MAXCHANNELS;c++) \
- samp += DryBuffer[i][c] * Matrix[chans[j]][c]; \
- buffer[ChanMap[chans[j]]] = func(samp); \
- } \
+ buffer[ChanMap[chans[j]]] = func(DryBuffer[i][chans[j]]); \
buffer += N; \
} \
}
@@ -789,23 +800,19 @@ DECL_TEMPLATE(ALbyte, X71Chans,8, aluF2B)
static void Write_##T##_##chans(ALCdevice *device, T *buffer, ALuint SamplesToDo)\
{ \
ALfloat (*DryBuffer)[MAXCHANNELS] = device->DryBuffer; \
- ALfloat (*Matrix)[MAXCHANNELS] = device->ChannelMatrix; \
const ALuint *ChanMap = device->DevChannels; \
- ALuint i, j, c; \
+ ALuint i, j; \
\
if(device->Bs2b) \
{ \
for(i = 0;i < SamplesToDo;i++) \
{ \
- float samples[2] = { 0.0f, 0.0f }; \
- for(c = 0;c < MAXCHANNELS;c++) \
- { \
- samples[0] += DryBuffer[i][c]*Matrix[FRONT_LEFT][c]; \
- samples[1] += DryBuffer[i][c]*Matrix[FRONT_RIGHT][c]; \
- } \
+ float samples[2]; \
+ samples[0] = DryBuffer[i][chans[0]]; \
+ samples[1] = DryBuffer[i][chans[1]]; \
bs2b_cross_feed(device->Bs2b, samples); \
- buffer[ChanMap[FRONT_LEFT]] = func(samples[0]); \
- buffer[ChanMap[FRONT_RIGHT]] = func(samples[1]); \
+ buffer[ChanMap[chans[0]]] = func(samples[0]); \
+ buffer[ChanMap[chans[1]]] = func(samples[1]); \
buffer += 2; \
} \
} \
@@ -814,12 +821,7 @@ static void Write_##T##_##chans(ALCdevice *device, T *buffer, ALuint SamplesToDo
for(i = 0;i < SamplesToDo;i++) \
{ \
for(j = 0;j < N;j++) \
- { \
- ALfloat samp = 0.0f; \
- for(c = 0;c < MAXCHANNELS;c++) \
- samp += DryBuffer[i][c] * Matrix[chans[j]][c]; \
- buffer[ChanMap[chans[j]]] = func(samp); \
- } \
+ buffer[ChanMap[chans[j]]] = func(DryBuffer[i][chans[j]]); \
buffer += N; \
} \
} \