aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2016-01-28 00:02:46 -0800
committerChris Robinson <[email protected]>2016-01-28 00:02:46 -0800
commitc1f87414c5452f595f78b7a52a7063a023ce2982 (patch)
tree7a8b3007d1cf3ff7b05edc45c5ac7962c3dbbbaf
parent2fa3ae85c9a4050eab3a4f140fb6accd0a02ce85 (diff)
Mix to multichannel for effects
This mixes to a 4-channel first-order ambisonics buffer. With ACN ordering and N3D scaling, this makes it easy to remain compatible with effects that only care about mono input since channel 0 is an unattenuated mono signal.
-rw-r--r--Alc/ALc.c2
-rw-r--r--Alc/ALu.c290
-rw-r--r--Alc/mixer.c2
-rw-r--r--Alc/panning.c22
-rw-r--r--OpenAL32/Include/alAuxEffectSlot.h19
-rw-r--r--OpenAL32/Include/alu.h10
-rw-r--r--OpenAL32/alAuxEffectSlot.c2
7 files changed, 283 insertions, 64 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index d6d23eba..f69f6ecc 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -3496,6 +3496,8 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
DELETE_OBJ(state);
ERR("Failed to initialize the default effect\n");
}
+ else
+ aluInitEffectPanning(device->DefaultSlot);
}
{
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 2f1cdd85..70f686f3 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -365,14 +365,18 @@ static void UpdateDryStepping(DirectParams *params, ALuint num_chans, ALuint ste
static void UpdateWetStepping(SendParams *params, ALuint num_chans, ALuint steps)
{
ALfloat delta;
- ALuint i;
+ ALuint i, j;
if(steps < 2)
{
for(i = 0;i < num_chans;i++)
{
- params->Gains[i].Current = params->Gains[i].Target;
- params->Gains[i].Step = 0.0f;
+ MixGains *gains = params->Gains[i];
+ for(j = 0;j < params->OutChannels;j++)
+ {
+ gains[j].Current = gains[j].Target;
+ gains[j].Step = 0.0f;
+ }
}
params->Counter = 0;
return;
@@ -381,13 +385,17 @@ static void UpdateWetStepping(SendParams *params, ALuint num_chans, ALuint steps
delta = 1.0f / (ALfloat)steps;
for(i = 0;i < num_chans;i++)
{
- ALfloat diff = params->Gains[i].Target - params->Gains[i].Current;
- if(fabsf(diff) >= GAIN_SILENCE_THRESHOLD)
- params->Gains[i].Step = diff * delta;
- else
+ MixGains *gains = params->Gains[i];
+ for(j = 0;j < params->OutChannels;j++)
{
- params->Gains[i].Current = params->Gains[i].Target;
- params->Gains[i].Step = 0.0f;
+ ALfloat diff = gains[j].Target - gains[j].Current;
+ if(fabsf(diff) >= GAIN_SILENCE_THRESHOLD)
+ gains[j].Step = diff * delta;
+ else
+ {
+ gains[j].Current = gains[j].Target;
+ gains[j].Step = 0.0f;
+ }
}
}
params->Counter = steps;
@@ -479,6 +487,7 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
ALfloat WetGain[MAX_SENDS];
ALfloat WetGainHF[MAX_SENDS];
ALfloat WetGainLF[MAX_SENDS];
+ ALeffectslot *SendSlots[MAX_SENDS];
ALuint NumSends, Frequency;
ALboolean Relative;
const struct ChanMap *chans = NULL;
@@ -507,13 +516,20 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
voice->Direct.OutChannels = Device->NumChannels;
for(i = 0;i < NumSends;i++)
{
- ALeffectslot *Slot = ALSource->Send[i].Slot;
- if(!Slot && i == 0)
- Slot = Device->DefaultSlot;
- if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
+ SendSlots[i] = ALSource->Send[i].Slot;
+ if(!SendSlots[i] && i == 0)
+ SendSlots[i] = Device->DefaultSlot;
+ if(!SendSlots[i] || SendSlots[i]->EffectType == AL_EFFECT_NULL)
+ {
+ SendSlots[i] = NULL;
voice->Send[i].OutBuffer = NULL;
+ voice->Send[i].OutChannels = 0;
+ }
else
- voice->Send[i].OutBuffer = Slot->WetBuffer;
+ {
+ voice->Send[i].OutBuffer = SendSlots[i]->WetBuffer;
+ voice->Send[i].OutChannels = SendSlots[i]->NumChannels;
+ }
}
/* Calculate the stepping value */
@@ -653,20 +669,37 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
UpdateDryStepping(&voice->Direct, num_channels, (voice->Direct.Moving ? 64 : 0));
voice->Direct.Moving = AL_TRUE;
- voice->IsHrtf = AL_FALSE;
-
for(i = 0;i < NumSends;i++)
{
- /* Only the first channel of B-Format buffers (W) goes to auxiliary
- * sends. It also needs to be scaled by sqrt(2) to account for the
- * signal being scaled by sqrt(1/2).
- */
- voice->Send[i].Gains[0].Target = WetGain[i] * 1.414213562f;
- for(c = 1;c < num_channels;c++)
- voice->Send[i].Gains[c].Target = 0.0f;
+ if(!SendSlots[i])
+ {
+ for(c = 0;c < num_channels;c++)
+ {
+ MixGains *gains = voice->Send[i].Gains[c];
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = 0.0f;
+ }
+ }
+ else
+ {
+ for(c = 0;c < num_channels;c++)
+ {
+ const ALeffectslot *Slot = SendSlots[i];
+ MixGains *gains = voice->Send[i].Gains[c];
+ ALfloat Target[MAX_OUTPUT_CHANNELS];
+ ALuint j;
+
+ ComputeBFormatGains(Slot->AmbiCoeffs, Slot->NumChannels,
+ matrix.m[c], WetGain[i], Target);
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = Target[j];
+ }
+ }
UpdateWetStepping(&voice->Send[i], num_channels, (voice->Send[i].Moving ? 64 : 0));
voice->Send[i].Moving = AL_TRUE;
}
+
+ voice->IsHrtf = AL_FALSE;
}
else
{
@@ -683,7 +716,6 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
for(c = 0;c < num_channels;c++)
{
MixGains *gains = voice->Direct.Gains[c];
-
for(j = 0;j < MAX_OUTPUT_CHANNELS;j++)
gains[j].Target = 0.0f;
@@ -703,8 +735,44 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
if((idx=GetChannelIdxByName(Device, chans[c].channel)) != -1)
gains[idx].Target = DryGain;
}
+
+ /* Auxiliary sends still use normal panning since they mix to B-Format, which can't
+ * channel-match. */
+ for(c = 0;c < num_channels;c++)
+ {
+ ALfloat coeffs[MAX_AMBI_COEFFS];
+
+ CalcAngleCoeffs(chans[c].angle, chans[c].elevation, coeffs);
+
+ for(i = 0;i < NumSends;i++)
+ {
+ MixGains *gains = voice->Send[i].Gains[c];
+ if(!SendSlots[i])
+ {
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = 0.0f;
+ }
+ else
+ {
+ const ALeffectslot *Slot = SendSlots[i];
+ ALfloat Target[MAX_OUTPUT_CHANNELS];
+ ALuint j;
+
+ ComputePanningGains(Slot->AmbiCoeffs, Slot->NumChannels,
+ coeffs, WetGain[i], Target);
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = Target[j];
+ }
+ }
+ }
+
UpdateDryStepping(&voice->Direct, num_channels, (voice->Direct.Moving ? 64 : 0));
voice->Direct.Moving = AL_TRUE;
+ for(i = 0;i < NumSends;i++)
+ {
+ UpdateWetStepping(&voice->Send[i], num_channels, (voice->Send[i].Moving ? 64 : 0));
+ voice->Send[i].Moving = AL_TRUE;
+ }
voice->IsHrtf = AL_FALSE;
}
@@ -742,6 +810,40 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
voice->Direct.Counter = 0;
voice->Direct.Moving = AL_TRUE;
+ /* Normal panning for auxiliary sends. */
+ for(c = 0;c < num_channels;c++)
+ {
+ ALfloat coeffs[MAX_AMBI_COEFFS];
+
+ CalcAngleCoeffs(chans[c].angle, chans[c].elevation, coeffs);
+
+ for(i = 0;i < NumSends;i++)
+ {
+ MixGains *gains = voice->Send[i].Gains[c];
+ if(!SendSlots[i])
+ {
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = 0.0f;
+ }
+ else
+ {
+ const ALeffectslot *Slot = SendSlots[i];
+ ALfloat Target[MAX_OUTPUT_CHANNELS];
+ ALuint j;
+
+ ComputePanningGains(Slot->AmbiCoeffs, Slot->NumChannels,
+ coeffs, WetGain[i], Target);
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = Target[j];
+ }
+ }
+ }
+ for(i = 0;i < NumSends;i++)
+ {
+ UpdateWetStepping(&voice->Send[i], num_channels, (voice->Send[i].Moving ? 64 : 0));
+ voice->Send[i].Moving = AL_TRUE;
+ }
+
voice->IsHrtf = AL_TRUE;
}
else
@@ -769,19 +871,38 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
ComputePanningGains(Device->AmbiCoeffs, Device->NumChannels, coeffs, DryGain, Target);
for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
gains[i].Target = Target[i];
+
+ for(i = 0;i < NumSends;i++)
+ {
+ MixGains *gains = voice->Send[i].Gains[c];
+ ALuint j;
+
+ if(!SendSlots[i])
+ {
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = 0.0f;
+ }
+ else
+ {
+ const ALeffectslot *Slot = SendSlots[i];
+ ComputePanningGains(Slot->AmbiCoeffs, Slot->NumChannels,
+ coeffs, WetGain[i], Target);
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = Target[j];
+ }
+ }
}
+
UpdateDryStepping(&voice->Direct, num_channels, (voice->Direct.Moving ? 64 : 0));
voice->Direct.Moving = AL_TRUE;
+ for(i = 0;i < NumSends;i++)
+ {
+ UpdateWetStepping(&voice->Send[i], num_channels, (voice->Send[i].Moving ? 64 : 0));
+ voice->Send[i].Moving = AL_TRUE;
+ }
voice->IsHrtf = AL_FALSE;
}
- for(i = 0;i < NumSends;i++)
- {
- for(c = 0;c < num_channels;c++)
- voice->Send[i].Gains[c].Target = WetGain[i];
- UpdateWetStepping(&voice->Send[i], num_channels, (voice->Send[i].Moving ? 64 : 0));
- voice->Send[i].Moving = AL_TRUE;
- }
}
{
@@ -838,6 +959,7 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
ALfloat AirAbsorptionFactor;
ALfloat RoomAirAbsorption[MAX_SENDS];
ALbufferlistitem *BufferListItem;
+ ALeffectslot *SendSlots[MAX_SENDS];
ALfloat Attenuation;
ALfloat RoomAttenuation[MAX_SENDS];
ALfloat MetersPerUnit;
@@ -899,26 +1021,26 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
voice->Direct.OutChannels = Device->NumChannels;
for(i = 0;i < NumSends;i++)
{
- ALeffectslot *Slot = ALSource->Send[i].Slot;
+ SendSlots[i] = ALSource->Send[i].Slot;
- if(!Slot && i == 0)
- Slot = Device->DefaultSlot;
- if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
+ if(!SendSlots[i] && i == 0)
+ SendSlots[i] = Device->DefaultSlot;
+ if(!SendSlots[i] || SendSlots[i]->EffectType == AL_EFFECT_NULL)
{
- Slot = NULL;
+ SendSlots[i] = NULL;
RoomRolloff[i] = 0.0f;
DecayDistance[i] = 0.0f;
RoomAirAbsorption[i] = 1.0f;
}
- else if(Slot->AuxSendAuto)
+ else if(SendSlots[i]->AuxSendAuto)
{
RoomRolloff[i] = RoomRolloffBase;
- if(IsReverbEffect(Slot->EffectType))
+ if(IsReverbEffect(SendSlots[i]->EffectType))
{
- RoomRolloff[i] += Slot->EffectProps.Reverb.RoomRolloffFactor;
- DecayDistance[i] = Slot->EffectProps.Reverb.DecayTime *
+ RoomRolloff[i] += SendSlots[i]->EffectProps.Reverb.RoomRolloffFactor;
+ DecayDistance[i] = SendSlots[i]->EffectProps.Reverb.DecayTime *
SPEEDOFSOUNDMETRESPERSEC;
- RoomAirAbsorption[i] = Slot->EffectProps.Reverb.AirAbsorptionGainHF;
+ RoomAirAbsorption[i] = SendSlots[i]->EffectProps.Reverb.AirAbsorptionGainHF;
}
else
{
@@ -935,10 +1057,16 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
RoomAirAbsorption[i] = AIRABSORBGAINHF;
}
- if(!Slot || Slot->EffectType == AL_EFFECT_NULL)
+ if(!SendSlots[i])
+ {
voice->Send[i].OutBuffer = NULL;
+ voice->Send[i].OutChannels = 0;
+ }
else
- voice->Send[i].OutBuffer = Slot->WetBuffer;
+ {
+ voice->Send[i].OutBuffer = SendSlots[i]->WetBuffer;
+ voice->Send[i].OutChannels = SendSlots[i]->NumChannels;
+ }
}
/* Transform source to listener space (convert to head relative) */
@@ -1159,6 +1287,8 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
ALfloat ev = 0.0f, az = 0.0f;
ALfloat radius = ALSource->Radius;
ALfloat dirfact = 1.0f;
+ ALfloat Target[MAX_OUTPUT_CHANNELS];
+ ALfloat coeffs[MAX_AMBI_COEFFS];
voice->Direct.OutBuffer += voice->Direct.OutChannels;
voice->Direct.OutChannels = 2;
@@ -1217,6 +1347,34 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
voice->Direct.LastDir = dir;
}
+ dir.v[0] *= dirfact;
+ dir.v[1] *= dirfact;
+ dir.v[2] *= dirfact;
+ CalcDirectionCoeffs(dir.v, coeffs);
+
+ for(i = 0;i < NumSends;i++)
+ {
+ MixGains *gains = voice->Send[i].Gains[0];
+ ALuint j;
+
+ if(!SendSlots[i])
+ {
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = 0.0f;
+ }
+ else
+ {
+ const ALeffectslot *Slot = SendSlots[i];
+ ComputePanningGains(Slot->AmbiCoeffs, Slot->NumChannels,
+ coeffs, WetGain[i], Target);
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = Target[j];
+ }
+
+ UpdateWetStepping(&voice->Send[i], 1, (voice->Send[i].Moving ? 64 : 0));
+ voice->Send[i].Moving = AL_TRUE;
+ }
+
voice->IsHrtf = AL_TRUE;
}
else
@@ -1255,14 +1413,31 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
UpdateDryStepping(&voice->Direct, 1, (voice->Direct.Moving ? 64 : 0));
voice->Direct.Moving = AL_TRUE;
+ for(i = 0;i < NumSends;i++)
+ {
+ MixGains *gains = voice->Send[i].Gains[0];
+ ALuint j;
+
+ if(!SendSlots[i])
+ {
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = 0.0f;
+ }
+ else
+ {
+ const ALeffectslot *Slot = SendSlots[i];
+ ComputePanningGains(Slot->AmbiCoeffs, Slot->NumChannels,
+ coeffs, WetGain[i], Target);
+ for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
+ gains[j].Target = Target[j];
+ }
+
+ UpdateWetStepping(&voice->Send[i], 1, (voice->Send[i].Moving ? 64 : 0));
+ voice->Send[i].Moving = AL_TRUE;
+ }
+
voice->IsHrtf = AL_FALSE;
}
- for(i = 0;i < NumSends;i++)
- {
- voice->Send[i].Gains[0].Target = WetGain[i];
- UpdateWetStepping(&voice->Send[i], 1, (voice->Send[i].Moving ? 64 : 0));
- voice->Send[i].Moving = AL_TRUE;
- }
{
ALfloat hfscale = ALSource->Direct.HFReference / Frequency;
@@ -1438,7 +1613,8 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
{
if(ATOMIC_EXCHANGE(ALenum, &slot->NeedsUpdate, AL_FALSE))
V(slot->EffectState,update)(device, slot);
- memset(slot->WetBuffer[0], 0, SamplesToDo*sizeof(ALfloat));
+ for(i = 0;i < slot->NumChannels;i++)
+ memset(slot->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat));
}
ctx = ATOMIC_LOAD(&device->ContextList);
@@ -1447,17 +1623,21 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
if(!ctx->DeferUpdates)
{
UpdateContextSources(ctx);
-#define UPDATE_SLOT(iter) do { \
- if(ATOMIC_EXCHANGE(ALenum, &(*iter)->NeedsUpdate, AL_FALSE)) \
- V((*iter)->EffectState,update)(device, *iter); \
- memset((*iter)->WetBuffer[0], 0, SamplesToDo*sizeof(ALfloat)); \
+#define UPDATE_SLOT(iter) do { \
+ if(ATOMIC_EXCHANGE(ALenum, &(*iter)->NeedsUpdate, AL_FALSE)) \
+ V((*iter)->EffectState,update)(device, *iter); \
+ for(i = 0;i < (*iter)->NumChannels;i++) \
+ memset((*iter)->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); \
} while(0)
VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, UPDATE_SLOT);
#undef UPDATE_SLOT
}
else
{
-#define CLEAR_WET_BUFFER(iter) memset((*iter)->WetBuffer[0], 0, SamplesToDo*sizeof(ALfloat))
+#define CLEAR_WET_BUFFER(iter) do { \
+ for(i = 0;i < (*iter)->NumChannels;i++) \
+ memset((*iter)->WetBuffer[i], 0, SamplesToDo*sizeof(ALfloat)); \
+} while(0)
VECTOR_FOR_EACH(ALeffectslot*, ctx->ActiveAuxSlots, CLEAR_WET_BUFFER);
#undef CLEAR_WET_BUFFER
}
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 712075f1..ddcf6f6b 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -570,7 +570,7 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam
Device->FilteredData, ResampledData, DstBufferSize,
parms->Filters[chan].ActiveType
);
- MixSamples(samples, 1, parms->OutBuffer, &parms->Gains[chan],
+ MixSamples(samples, parms->OutChannels, parms->OutBuffer, parms->Gains[chan],
parms->Counter, OutPos, DstBufferSize);
}
}
diff --git a/Alc/panning.c b/Alc/panning.c
index dccb495e..c4eb3f82 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -27,8 +27,7 @@
#include <assert.h>
#include "alMain.h"
-#include "AL/al.h"
-#include "AL/alc.h"
+#include "alAuxEffectSlot.h"
#include "alu.h"
#include "bool.h"
@@ -569,3 +568,22 @@ ALvoid aluInitPanning(ALCdevice *device)
&device->NumChannels, AL_TRUE);
device->AmbiScale = ambiscale;
}
+
+void aluInitEffectPanning(ALeffectslot *slot)
+{
+ static const ChannelMap FirstOrderN3D[4] = {
+ { BFormatW, { 1.0f, 0.0f, 0.0f, 0.0f } },
+ { BFormatY, { 0.0f, 1.0f, 0.0f, 0.0f } },
+ { BFormatZ, { 0.0f, 0.0f, 1.0f, 0.0f } },
+ { BFormatX, { 0.0f, 0.0f, 0.0f, 1.0f } },
+ };
+ static const enum Channel AmbiChannels[MAX_OUTPUT_CHANNELS] = {
+ BFormatW, BFormatY, BFormatZ, BFormatX, InvalidChannel
+ };
+
+ memset(slot->AmbiCoeffs, 0, sizeof(slot->AmbiCoeffs));
+ slot->NumChannels = 0;
+
+ SetChannelMap(AmbiChannels, slot->AmbiCoeffs, FirstOrderN3D, COUNTOF(FirstOrderN3D),
+ &slot->NumChannels, AL_FALSE);
+}
diff --git a/OpenAL32/Include/alAuxEffectSlot.h b/OpenAL32/Include/alAuxEffectSlot.h
index bbb112be..3f677fd1 100644
--- a/OpenAL32/Include/alAuxEffectSlot.h
+++ b/OpenAL32/Include/alAuxEffectSlot.h
@@ -64,6 +64,9 @@ static const struct ALeffectStateFactoryVtable T##_ALeffectStateFactory_vtable =
}
+#define MAX_EFFECT_CHANNELS (4)
+
+
typedef struct ALeffectslot {
ALenum EffectType;
ALeffectProps EffectProps;
@@ -74,12 +77,24 @@ typedef struct ALeffectslot {
ATOMIC(ALenum) NeedsUpdate;
ALeffectState *EffectState;
- alignas(16) ALfloat WetBuffer[1][BUFFERSIZE];
-
RefCount ref;
/* Self ID */
ALuint id;
+
+ ALuint NumChannels;
+ ChannelConfig AmbiCoeffs[MAX_EFFECT_CHANNELS];
+ /* Wet buffer configuration is ACN channel order with N3D scaling:
+ * * Channel 0 is the unattenuated mono signal.
+ * * Channel 1 is OpenAL -X
+ * * Channel 2 is OpenAL Y
+ * * Channel 3 is OpenAL -Z
+ * Consequently, effects that only want to work with mono input can use
+ * channel 0 by itself. Effects that want multichannel can process the
+ * ambisonics signal and create a B-Format pan (ComputeBFormatGains) for
+ * the device output.
+ */
+ alignas(16) ALfloat WetBuffer[MAX_EFFECT_CHANNELS][BUFFERSIZE];
} ALeffectslot;
inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id)
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 5f5493c5..63a03adc 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -13,6 +13,7 @@
#include "alMain.h"
#include "alBuffer.h"
#include "alFilter.h"
+#include "alAuxEffectSlot.h"
#include "hrtf.h"
#include "align.h"
@@ -34,6 +35,7 @@ extern "C" {
struct ALsource;
struct ALvoice;
+struct ALeffectslot;
/* The number of distinct scale and phase intervals within the filter table. */
@@ -164,6 +166,7 @@ typedef struct DirectParams {
typedef struct SendParams {
ALfloat (*OutBuffer)[BUFFERSIZE];
+ ALuint OutChannels;
ALboolean Moving;
ALuint Counter;
@@ -173,10 +176,7 @@ typedef struct SendParams {
ALfilterState LowPass;
ALfilterState HighPass;
} Filters[MAX_INPUT_CHANNELS];
-
- /* Gain control, which applies to each input channel to a single (mono)
- * output buffer. */
- MixGains Gains[MAX_INPUT_CHANNELS];
+ MixGains Gains[MAX_INPUT_CHANNELS][MAX_EFFECT_CHANNELS];
} SendParams;
@@ -276,6 +276,8 @@ void aluInitMixer(void);
ALvoid aluInitPanning(ALCdevice *Device);
+void aluInitEffectPanning(struct ALeffectslot *slot);
+
/**
* CalcDirectionCoeffs
*
diff --git a/OpenAL32/alAuxEffectSlot.c b/OpenAL32/alAuxEffectSlot.c
index c1314301..b0dba25d 100644
--- a/OpenAL32/alAuxEffectSlot.c
+++ b/OpenAL32/alAuxEffectSlot.c
@@ -90,6 +90,8 @@ AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslo
SET_ERROR_AND_GOTO(context, err, done);
}
+ aluInitEffectPanning(slot);
+
VECTOR_PUSH_BACK(slotvec, slot);
effectslots[cur] = slot->id;