From 69f9ab88b9b9ad1b14bd1a143af230eab2a15b61 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 26 Nov 2009 00:39:32 -0800 Subject: [PATCH] Send multi-channel sources to auxiliary effect slots They are downmixed to mono using a volume-preserving scalar, and passed through a 1-pole low-pass filter (not chained) --- Alc/ALu.c | 59 +++++++++++++++++++++++++++++++++++++-------- OpenAL32/Include/alSource.h | 2 +- 2 files changed, 50 insertions(+), 11 deletions(-) diff --git a/Alc/ALu.c b/Alc/ALu.c index 6b7dc364..fa2c92ea 100644 --- a/Alc/ALu.c +++ b/Alc/ALu.c @@ -478,8 +478,29 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext, ALsource *ALSource, ALSource->Params.DryGains[FRONT_CENTER] = DryMix * ListenerGain; ALSource->Params.DryGains[BACK_CENTER] = DryMix * ListenerGain; ALSource->Params.DryGains[LFE] = DryMix * ListenerGain; - for(i = 0;i < MAX_SENDS;i++) + + for(i = 0;i < NumSends;i++) + { + WetGain[i] = SourceVolume; + WetGain[i] = __min(WetGain[i],MaxVolume); + WetGain[i] = __max(WetGain[i],MinVolume); + WetGainHF[i] = 1.0f; + + switch(ALSource->Send[i].WetFilter.type) + { + case AL_FILTER_LOWPASS: + WetGain[i] *= ALSource->Send[i].WetFilter.Gain; + WetGainHF[i] *= ALSource->Send[i].WetFilter.GainHF; + break; + } + + ALSource->Params.WetGains[i] = WetGain[i] * ListenerGain; + } + for(i = NumSends;i < MAX_SENDS;i++) + { ALSource->Params.WetGains[i] = 0.0f; + WetGainHF[i] = 1.0f; + } /* Update filter coefficients. Calculations based on the I3DL2 * spec. */ @@ -495,8 +516,18 @@ static ALvoid CalcSourceParams(const ALCcontext *ALContext, ALsource *ALSource, a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / (1 - g); ALSource->Params.iirFilter.coeff = a; - for(i = 0;i < MAX_SENDS;i++) - ALSource->Params.Send[i].iirFilter.coeff = 0.0f; + + for(i = 0;i < NumSends;i++) + { + /* We use a one-pole filter, so we need to take the squared gain */ + g = __max(WetGainHF[i], 0.1f); + g *= g; + a = 0.0f; + if(g < 0.9999f) /* 1-epsilon */ + a = (1 - g*cw - aluSqrt(2*g*(1-cw) - g*g*(1 - cw*cw))) / + (1 - g); + ALSource->Params.Send[i].iirFilter.coeff = a; + } return; } @@ -832,7 +863,7 @@ static void MixSomeSources(ALCcontext *ALContext, float (*DryBuffer)[OUTPUTCHANN ALfloat wetGainStep[MAX_SENDS]; ALuint i, j, k, out; ALsource *ALSource; - ALfloat value; + ALfloat value, outsamp; ALbufferlistitem *BufferListItem; ALint64 DataSize64,DataPos64; FILTER *DryFilter, *WetFilter[MAX_SENDS]; @@ -1009,8 +1040,6 @@ another_source: if(Channels == 1) /* Mono */ { - ALfloat outsamp; - while(BufferSize--) { for(i = 0;i < OUTPUTCHANNELS;i++) @@ -1050,21 +1079,27 @@ another_source: const int chans[] = { FRONT_LEFT, FRONT_RIGHT }; + const ALfloat scaler = aluSqrt(1.0f/Channels); #define DO_MIX() do { \ - for(i = 0;i < MAX_SENDS;i++) \ - WetSend[i] += wetGainStep[i]*BufferSize; \ while(BufferSize--) \ { \ for(i = 0;i < OUTPUTCHANNELS;i++) \ DrySend[i] += dryGainStep[i]; \ + for(i = 0;i < MAX_SENDS;i++) \ + WetSend[i] += wetGainStep[i]; \ \ for(i = 0;i < Channels;i++) \ { \ value = lerp(Data[k*Channels + i], Data[(k+1)*Channels + i], DataPosFrac); \ - value = lpFilter2P(DryFilter, chans[i]*2, value)*DrySend[chans[i]]; \ + outsamp = lpFilter2P(DryFilter, chans[i]*2, value)*DrySend[chans[i]]; \ for(out = 0;out < OUTPUTCHANNELS;out++) \ - DryBuffer[j][out] += value*Matrix[chans[i]][out]; \ + DryBuffer[j][out] += outsamp*Matrix[chans[i]][out]; \ + for(out = 0;out < MAX_SENDS;out++) \ + { \ + outsamp = lpFilter1P(WetFilter[out], chans[out], value); \ + WetBuffer[out][j] += outsamp*WetSend[out]*scaler; \ + } \ } \ \ DataPosFrac += increment; \ @@ -1082,6 +1117,7 @@ another_source: FRONT_LEFT, FRONT_RIGHT, BACK_LEFT, BACK_RIGHT }; + const ALfloat scaler = aluSqrt(1.0f/Channels); DO_MIX(); } @@ -1092,6 +1128,7 @@ another_source: FRONT_CENTER, LFE, BACK_LEFT, BACK_RIGHT }; + const ALfloat scaler = aluSqrt(1.0f/Channels); DO_MIX(); } @@ -1103,6 +1140,7 @@ another_source: BACK_CENTER, SIDE_LEFT, SIDE_RIGHT }; + const ALfloat scaler = aluSqrt(1.0f/Channels); DO_MIX(); } @@ -1114,6 +1152,7 @@ another_source: BACK_LEFT, BACK_RIGHT, SIDE_LEFT, SIDE_RIGHT }; + const ALfloat scaler = aluSqrt(1.0f/Channels); DO_MIX(); #undef DO_MIX diff --git a/OpenAL32/Include/alSource.h b/OpenAL32/Include/alSource.h index 1e54031b..3889c85c 100644 --- a/OpenAL32/Include/alSource.h +++ b/OpenAL32/Include/alSource.h @@ -93,7 +93,7 @@ typedef struct ALsource struct { FILTER iirFilter; - ALfloat history[2]; + ALfloat history[OUTPUTCHANNELS]; } Send[MAX_SENDS]; FILTER iirFilter; -- 2.11.4.GIT