aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2017-03-10 04:35:32 -0800
committerChris Robinson <[email protected]>2017-03-10 04:35:32 -0800
commit583d431947be540a33843d68feb5f1456671c298 (patch)
tree0f85220f58dd446d9732cb3a70bf7917585619c8 /Alc
parentd9b1995e95ac3d838566500f1e5496ae71d832e0 (diff)
Implement NFC filters for Ambisonic rendering
NFC filters currently only work when rendering to ambisonic buffers, which includes HQ rendering and ambisonic output. There are two new config options: 'decoder/nfc' (default on) enables or disables use of NFC filters globally, and 'decoder/nfc-ref-delay' (default 0) specifies the reference delay parameter for NFC-HOA rendering with ambisonic output (a value of 0 disables NFC). Currently, NFC filters rely on having an appropriate value set for AL_METERS_PER_UNIT to get the correct scaling. HQ rendering uses the averaged speaker distances as a control/reference, and currently doesn't correct for individual speaker distances (if the speakers are all equidistant, this is fine, otherwise per-speaker correction should be done as well).
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALc.c20
-rw-r--r--Alc/ALu.c64
-rw-r--r--Alc/mixer.c55
-rw-r--r--Alc/panning.c172
4 files changed, 235 insertions, 76 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 882a8cb0..beec0c32 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -2310,6 +2310,24 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
}
}
AllocateVoices(context, context->MaxVoices, old_sends);
+ for(pos = 0;pos < context->VoiceCount;pos++)
+ {
+ ALvoice *voice = context->Voices[pos];
+ if(!voice->Source) continue;
+
+ if(device->AvgSpeakerDist > 0.0f)
+ {
+ /* Reinitialize the NFC filters for new parameters. */
+ ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
+ (device->AvgSpeakerDist * device->Frequency);
+ for(i = 0;i < voice->NumChannels;i++)
+ {
+ NfcFilterCreate1(&voice->Direct.Params[i].NFCtrlFilter[0], 0.0f, w1);
+ NfcFilterCreate2(&voice->Direct.Params[i].NFCtrlFilter[1], 0.0f, w1);
+ NfcFilterCreate3(&voice->Direct.Params[i].NFCtrlFilter[2], 0.0f, w1);
+ }
+ }
+ }
UnlockUIntMapRead(&context->SourceMap);
UpdateListenerProps(context);
@@ -3755,6 +3773,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName)
device->FOAOut.NumChannels = 0;
device->RealOut.Buffer = NULL;
device->RealOut.NumChannels = 0;
+ device->AvgSpeakerDist = 0.0f;
ATOMIC_INIT(&device->ContextList, NULL);
@@ -4271,6 +4290,7 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN
device->FOAOut.NumChannels = 0;
device->RealOut.Buffer = NULL;
device->RealOut.NumChannels = 0;
+ device->AvgSpeakerDist = 0.0f;
ATOMIC_INIT(&device->ContextList, NULL);
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 04b9c89d..90ca8ab1 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -496,6 +496,7 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
break;
}
+ voice->Flags &= ~(VOICE_IS_HRTF | VOICE_HAS_NFC);
if(isbformat)
{
ALfloat N[3], V[3], U[3];
@@ -535,6 +536,17 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
for(c = 0;c < num_channels;c++)
ComputeFirstOrderGains(Device->FOAOut, matrix.m[c], DryGain,
voice->Direct.Params[c].Gains.Target);
+ if(Device->AvgSpeakerDist > 0.0f)
+ {
+ /* NOTE: The NFCtrlFilters were created with a w0 of 0, which is
+ * what we want for FOA input. So there's nothing to adjust.
+ */
+ voice->Direct.ChannelsPerOrder[0] = 1;
+ voice->Direct.ChannelsPerOrder[1] = mini(voice->Direct.Channels-1, 3);
+ voice->Direct.ChannelsPerOrder[2] = 0;
+ voice->Direct.ChannelsPerOrder[3] = 0;
+ voice->Flags |= VOICE_HAS_NFC;
+ }
for(i = 0;i < NumSends;i++)
{
@@ -553,8 +565,6 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
}
}
-
- voice->IsHrtf = AL_FALSE;
}
else
{
@@ -592,8 +602,6 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
}
}
-
- voice->IsHrtf = AL_FALSE;
}
else if(Device->Render_Mode == HrtfRender)
{
@@ -647,7 +655,7 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
}
}
- voice->IsHrtf = AL_TRUE;
+ voice->Flags |= VOICE_IS_HRTF;
}
else
{
@@ -694,8 +702,6 @@ static void CalcNonAttnSourceParams(ALvoice *voice, const struct ALsourceProps *
voice->Send[i].Params[c].Gains.Target[j] = 0.0f;
}
}
-
- voice->IsHrtf = AL_FALSE;
}
}
@@ -1064,6 +1070,7 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
voice->Step = maxi(fastf2i(Pitch*FRACTIONONE + 0.5f), 1);
BsincPrepare(voice->Step, &voice->ResampleState.bsinc);
+ voice->Flags &= ~(VOICE_IS_HRTF | VOICE_HAS_NFC);
if(Device->Render_Mode == HrtfRender)
{
/* Full HRTF rendering. Skip the virtual channels and render to the
@@ -1115,7 +1122,7 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
voice->Send[i].Params[0].Gains.Target[j] = 0.0f;
}
- voice->IsHrtf = AL_TRUE;
+ voice->Flags |= VOICE_IS_HRTF;
}
else
{
@@ -1128,10 +1135,49 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
/* Get the localized direction, and compute panned gains. */
if(Distance > FLT_EPSILON)
{
+ if(Device->AvgSpeakerDist > 0.0f && MetersPerUnit > 0.0f)
+ {
+ ALfloat w0 = SPEEDOFSOUNDMETRESPERSEC /
+ (Distance*MetersPerUnit * (ALfloat)Device->Frequency);
+ ALfloat w1 = SPEEDOFSOUNDMETRESPERSEC /
+ (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
+ /* Clamp w0 for really close distances, to prevent excessive
+ * bass.
+ */
+ w0 = minf(w0, w1*4.0f);
+
+ NfcFilterAdjust1(&voice->Direct.Params[0].NFCtrlFilter[0], w0);
+ NfcFilterAdjust2(&voice->Direct.Params[0].NFCtrlFilter[1], w0);
+ NfcFilterAdjust3(&voice->Direct.Params[0].NFCtrlFilter[2], w0);
+
+ for(i = 0;i < MAX_AMBI_ORDER+1;i++)
+ voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
+ voice->Flags |= VOICE_HAS_NFC;
+ }
+
dir[0] = -SourceToListener.v[0];
dir[1] = -SourceToListener.v[1];
dir[2] = -SourceToListener.v[2] * ZScale;
}
+ else if(Device->AvgSpeakerDist > 0.0f)
+ {
+ /* If the source distance is 0, set w0 to w1 to act as a pass-
+ * through. We still want to pass the signal through the filters so
+ * they keep an appropriate history, in case the source moves away
+ * from the listener.
+ */
+ ALfloat w0 = SPEEDOFSOUNDMETRESPERSEC /
+ (Device->AvgSpeakerDist * (ALfloat)Device->Frequency);
+
+ NfcFilterAdjust1(&voice->Direct.Params[0].NFCtrlFilter[0], w0);
+ NfcFilterAdjust2(&voice->Direct.Params[0].NFCtrlFilter[1], w0);
+ NfcFilterAdjust3(&voice->Direct.Params[0].NFCtrlFilter[2], w0);
+
+ for(i = 0;i < MAX_AMBI_ORDER+1;i++)
+ voice->Direct.ChannelsPerOrder[i] = Device->Dry.NumChannelsPerOrder[i];
+ voice->Flags |= VOICE_HAS_NFC;
+ }
+
if(radius > Distance)
spread = F_TAU - Distance/radius*F_PI;
else if(Distance > FLT_EPSILON)
@@ -1160,8 +1206,6 @@ static void CalcAttnSourceParams(ALvoice *voice, const struct ALsourceProps *pro
for(j = 0;j < MAX_EFFECT_CHANNELS;j++)
voice->Send[i].Params[0].Gains.Target[j] = 0.0f;
}
-
- voice->IsHrtf = AL_FALSE;
}
{
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 1c503a92..961c8f31 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -545,15 +545,60 @@ ALboolean MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALsizei
&parms->LowPass, &parms->HighPass, Device->FilteredData,
ResampledData, DstBufferSize, parms->FilterType
);
- if(!voice->IsHrtf)
+ if(!(voice->Flags&VOICE_IS_HRTF))
{
if(!Counter)
memcpy(parms->Gains.Current, parms->Gains.Target,
sizeof(parms->Gains.Current));
- MixSamples(samples, voice->Direct.Channels, voice->Direct.Buffer,
- parms->Gains.Current, parms->Gains.Target, Counter, OutPos,
- DstBufferSize
- );
+ if(!(voice->Flags&VOICE_HAS_NFC))
+ MixSamples(samples, voice->Direct.Channels, voice->Direct.Buffer,
+ parms->Gains.Current, parms->Gains.Target, Counter, OutPos,
+ DstBufferSize
+ );
+ else
+ {
+ ALfloat *nfcsamples = Device->NFCtrlData;
+ ALsizei chanoffset = 0;
+ MixSamples(samples,
+ voice->Direct.ChannelsPerOrder[0], voice->Direct.Buffer,
+ parms->Gains.Current, parms->Gains.Target, Counter, OutPos,
+ DstBufferSize
+ );
+ chanoffset += voice->Direct.ChannelsPerOrder[0];
+ if(voice->Direct.ChannelsPerOrder[1] > 0)
+ {
+ NfcFilterUpdate1(&parms->NFCtrlFilter[0], nfcsamples, samples,
+ DstBufferSize);
+ MixSamples(nfcsamples,
+ voice->Direct.ChannelsPerOrder[1], voice->Direct.Buffer+chanoffset,
+ parms->Gains.Current+chanoffset, parms->Gains.Target+chanoffset,
+ Counter, OutPos, DstBufferSize
+ );
+ chanoffset += voice->Direct.ChannelsPerOrder[1];
+ }
+ if(voice->Direct.ChannelsPerOrder[2] > 0)
+ {
+ NfcFilterUpdate2(&parms->NFCtrlFilter[1], nfcsamples, samples,
+ DstBufferSize);
+ MixSamples(nfcsamples,
+ voice->Direct.ChannelsPerOrder[2], voice->Direct.Buffer+chanoffset,
+ parms->Gains.Current+chanoffset, parms->Gains.Target+chanoffset,
+ Counter, OutPos, DstBufferSize
+ );
+ chanoffset += voice->Direct.ChannelsPerOrder[2];
+ }
+ if(voice->Direct.ChannelsPerOrder[3] > 0)
+ {
+ NfcFilterUpdate3(&parms->NFCtrlFilter[2], nfcsamples, samples,
+ DstBufferSize);
+ MixSamples(nfcsamples,
+ voice->Direct.ChannelsPerOrder[3], voice->Direct.Buffer+chanoffset,
+ parms->Gains.Current+chanoffset, parms->Gains.Target+chanoffset,
+ Counter, OutPos, DstBufferSize
+ );
+ chanoffset += voice->Direct.ChannelsPerOrder[3];
+ }
+ }
}
else
{
diff --git a/Alc/panning.c b/Alc/panning.c
index c4d3e43f..6315328a 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -487,6 +487,88 @@ static const ChannelMap MonoCfg[1] = {
{ BackRight, { 2.04124145e-1f, -1.08880247e-1f, 0.0f, -1.88586120e-1f, 1.29099444e-1f, 0.0f, 0.0f, 0.0f, 7.45355993e-2f, -3.73460789e-2f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.00000000e+0f } },
};
+static void InitNearFieldCtrl(ALCdevice *device, ALfloat ctrl_dist, ALsizei order, bool periphonic)
+{
+ const char *devname = al_string_get_cstr(device->DeviceName);
+ ALsizei i;
+
+ if(GetConfigValueBool(devname, "decoder", "nfc", 1) && ctrl_dist > 0.0f)
+ {
+ /* NFC is only used when AvgSpeakerDist is greater than 0, and
+ * METERS_PER_UNIT is also greater than 0. In addition, NFC can only be
+ * used when rendering to an ambisonic buffer.
+ */
+ device->AvgSpeakerDist = ctrl_dist;
+
+ device->Dry.NumChannelsPerOrder[0] = 1;
+ if(periphonic)
+ for(i = 1;i < order+1;i++)
+ device->Dry.NumChannelsPerOrder[i] = (i+1)*(i+1) - i*i;
+ else
+ for(i = 1;i < order+1;i++)
+ device->Dry.NumChannelsPerOrder[i] = (i*2+1) - ((i-1)*2+1);
+ for(;i < MAX_AMBI_ORDER+1;i++)
+ device->Dry.NumChannelsPerOrder[i] = 0;
+ }
+}
+
+static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
+{
+ const char *devname = al_string_get_cstr(device->DeviceName);
+ ALfloat maxdist = 0.0f;
+ ALsizei total = 0;
+ ALsizei i;
+
+ for(i = 0;i < conf->NumSpeakers;i++)
+ maxdist = maxf(maxdist, conf->Speakers[i].Distance);
+
+ if(GetConfigValueBool(devname, "decoder", "distance-comp", 1) && maxdist > 0.0f)
+ {
+ ALfloat srate = (ALfloat)device->Frequency;
+ for(i = 0;i < conf->NumSpeakers;i++)
+ {
+ ALsizei chan = speakermap[i];
+ ALfloat delay;
+
+ /* Distance compensation only delays in steps of the sample rate.
+ * This is a bit less accurate since the delay time falls to the
+ * nearest sample time, but it's far simpler as it doesn't have to
+ * deal with phase offsets. This means at 48khz, for instance, the
+ * distance delay will be in steps of about 7 millimeters.
+ */
+ delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
+ srate + 0.5f);
+ if(delay >= (ALfloat)MAX_DELAY_LENGTH)
+ ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
+ al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
+
+ device->ChannelDelay[chan].Length = (ALsizei)clampf(
+ delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)
+ );
+ device->ChannelDelay[chan].Gain = conf->Speakers[i].Distance / maxdist;
+ TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan,
+ al_string_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length,
+ device->ChannelDelay[chan].Gain
+ );
+
+ /* Round up to the next 4th sample, so each channel buffer starts
+ * 16-byte aligned.
+ */
+ total += RoundUp(device->ChannelDelay[chan].Length, 4);
+ }
+ }
+
+ if(total > 0)
+ {
+ device->ChannelDelay[0].Buffer = al_calloc(16, total * sizeof(ALfloat));
+ for(i = 1;i < MAX_OUTPUT_CHANNELS;i++)
+ {
+ size_t len = RoundUp(device->ChannelDelay[i-1].Length, 4);
+ device->ChannelDelay[i].Buffer = device->ChannelDelay[i-1].Buffer + len;
+ }
+ }
+}
+
static void InitPanning(ALCdevice *device)
{
const ChannelMap *chanmap = NULL;
@@ -546,10 +628,12 @@ static void InitPanning(ALCdevice *device)
if(device->FmtChans >= DevFmtAmbi1 && device->FmtChans <= DevFmtAmbi3)
{
+ const char *devname = al_string_get_cstr(device->DeviceName);
const ALsizei *acnmap = (device->AmbiLayout == AmbiLayout_FuMa) ? FuMa2ACN : ACN2ACN;
const ALfloat *n3dscale = (device->AmbiScale == AmbiNorm_FuMa) ? FuMa2N3DScale :
(device->AmbiScale == AmbiNorm_SN3D) ? SN3D2N3DScale :
/*(device->AmbiScale == AmbiNorm_N3D) ?*/ UnitScale;
+ ALfloat nfc_delay = 0.0f;
count = (device->FmtChans == DevFmtAmbi3) ? 16 :
(device->FmtChans == DevFmtAmbi2) ? 9 :
@@ -585,6 +669,16 @@ static void InitPanning(ALCdevice *device)
ambiup_reset(device->AmbiUp, device);
}
+
+ if(ConfigValueFloat(devname, "decoder", "nfc-ref-delay", &nfc_delay))
+ {
+ nfc_delay = clampf(nfc_delay, 0.001f, 1000.0f);
+ InitNearFieldCtrl(device, nfc_delay * SPEEDOFSOUNDMETRESPERSEC,
+ (device->FmtChans == DevFmtAmbi3) ? 3 :
+ (device->FmtChans == DevFmtAmbi2) ? 2 : 1,
+ true
+ );
+ }
}
else
{
@@ -612,63 +706,6 @@ static void InitPanning(ALCdevice *device)
device->RealOut.NumChannels = 0;
}
-static void InitDistanceComp(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
-{
- const char *devname = al_string_get_cstr(device->DeviceName);
- ALfloat maxdist = 0.0f;
- ALsizei total = 0;
- ALsizei i;
-
- for(i = 0;i < conf->NumSpeakers;i++)
- maxdist = maxf(maxdist, conf->Speakers[i].Distance);
-
- if(GetConfigValueBool(devname, "decoder", "distance-comp", 1) && maxdist > 0.0f)
- {
- ALfloat srate = (ALfloat)device->Frequency;
- for(i = 0;i < conf->NumSpeakers;i++)
- {
- ALsizei chan = speakermap[i];
- ALfloat delay;
-
- /* Distance compensation only delays in steps of the sample rate.
- * This is a bit less accurate since the delay time falls to the
- * nearest sample time, but it's far simpler as it doesn't have to
- * deal with phase offsets. This means at 48khz, for instance, the
- * distance delay will be in steps of about 7 millimeters.
- */
- delay = floorf((maxdist-conf->Speakers[i].Distance) / SPEEDOFSOUNDMETRESPERSEC *
- srate + 0.5f);
- if(delay >= (ALfloat)MAX_DELAY_LENGTH)
- ERR("Delay for speaker \"%s\" exceeds buffer length (%f >= %u)\n",
- al_string_get_cstr(conf->Speakers[i].Name), delay, MAX_DELAY_LENGTH);
-
- device->ChannelDelay[chan].Length = (ALsizei)clampf(
- delay, 0.0f, (ALfloat)(MAX_DELAY_LENGTH-1)
- );
- device->ChannelDelay[chan].Gain = conf->Speakers[i].Distance / maxdist;
- TRACE("Channel %u \"%s\" distance compensation: %d samples, %f gain\n", chan,
- al_string_get_cstr(conf->Speakers[i].Name), device->ChannelDelay[chan].Length,
- device->ChannelDelay[chan].Gain
- );
-
- /* Round up to the next 4th sample, so each channel buffer starts
- * 16-byte aligned.
- */
- total += RoundUp(device->ChannelDelay[chan].Length, 4);
- }
- }
-
- if(total > 0)
- {
- device->ChannelDelay[0].Buffer = al_calloc(16, total * sizeof(ALfloat));
- for(i = 1;i < MAX_OUTPUT_CHANNELS;i++)
- {
- size_t len = RoundUp(device->ChannelDelay[i-1].Length, 4);
- device->ChannelDelay[i].Buffer = device->ChannelDelay[i-1].Buffer + len;
- }
- }
-}
-
static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
{
ChannelMap chanmap[MAX_OUTPUT_CHANNELS];
@@ -756,8 +793,9 @@ static void InitCustomPanning(ALCdevice *device, const AmbDecConf *conf, const A
static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsizei speakermap[MAX_OUTPUT_CHANNELS])
{
- size_t count;
- size_t i;
+ ALfloat avg_dist;
+ ALsizei count;
+ ALsizei i;
if((conf->ChanMask&AMBI_PERIPHONIC_MASK))
{
@@ -825,6 +863,15 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALsiz
device->RealOut.NumChannels = ChannelsFromDevFmt(device->FmtChans);
+ avg_dist = 0.0f;
+ for(i = 0;i < conf->NumSpeakers;i++)
+ avg_dist += conf->Speakers[i].Distance;
+ avg_dist /= (ALfloat)conf->NumSpeakers;
+ InitNearFieldCtrl(device, avg_dist,
+ (conf->ChanMask > 0x1ff) ? 3 : (conf->ChanMask > 0xf) ? 2 : 1,
+ !!(conf->ChanMask&AMBI_PERIPHONIC_MASK)
+ );
+
InitDistanceComp(device, conf, speakermap);
}
@@ -879,8 +926,8 @@ static void InitHrtfPanning(ALCdevice *device, bool hoa_mode)
{ { 1.43315266e-001f, 0.00000000e+000f, -1.90399923e-001f, 0.00000000e+000f, 0.00000000e+000f, 0.00000000e+000f, 1.18020996e-001f, 0.00000000e+000f, 0.00000000e+000f }, { 7.26741039e-002f, 0.00000000e+000f, -1.24646009e-001f, 0.00000000e+000f, 0.00000000e+000f, 0.00000000e+000f, 1.49618920e-001f, 0.00000000e+000f, 0.00000000e+000f } },
};
const ALfloat (*AmbiMatrix)[2][MAX_AMBI_COEFFS] = hoa_mode ? AmbiMatrixHOA : AmbiMatrixFOA;
- size_t count = hoa_mode ? 9 : 4;
- size_t i;
+ ALsizei count = hoa_mode ? 9 : 4;
+ ALsizei i;
static_assert(9 <= COUNTOF(device->Hrtf.Coeffs), "ALCdevice::Hrtf.Values/Coeffs size is too small");
static_assert(COUNTOF(AmbiPoints) <= HRTF_AMBI_MAX_CHANNELS, "HRTF_AMBI_MAX_CHANNELS is too small");
@@ -960,7 +1007,10 @@ void aluInitRenderer(ALCdevice *device, ALint hrtf_id, enum HrtfRequestMode hrtf
memset(&device->Dry.Ambi, 0, sizeof(device->Dry.Ambi));
device->Dry.CoeffCount = 0;
device->Dry.NumChannels = 0;
+ for(i = 0;i < MAX_AMBI_ORDER+1;i++)
+ device->Dry.NumChannelsPerOrder[i] = 0;
+ device->AvgSpeakerDist = 0.0f;
memset(device->ChannelDelay, 0, sizeof(device->ChannelDelay));
for(i = 0;i < MAX_OUTPUT_CHANNELS;i++)
{