aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALu.c144
-rw-r--r--Alc/mixer.c32
-rw-r--r--OpenAL32/Include/alu.h1
-rw-r--r--OpenAL32/alSource.c4
4 files changed, 154 insertions, 27 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index cc3f95cf..9797908c 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -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;