diff options
author | Chris Robinson <[email protected]> | 2011-04-14 21:03:37 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2011-04-14 21:03:37 -0700 |
commit | 678d0b87d0be1aa84a07dff82652f2867d046921 (patch) | |
tree | 8fb3b7a468b3e8d03d4304813b2d368fb8253a26 /Alc/ALu.c | |
parent | 319dfce300d85d0fa2c26dbbbfc3d3a953dbcb76 (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.c | 146 |
1 files changed, 74 insertions, 72 deletions
@@ -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; \ } \ } \ |