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 /Alc | |
parent | 2aacca76de7577db8632b796ce8e205207b23d68 (diff) |
Combine stereo and stereo-duplicate mixers
Use a separate update method for stereo sources to the set appropriate channel
gains
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALu.c | 144 | ||||
-rw-r--r-- | Alc/mixer.c | 32 |
2 files changed, 149 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[] = { |