diff options
author | Chris Robinson <[email protected]> | 2010-08-05 01:07:20 -0700 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2010-08-05 01:07:20 -0700 |
commit | 98bc60cfb72939cfabcdd118597a02a015091756 (patch) | |
tree | 7604d53bc502bdc156707299567aef1801b670da | |
parent | 2aacca76de7577db8632b796ce8e205207b23d68 (diff) |
Combine stereo and stereo-duplicate mixers
Use a separate update method for stereo sources to the set appropriate channel
gains
-rw-r--r-- | Alc/ALu.c | 144 | ||||
-rw-r--r-- | Alc/mixer.c | 32 | ||||
-rw-r--r-- | OpenAL32/Include/alu.h | 1 | ||||
-rw-r--r-- | OpenAL32/alSource.c | 4 |
4 files changed, 154 insertions, 27 deletions
@@ -157,6 +157,150 @@ ALvoid CalcNonAttnSourceParams(ALsource *ALSource, const ALCcontext *ALContext) } } +ALvoid CalcNonAttnStereoSourceParams(ALsource *ALSource, const ALCcontext *ALContext) +{ + ALfloat SourceVolume,ListenerGain,MinVolume,MaxVolume; + ALfloat DryGain, DryGainHF; + ALfloat WetGain[MAX_SENDS]; + ALfloat WetGainHF[MAX_SENDS]; + ALint NumSends, Frequency; + ALboolean DupStereo; + ALenum Format; + ALfloat cw; + ALint i; + + //Get context properties + Format = ALContext->Device->Format; + DupStereo = ALContext->Device->DuplicateStereo; + NumSends = ALContext->Device->NumAuxSends; + Frequency = ALContext->Device->Frequency; + + //Get listener properties + ListenerGain = ALContext->Listener.Gain; + + //Get source properties + SourceVolume = ALSource->flGain; + MinVolume = ALSource->flMinGain; + MaxVolume = ALSource->flMaxGain; + + //1. Multi-channel buffers always play "normal" + ALSource->Params.Pitch = ALSource->flPitch; + + DryGain = SourceVolume; + DryGain = __min(DryGain,MaxVolume); + DryGain = __max(DryGain,MinVolume); + DryGainHF = 1.0f; + + switch(ALSource->DirectFilter.type) + { + case AL_FILTER_LOWPASS: + DryGain *= ALSource->DirectFilter.Gain; + DryGainHF *= ALSource->DirectFilter.GainHF; + break; + } + + for(i = 0;i < OUTPUTCHANNELS;i++) + ALSource->Params.DryGains[i] = 0.0f; + + if(DupStereo == AL_FALSE) + { + ALSource->Params.DryGains[FRONT_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[FRONT_RIGHT] = DryGain * ListenerGain; + } + else + { + switch(Format) + { + case AL_FORMAT_MONO8: + case AL_FORMAT_MONO16: + case AL_FORMAT_MONO_FLOAT32: + case AL_FORMAT_STEREO8: + case AL_FORMAT_STEREO16: + case AL_FORMAT_STEREO_FLOAT32: + ALSource->Params.DryGains[FRONT_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[FRONT_RIGHT] = DryGain * ListenerGain; + break; + + case AL_FORMAT_QUAD8: + case AL_FORMAT_QUAD16: + case AL_FORMAT_QUAD32: + case AL_FORMAT_51CHN8: + case AL_FORMAT_51CHN16: + case AL_FORMAT_51CHN32: + DryGain *= aluSqrt(2.0f/4.0f); + ALSource->Params.DryGains[FRONT_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[FRONT_RIGHT] = DryGain * ListenerGain; + ALSource->Params.DryGains[BACK_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[BACK_RIGHT] = DryGain * ListenerGain; + break; + + case AL_FORMAT_61CHN8: + case AL_FORMAT_61CHN16: + case AL_FORMAT_61CHN32: + DryGain *= aluSqrt(2.0f/4.0f); + ALSource->Params.DryGains[FRONT_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[FRONT_RIGHT] = DryGain * ListenerGain; + ALSource->Params.DryGains[SIDE_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[SIDE_RIGHT] = DryGain * ListenerGain; + break; + + case AL_FORMAT_71CHN8: + case AL_FORMAT_71CHN16: + case AL_FORMAT_71CHN32: + DryGain *= aluSqrt(2.0f/6.0f); + ALSource->Params.DryGains[FRONT_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[FRONT_RIGHT] = DryGain * ListenerGain; + ALSource->Params.DryGains[BACK_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[BACK_RIGHT] = DryGain * ListenerGain; + ALSource->Params.DryGains[SIDE_LEFT] = DryGain * ListenerGain; + ALSource->Params.DryGains[SIDE_RIGHT] = DryGain * ListenerGain; + break; + + default: + break; + } + } + + 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. */ + cw = cos(2.0*M_PI * LOWPASSFREQCUTOFF / Frequency); + + /* We use two chained one-pole filters, so we need to take the + * square root of the squared gain, which is the same as the base + * gain. */ + ALSource->Params.iirFilter.coeff = lpCoeffCalc(DryGainHF, cw); + + for(i = 0;i < NumSends;i++) + { + /* We use a one-pole filter, so we need to take the squared gain */ + ALfloat a = lpCoeffCalc(WetGainHF[i]*WetGainHF[i], cw); + ALSource->Params.Send[i].iirFilter.coeff = a; + } +} + ALvoid CalcSourceParams(ALsource *ALSource, const ALCcontext *ALContext) { const ALCdevice *Device = ALContext->Device; diff --git a/Alc/mixer.c b/Alc/mixer.c index e880ad3a..3c1f266f 100644 --- a/Alc/mixer.c +++ b/Alc/mixer.c @@ -106,7 +106,6 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, FILTER *DryFilter, *WetFilter[MAX_SENDS]; ALfloat WetSend[MAX_SENDS]; ALuint rampLength; - ALboolean DuplicateStereo; ALuint DeviceFreq; ALint increment; ALuint DataPosInt, DataPosFrac; @@ -118,7 +117,6 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, ALfloat Pitch; ALenum State; - DuplicateStereo = ALContext->Device->DuplicateStereo; DeviceFreq = ALContext->Device->Frequency; rampLength = DeviceFreq * MIN_RAMP_LENGTH / 1000; @@ -321,7 +319,7 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, } #undef DO_MIX } - else if(Channels == 2 && DuplicateStereo) /* Stereo */ + else if(Channels == 2) /* Stereo */ { const int chans[] = { FRONT_LEFT, FRONT_RIGHT @@ -329,7 +327,6 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, const int chans2[] = { BACK_LEFT, SIDE_LEFT, BACK_RIGHT, SIDE_RIGHT }; - const ALfloat dupscaler = aluSqrt(1.0f/3.0f); #define DO_MIX(resampler) do { \ const ALfloat scaler = 1.0f/Channels; \ @@ -346,7 +343,7 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, Data[(DataPosInt+1)*Channels + i], \ DataPosFrac); \ \ - outsamp = lpFilter2P(DryFilter, chans[i]*2, value) * dupscaler; \ + outsamp = lpFilter2P(DryFilter, chans[i]*2, value); \ DryBuffer[j][chans[i]] += outsamp*DrySend[chans[i]]; \ DryBuffer[j][chans2[i*2+0]] += outsamp*DrySend[chans2[i*2+0]]; \ DryBuffer[j][chans2[i*2+1]] += outsamp*DrySend[chans2[i*2+1]]; \ @@ -379,10 +376,11 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, } #undef DO_MIX } - else if(Channels == 2) /* Stereo */ + else if(Channels == 4) /* Quad */ { const int chans[] = { - FRONT_LEFT, FRONT_RIGHT + FRONT_LEFT, FRONT_RIGHT, + BACK_LEFT, BACK_RIGHT }; #define DO_MIX(resampler) do { \ @@ -430,26 +428,6 @@ static void MixSource(ALsource *ALSource, ALCcontext *ALContext, break; } } - else if(Channels == 4) /* Quad */ - { - const int chans[] = { - FRONT_LEFT, FRONT_RIGHT, - BACK_LEFT, BACK_RIGHT - }; - - switch(Resampler) - { - case POINT_RESAMPLER: - DO_MIX(point); break; - case LINEAR_RESAMPLER: - DO_MIX(lerp); break; - case COSINE_RESAMPLER: - DO_MIX(cos_lerp); break; - case RESAMPLER_MIN: - case RESAMPLER_MAX: - break; - } - } else if(Channels == 6) /* 5.1 */ { const int chans[] = { diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h index bd28771f..73f70224 100644 --- a/OpenAL32/Include/alu.h +++ b/OpenAL32/Include/alu.h @@ -183,6 +183,7 @@ ALvoid aluInitPanning(ALCdevice *Device); ALvoid CalcSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext); ALvoid CalcNonAttnSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext); +ALvoid CalcNonAttnStereoSourceParams(struct ALsource *ALSource, const ALCcontext *ALContext); ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size); ALvoid aluHandleDisconnect(ALCdevice *device); diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c index 0db6f76b..5488003c 100644 --- a/OpenAL32/alSource.c +++ b/OpenAL32/alSource.c @@ -576,6 +576,8 @@ AL_API ALvoid AL_APIENTRY alSourcei(ALuint source,ALenum eParam,ALint lValue) if(aluChannelsFromFormat(buffer->format) == 1) Source->Update = CalcSourceParams; + else if(aluChannelsFromFormat(buffer->format) == 2) + Source->Update = CalcNonAttnStereoSourceParams; else Source->Update = CalcNonAttnSourceParams; @@ -1626,6 +1628,8 @@ AL_API ALvoid AL_APIENTRY alSourceQueueBuffers(ALuint source, ALsizei n, const A Format = buffer->eOriginalFormat; if(aluChannelsFromFormat(buffer->format) == 1) Source->Update = CalcSourceParams; + else if(aluChannelsFromFormat(buffer->format) == 2) + Source->Update = CalcNonAttnStereoSourceParams; else Source->Update = CalcNonAttnSourceParams; Source->NeedsUpdate = AL_TRUE; |