aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c14
-rw-r--r--Alc/ALu.c163
-rw-r--r--Alc/hrtf.c222
-rw-r--r--Alc/hrtf.h4
-rw-r--r--Alc/midi/fluidsynth.c8
-rw-r--r--Alc/mixer.c25
-rw-r--r--Alc/mixer_c.c17
-rw-r--r--Alc/mixer_defs.h15
-rw-r--r--Alc/mixer_inc.c54
-rw-r--r--Alc/mixer_neon.c32
-rw-r--r--Alc/mixer_sse.c62
-rw-r--r--Alc/panning.c64
-rw-r--r--OpenAL32/Include/alMain.h33
-rw-r--r--OpenAL32/Include/alu.h28
-rw-r--r--OpenAL32/alSource.c15
15 files changed, 198 insertions, 558 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 43f3cdc8..538ed4c3 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -1712,6 +1712,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
enum DevFmtType oldType;
ALCuint oldFreq;
FPUCtl oldMode;
+ size_t size;
// Check for attributes
if(device->Type == Loopback)
@@ -1885,6 +1886,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if((device->Flags&DEVICE_RUNNING))
return ALC_NO_ERROR;
+ al_free(device->DryBuffer);
+ device->DryBuffer = NULL;
+
UpdateClockBase(device);
if(device->Type != Loopback)
@@ -1992,11 +1996,15 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
aluInitPanning(device);
- al_free(device->DryBuffer);
- device->DryBuffer = al_calloc(16, sizeof(device->DryBuffer[0]) * device->NumChannels);
+ /* With HRTF enabled, the channels are virtual and get positioned around
+ * the virtual listener. Two extra channels are allocated for the actual
+ * HRTF-filtered output.
+ */
+ size = sizeof(device->DryBuffer[0]) * (device->NumChannels + (device->Hrtf ? 2 : 0));
+ device->DryBuffer = al_calloc(16, size);
if(!device->DryBuffer)
{
- ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", sizeof(device->DryBuffer[0]) * device->NumChannels);
+ ERR("Failed to allocate "SZFMT" bytes for mix buffer\n", size);
return ALC_INVALID_DEVICE;
}
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 97205d8b..7ec6183d 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -36,6 +36,8 @@
#include "hrtf.h"
#include "static_assert.h"
+#include "mixer_defs.h"
+
#include "backends/base.h"
#include "midi/base.h"
@@ -83,6 +85,21 @@ extern inline ALfloat lerp(ALfloat val1, ALfloat val2, ALfloat mu);
extern inline ALfloat cubic(ALfloat val0, ALfloat val1, ALfloat val2, ALfloat val3, ALfloat mu);
+static inline HrtfMixerFunc SelectHrtfMixer(void)
+{
+#ifdef HAVE_SSE
+ if((CPUCapFlags&CPU_CAP_SSE))
+ return MixHrtf_SSE;
+#endif
+#ifdef HAVE_NEON
+ if((CPUCapFlags&CPU_CAP_NEON))
+ return MixHrtf_Neon;
+#endif
+
+ return MixHrtf_C;
+}
+
+
static inline void aluCrossproduct(const ALfloat *inVector1, const ALfloat *inVector2, ALfloat *outVector)
{
outVector[0] = inVector1[1]*inVector2[2] - inVector1[2]*inVector2[1];
@@ -492,37 +509,6 @@ ALvoid CalcNonAttnSourceParams(ALvoice *voice, const ALsource *ALSource, const A
voice->IsHrtf = AL_FALSE;
}
- else if(Device->Hrtf)
- {
- for(c = 0;c < num_channels;c++)
- {
- if(chans[c].channel == LFE)
- {
- /* Skip LFE */
- voice->Direct.Mix.Hrtf.Params[c].Delay[0] = 0;
- voice->Direct.Mix.Hrtf.Params[c].Delay[1] = 0;
- for(i = 0;i < HRIR_LENGTH;i++)
- {
- voice->Direct.Mix.Hrtf.Params[c].Coeffs[i][0] = 0.0f;
- voice->Direct.Mix.Hrtf.Params[c].Coeffs[i][1] = 0.0f;
- }
- }
- else
- {
- /* Get the static HRIR coefficients and delays for this
- * channel. */
- GetLerpedHrtfCoeffs(Device->Hrtf,
- chans[c].elevation, chans[c].angle, 1.0f, DryGain,
- voice->Direct.Mix.Hrtf.Params[c].Coeffs,
- voice->Direct.Mix.Hrtf.Params[c].Delay);
- }
- }
- voice->Direct.Counter = 0;
- voice->Direct.Moving = AL_TRUE;
- voice->Direct.Mix.Hrtf.IrSize = GetHrtfIrSize(Device->Hrtf);
-
- voice->IsHrtf = AL_TRUE;
- }
else
{
for(c = 0;c < num_channels;c++)
@@ -929,70 +915,6 @@ ALvoid CalcSourceParams(ALvoice *voice, const ALsource *ALSource, const ALCconte
BufferListItem = BufferListItem->next;
}
- if(Device->Hrtf)
- {
- /* Use a binaural HRTF algorithm for stereo headphone playback */
- ALfloat delta, ev = 0.0f, az = 0.0f;
- ALfloat radius = ALSource->Radius;
- ALfloat dirfact = 1.0f;
-
- if(Distance > FLT_EPSILON)
- {
- ALfloat invlen = 1.0f/Distance;
- Position[0] *= invlen;
- Position[1] *= invlen;
- Position[2] *= invlen;
-
- /* Calculate elevation and azimuth only when the source is not at
- * the listener. This prevents +0 and -0 Z from producing
- * inconsistent panning. Also, clamp Y in case FP precision errors
- * cause it to land outside of -1..+1. */
- ev = asinf(clampf(Position[1], -1.0f, 1.0f));
- az = atan2f(Position[0], -Position[2]*ZScale);
- }
- if(radius > Distance)
- dirfact *= Distance / radius;
-
- /* Check to see if the HRIR is already moving. */
- if(voice->Direct.Moving)
- {
- /* Calculate the normalized HRTF transition factor (delta). */
- delta = CalcHrtfDelta(voice->Direct.Mix.Hrtf.Gain, DryGain,
- voice->Direct.Mix.Hrtf.Dir, Position);
- /* If the delta is large enough, get the moving HRIR target
- * coefficients, target delays, steppping values, and counter. */
- if(delta > 0.001f)
- {
- ALuint counter = GetMovingHrtfCoeffs(Device->Hrtf,
- ev, az, dirfact, DryGain, delta, voice->Direct.Counter,
- voice->Direct.Mix.Hrtf.Params[0].Coeffs, voice->Direct.Mix.Hrtf.Params[0].Delay,
- voice->Direct.Mix.Hrtf.Params[0].CoeffStep, voice->Direct.Mix.Hrtf.Params[0].DelayStep
- );
- voice->Direct.Counter = counter;
- voice->Direct.Mix.Hrtf.Gain = DryGain;
- voice->Direct.Mix.Hrtf.Dir[0] = Position[0];
- voice->Direct.Mix.Hrtf.Dir[1] = Position[1];
- voice->Direct.Mix.Hrtf.Dir[2] = Position[2];
- }
- }
- else
- {
- /* Get the initial (static) HRIR coefficients and delays. */
- GetLerpedHrtfCoeffs(Device->Hrtf, ev, az, dirfact, DryGain,
- voice->Direct.Mix.Hrtf.Params[0].Coeffs,
- voice->Direct.Mix.Hrtf.Params[0].Delay);
- voice->Direct.Counter = 0;
- voice->Direct.Moving = AL_TRUE;
- voice->Direct.Mix.Hrtf.Gain = DryGain;
- voice->Direct.Mix.Hrtf.Dir[0] = Position[0];
- voice->Direct.Mix.Hrtf.Dir[1] = Position[1];
- voice->Direct.Mix.Hrtf.Dir[2] = Position[2];
- }
- voice->Direct.Mix.Hrtf.IrSize = GetHrtfIrSize(Device->Hrtf);
-
- voice->IsHrtf = AL_TRUE;
- }
- else
{
MixGains *gains = voice->Direct.Mix.Gains[0];
ALfloat radius = ALSource->Radius;
@@ -1125,14 +1047,24 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
while(size > 0)
{
+ ALuint outchanoffset = 0;
+ ALuint outchancount = device->NumChannels;
+
IncrementRef(&device->MixCount);
SamplesToDo = minu(size, BUFFERSIZE);
for(c = 0;c < device->NumChannels;c++)
memset(device->DryBuffer[c], 0, SamplesToDo*sizeof(ALfloat));
+ if(device->Hrtf)
+ {
+ outchanoffset = device->NumChannels;
+ outchancount = 2;
+ for(c = 0;c < outchancount;c++)
+ memset(device->DryBuffer[outchanoffset+c], 0, SamplesToDo*sizeof(ALfloat));
+ }
V0(device->Backend,lock)();
- V(device->Synth,process)(SamplesToDo, device->DryBuffer);
+ V(device->Synth,process)(SamplesToDo, &device->DryBuffer[outchanoffset]);
ctx = ATOMIC_LOAD(&device->ContextList);
while(ctx)
@@ -1212,7 +1144,16 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
device->SamplesDone %= device->Frequency;
V0(device->Backend,unlock)();
- if(device->Bs2b)
+ if(device->Hrtf)
+ {
+ HrtfMixerFunc HrtfMix = SelectHrtfMixer();
+ ALuint irsize = GetHrtfIrSize(device->Hrtf);
+ for(c = 0;c < device->NumChannels;c++)
+ HrtfMix(&device->DryBuffer[outchanoffset], device->DryBuffer[c], device->Hrtf_Offset, irsize,
+ &device->Hrtf_Params[c], &device->Hrtf_State[c], SamplesToDo);
+ device->Hrtf_Offset += SamplesToDo;
+ }
+ else if(device->Bs2b)
{
/* Apply binaural/crossfeed filter */
for(i = 0;i < SamplesToDo;i++)
@@ -1231,32 +1172,32 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size)
switch(device->FmtType)
{
case DevFmtByte:
- Write_ALbyte(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALbyte);
+ Write_ALbyte(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALbyte);
break;
case DevFmtUByte:
- Write_ALubyte(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALubyte);
+ Write_ALubyte(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALubyte);
break;
case DevFmtShort:
- Write_ALshort(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALshort);
+ Write_ALshort(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALshort);
break;
case DevFmtUShort:
- Write_ALushort(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALushort);
+ Write_ALushort(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALushort);
break;
case DevFmtInt:
- Write_ALint(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALint);
+ Write_ALint(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALint);
break;
case DevFmtUInt:
- Write_ALuint(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALuint);
+ Write_ALuint(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALuint);
break;
case DevFmtFloat:
- Write_ALfloat(device->DryBuffer, buffer, SamplesToDo, device->NumChannels);
- buffer = (char*)buffer + SamplesToDo*device->NumChannels*sizeof(ALfloat);
+ Write_ALfloat(&device->DryBuffer[outchanoffset], buffer, SamplesToDo, outchancount);
+ buffer = (char*)buffer + SamplesToDo*outchancount*sizeof(ALfloat);
break;
}
}
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index 9f1386aa..2e4156a0 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -58,10 +58,6 @@ struct Hrtf {
static const ALchar magicMarker00[8] = "MinPHR00";
static const ALchar magicMarker01[8] = "MinPHR01";
-/* First value for pass-through coefficients (remaining are 0), used for omni-
- * directional sounds. */
-static const ALfloat PassthruCoeff = 32767.0f * 0.707106781187f/*sqrt(0.5)*/;
-
static struct Hrtf *LoadedHrtfs = NULL;
/* Calculate the elevation indices given the polar elevation in radians.
@@ -88,45 +84,12 @@ static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *az
*azmu = az - floorf(az);
}
-/* Calculates the normalized HRTF transition factor (delta) from the changes
- * in gain and listener to source angle between updates. The result is a
- * normalized delta factor that can be used to calculate moving HRIR stepping
- * values.
- */
-ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3])
-{
- ALfloat gainChange, angleChange, change;
-
- // Calculate the normalized dB gain change.
- newGain = maxf(newGain, 0.0001f);
- oldGain = maxf(oldGain, 0.0001f);
- gainChange = fabsf(log10f(newGain / oldGain) / log10f(0.0001f));
-
- // Calculate the angle change only when there is enough gain to notice it.
- angleChange = 0.0f;
- if(gainChange > 0.0001f || newGain > 0.0001f)
- {
- // No angle change when the directions are equal or degenerate (when
- // both have zero length).
- if(newdir[0] != olddir[0] || newdir[1] != olddir[1] || newdir[2] != olddir[2])
- {
- ALfloat dotp = olddir[0]*newdir[0] + olddir[1]*newdir[1] + olddir[2]*newdir[2];
- angleChange = acosf(clampf(dotp, -1.0f, 1.0f)) / F_PI;
- }
- }
-
- // Use the largest of the two changes for the delta factor, and apply a
- // significance shaping function to it.
- change = maxf(angleChange * 25.0f, gainChange) * 2.0f;
- return minf(change, 1.0f);
-}
-
/* Calculates static HRIR coefficients and delays for the given polar
* elevation and azimuth in radians. Linear interpolation is used to
* increase the apparent resolution of the HRIR data set. The coefficients
* are also normalized and attenuated by the specified gain.
*/
-void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays)
+void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat (*coeffs)[2], ALuint *delays)
{
ALuint evidx[2], lidx[4], ridx[4];
ALfloat mu[3], blend[4];
@@ -158,12 +121,12 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi
blend[3] = ( mu[1]) * ( mu[2]);
/* Calculate the HRIR delays using linear interpolation. */
- delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
- Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
- dirfact + 0.5f) << HRTFDELAY_BITS;
- delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
- Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
- dirfact + 0.5f) << HRTFDELAY_BITS;
+ delays[0] = fastf2u(Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
+ Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3] +
+ 0.5f);
+ delays[1] = fastf2u(Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
+ Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3] +
+ 0.5f);
/* Calculate the sample offsets for the HRIR indices. */
lidx[0] *= Hrtf->irSize;
@@ -175,183 +138,22 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi
ridx[2] *= Hrtf->irSize;
ridx[3] *= Hrtf->irSize;
- /* Calculate the normalized and attenuated HRIR coefficients using linear
- * interpolation when there is enough gain to warrant it. Zero the
- * coefficients if gain is too low.
- */
- if(gain > 0.0001f)
+ for(i = 0;i < Hrtf->irSize;i++)
{
ALfloat c;
-
- gain *= 1.0f/32767.0f;
-
- i = 0;
c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
- coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
+ coeffs[i][0] = c * (1.0f/32767.0f);
c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
- coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
-
- for(i = 1;i < Hrtf->irSize;i++)
- {
- c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
- Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
- coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
- c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
- Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
- coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
- }
+ coeffs[i][1] = c * (1.0f/32767.0f);
}
- else
- {
- for(i = 0;i < Hrtf->irSize;i++)
- {
- coeffs[i][0] = 0.0f;
- coeffs[i][1] = 0.0f;
- }
- }
-}
-
-/* Calculates the moving HRIR target coefficients, target delays, and
- * stepping values for the given polar elevation and azimuth in radians.
- * Linear interpolation is used to increase the apparent resolution of the
- * HRIR data set. The coefficients are also normalized and attenuated by the
- * specified gain. Stepping resolution and count is determined using the
- * given delta factor between 0.0 and 1.0.
- */
-ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep)
-{
- ALuint evidx[2], lidx[4], ridx[4];
- ALfloat mu[3], blend[4];
- ALfloat left, right;
- ALfloat step;
- ALuint i;
-
- /* Claculate elevation indices and interpolation factor. */
- CalcEvIndices(Hrtf->evCount, elevation, evidx, &mu[2]);
-
- for(i = 0;i < 2;i++)
- {
- ALuint azcount = Hrtf->azCount[evidx[i]];
- ALuint evoffset = Hrtf->evOffset[evidx[i]];
- ALuint azidx[2];
-
- /* Calculate azimuth indices and interpolation factor for this elevation. */
- CalcAzIndices(azcount, azimuth, azidx, &mu[i]);
-
- /* Calculate a set of linear HRIR indices for left and right channels. */
- lidx[i*2 + 0] = evoffset + azidx[0];
- lidx[i*2 + 1] = evoffset + azidx[1];
- ridx[i*2 + 0] = evoffset + ((azcount-azidx[0]) % azcount);
- ridx[i*2 + 1] = evoffset + ((azcount-azidx[1]) % azcount);
- }
-
- // Calculate the stepping parameters.
- delta = maxf(floorf(delta*(Hrtf->sampleRate*0.015f) + 0.5f), 1.0f);
- step = 1.0f / delta;
-
- /* Calculate 4 blending weights for 2D bilinear interpolation. */
- blend[0] = (1.0f-mu[0]) * (1.0f-mu[2]);
- blend[1] = ( mu[0]) * (1.0f-mu[2]);
- blend[2] = (1.0f-mu[1]) * ( mu[2]);
- blend[3] = ( mu[1]) * ( mu[2]);
-
- /* Calculate the HRIR delays using linear interpolation. Then calculate
- * the delay stepping values using the target and previous running
- * delays.
- */
- left = (ALfloat)(delays[0] - (delayStep[0] * counter));
- right = (ALfloat)(delays[1] - (delayStep[1] * counter));
-
- delays[0] = fastf2u((Hrtf->delays[lidx[0]]*blend[0] + Hrtf->delays[lidx[1]]*blend[1] +
- Hrtf->delays[lidx[2]]*blend[2] + Hrtf->delays[lidx[3]]*blend[3]) *
- dirfact + 0.5f) << HRTFDELAY_BITS;
- delays[1] = fastf2u((Hrtf->delays[ridx[0]]*blend[0] + Hrtf->delays[ridx[1]]*blend[1] +
- Hrtf->delays[ridx[2]]*blend[2] + Hrtf->delays[ridx[3]]*blend[3]) *
- dirfact + 0.5f) << HRTFDELAY_BITS;
-
- delayStep[0] = fastf2i(step * (delays[0] - left));
- delayStep[1] = fastf2i(step * (delays[1] - right));
-
- /* Calculate the sample offsets for the HRIR indices. */
- lidx[0] *= Hrtf->irSize;
- lidx[1] *= Hrtf->irSize;
- lidx[2] *= Hrtf->irSize;
- lidx[3] *= Hrtf->irSize;
- ridx[0] *= Hrtf->irSize;
- ridx[1] *= Hrtf->irSize;
- ridx[2] *= Hrtf->irSize;
- ridx[3] *= Hrtf->irSize;
-
- /* Calculate the normalized and attenuated target HRIR coefficients using
- * linear interpolation when there is enough gain to warrant it. Zero
- * the target coefficients if gain is too low. Then calculate the
- * coefficient stepping values using the target and previous running
- * coefficients.
- */
- if(gain > 0.0001f)
- {
- ALfloat c;
-
- gain *= 1.0f/32767.0f;
-
- i = 0;
- left = coeffs[i][0] - (coeffStep[i][0] * counter);
- right = coeffs[i][1] - (coeffStep[i][1] * counter);
-
- c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
- Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
- coeffs[i][0] = lerp(PassthruCoeff, c, dirfact) * gain;
- c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
- Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
- coeffs[i][1] = lerp(PassthruCoeff, c, dirfact) * gain;
-
- coeffStep[i][0] = step * (coeffs[i][0] - left);
- coeffStep[i][1] = step * (coeffs[i][1] - right);
-
- for(i = 1;i < Hrtf->irSize;i++)
- {
- left = coeffs[i][0] - (coeffStep[i][0] * counter);
- right = coeffs[i][1] - (coeffStep[i][1] * counter);
-
- c = (Hrtf->coeffs[lidx[0]+i]*blend[0] + Hrtf->coeffs[lidx[1]+i]*blend[1] +
- Hrtf->coeffs[lidx[2]+i]*blend[2] + Hrtf->coeffs[lidx[3]+i]*blend[3]);
- coeffs[i][0] = lerp(0.0f, c, dirfact) * gain;
- c = (Hrtf->coeffs[ridx[0]+i]*blend[0] + Hrtf->coeffs[ridx[1]+i]*blend[1] +
- Hrtf->coeffs[ridx[2]+i]*blend[2] + Hrtf->coeffs[ridx[3]+i]*blend[3]);
- coeffs[i][1] = lerp(0.0f, c, dirfact) * gain;
-
- coeffStep[i][0] = step * (coeffs[i][0] - left);
- coeffStep[i][1] = step * (coeffs[i][1] - right);
- }
- }
- else
- {
- for(i = 0;i < Hrtf->irSize;i++)
- {
- left = coeffs[i][0] - (coeffStep[i][0] * counter);
- right = coeffs[i][1] - (coeffStep[i][1] * counter);
-
- coeffs[i][0] = 0.0f;
- coeffs[i][1] = 0.0f;
-
- coeffStep[i][0] = step * -left;
- coeffStep[i][1] = step * -right;
- }
- }
-
- /* The stepping count is the number of samples necessary for the HRIR to
- * complete its transition. The mixer will only apply stepping for this
- * many samples.
- */
- return fastf2u(delta);
}
static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
{
- const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
+ const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
struct Hrtf *Hrtf = NULL;
ALboolean failed = AL_FALSE;
ALuint rate = 0, irCount = 0;
@@ -518,7 +320,7 @@ static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
static struct Hrtf *LoadHrtf01(FILE *f, ALuint deviceRate)
{
- const ALubyte maxDelay = SRC_HISTORY_LENGTH-1;
+ const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
struct Hrtf *Hrtf = NULL;
ALboolean failed = AL_FALSE;
ALuint rate = 0, irCount = 0;
diff --git a/Alc/hrtf.h b/Alc/hrtf.h
index 938bf552..48636344 100644
--- a/Alc/hrtf.h
+++ b/Alc/hrtf.h
@@ -21,8 +21,6 @@ ALCboolean FindHrtfFormat(enum DevFmtChannels *chans, ALCuint *srate);
void FreeHrtfs(void);
ALuint GetHrtfIrSize(const struct Hrtf *Hrtf);
-ALfloat CalcHrtfDelta(ALfloat oldGain, ALfloat newGain, const ALfloat olddir[3], const ALfloat newdir[3]);
-void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays);
-ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat dirfact, ALfloat gain, ALfloat delta, ALint counter, ALfloat (*coeffs)[2], ALuint *delays, ALfloat (*coeffStep)[2], ALint *delayStep);
+void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat (*coeffs)[2], ALuint *delays);
#endif /* ALC_HRTF_H */
diff --git a/Alc/midi/fluidsynth.c b/Alc/midi/fluidsynth.c
index bf774ab1..d08d4fb5 100644
--- a/Alc/midi/fluidsynth.c
+++ b/Alc/midi/fluidsynth.c
@@ -853,8 +853,8 @@ static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict
return;
if(state != AL_PLAYING)
{
- fluid_synth_write_float(self->Synth, SamplesToDo, DryBuffer[FrontLeft], 0, 1,
- DryBuffer[FrontRight], 0, 1);
+ fluid_synth_write_float(self->Synth, SamplesToDo, DryBuffer[0], 0, 1,
+ DryBuffer[1], 0, 1);
return;
}
@@ -882,8 +882,8 @@ static void FSynth_process(FSynth *self, ALuint SamplesToDo, ALfloat (*restrict
if(tonext > 0)
{
ALuint todo = minu(tonext, SamplesToDo-total);
- fluid_synth_write_float(self->Synth, todo, DryBuffer[FrontLeft], total, 1,
- DryBuffer[FrontRight], total, 1);
+ fluid_synth_write_float(self->Synth, todo, DryBuffer[0], total, 1,
+ DryBuffer[1], total, 1);
total += todo;
tonext -= todo;
}
diff --git a/Alc/mixer.c b/Alc/mixer.c
index 5927bb7b..7a4d455d 100644
--- a/Alc/mixer.c
+++ b/Alc/mixer.c
@@ -41,20 +41,6 @@
extern inline void InitiatePositionArrays(ALuint frac, ALuint increment, ALuint *frac_arr, ALuint *pos_arr, ALuint size);
-static inline HrtfMixerFunc SelectHrtfMixer(void)
-{
-#ifdef HAVE_SSE
- if((CPUCapFlags&CPU_CAP_SSE))
- return MixHrtf_SSE;
-#endif
-#ifdef HAVE_NEON
- if((CPUCapFlags&CPU_CAP_NEON))
- return MixHrtf_Neon;
-#endif
-
- return MixHrtf_C;
-}
-
static inline MixerFunc SelectMixer(void)
{
#ifdef HAVE_SSE
@@ -179,7 +165,6 @@ static const ALfloat *DoFilters(ALfilterState *lpfilter, ALfilterState *hpfilter
ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint SamplesToDo)
{
MixerFunc Mix;
- HrtfMixerFunc HrtfMix;
ResamplerFunc Resample;
ALbufferlistitem *BufferListItem;
ALuint DataPosInt, DataPosFrac;
@@ -218,7 +203,6 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam
}
Mix = SelectMixer();
- HrtfMix = SelectHrtfMixer();
Resample = ((increment == FRACTIONONE && DataPosFrac == 0) ?
Resample_copy32_C : SelectResampler(Resampler));
@@ -431,13 +415,8 @@ ALvoid MixSource(ALvoice *voice, ALsource *Source, ALCdevice *Device, ALuint Sam
Device->FilteredData, ResampledData, DstBufferSize,
parms->Filters[chan].ActiveType
);
- if(!voice->IsHrtf)
- Mix(samples, Device->NumChannels, parms->OutBuffer, parms->Mix.Gains[chan],
- parms->Counter, OutPos, DstBufferSize);
- else
- HrtfMix(parms->OutBuffer, samples, parms->Counter, voice->Offset,
- OutPos, parms->Mix.Hrtf.IrSize, &parms->Mix.Hrtf.Params[chan],
- &parms->Mix.Hrtf.State[chan], DstBufferSize);
+ Mix(samples, Device->NumChannels, parms->OutBuffer, parms->Mix.Gains[chan],
+ parms->Counter, OutPos, DstBufferSize);
}
/* Only the first channel for B-Format buffers (W channel) goes to
diff --git a/Alc/mixer_c.c b/Alc/mixer_c.c
index 0fdcc087..caedd339 100644
--- a/Alc/mixer_c.c
+++ b/Alc/mixer_c.c
@@ -59,23 +59,6 @@ void ALfilterState_processC(ALfilterState *filter, ALfloat *restrict dst, const
}
-static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
- const ALuint IrSize,
- ALfloat (*restrict Coeffs)[2],
- const ALfloat (*restrict CoeffStep)[2],
- ALfloat left, ALfloat right)
-{
- ALuint c;
- for(c = 0;c < IrSize;c++)
- {
- const ALuint off = (Offset+c)&HRIR_MASK;
- Values[off][0] += Coeffs[c][0] * left;
- Values[off][1] += Coeffs[c][1] * right;
- Coeffs[c][0] += CoeffStep[c][0];
- Coeffs[c][1] += CoeffStep[c][1];
- }
-}
-
static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
const ALuint IrSize,
ALfloat (*restrict Coeffs)[2],
diff --git a/Alc/mixer_defs.h b/Alc/mixer_defs.h
index c1500ed2..62dad9dc 100644
--- a/Alc/mixer_defs.h
+++ b/Alc/mixer_defs.h
@@ -20,17 +20,15 @@ const ALfloat *Resample_cubic32_C(const ALfloat *src, ALuint frac, ALuint increm
/* C mixers */
void MixHrtf_C(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
- ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
- const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
- ALuint BufferSize);
+ ALuint Offset, const ALuint IrSize, const struct HrtfParams *hrtfparams,
+ struct HrtfState *hrtfstate, ALuint BufferSize);
void Mix_C(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
/* SSE mixers */
void MixHrtf_SSE(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
- ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
- const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
- ALuint BufferSize);
+ ALuint Offset, const ALuint IrSize, const struct HrtfParams *hrtfparams,
+ struct HrtfState *hrtfstate, ALuint BufferSize);
void Mix_SSE(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
@@ -56,9 +54,8 @@ const ALfloat *Resample_lerp32_SSE41(const ALfloat *src, ALuint frac, ALuint inc
/* Neon mixers */
void MixHrtf_Neon(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
- ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
- const struct HrtfParams *hrtfparams, struct HrtfState *hrtfstate,
- ALuint BufferSize);
+ ALuint Offset, const ALuint IrSize, const struct HrtfParams *hrtfparams,
+ struct HrtfState *hrtfstate, ALuint BufferSize);
void Mix_Neon(const ALfloat *data, ALuint OutChans, ALfloat (*restrict OutBuffer)[BUFFERSIZE],
struct MixGains *Gains, ALuint Counter, ALuint OutPos, ALuint BufferSize);
diff --git a/Alc/mixer_inc.c b/Alc/mixer_inc.c
index ab6f32c5..46ccec7d 100644
--- a/Alc/mixer_inc.c
+++ b/Alc/mixer_inc.c
@@ -14,11 +14,6 @@
#define MixHrtf MERGE(MixHrtf_,SUFFIX)
-static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
- const ALuint irSize,
- ALfloat (*restrict Coeffs)[2],
- const ALfloat (*restrict CoeffStep)[2],
- ALfloat left, ALfloat right);
static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
const ALuint irSize,
ALfloat (*restrict Coeffs)[2],
@@ -26,7 +21,7 @@ static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
- ALuint Counter, ALuint Offset, ALuint OutPos, const ALuint IrSize,
+ ALuint Offset, const ALuint IrSize,
const HrtfParams *hrtfparams, HrtfState *hrtfstate, ALuint BufferSize)
{
alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
@@ -37,52 +32,25 @@ void MixHrtf(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
for(c = 0;c < IrSize;c++)
{
- Coeffs[c][0] = hrtfparams->Coeffs[c][0] - (hrtfparams->CoeffStep[c][0]*Counter);
- Coeffs[c][1] = hrtfparams->Coeffs[c][1] - (hrtfparams->CoeffStep[c][1]*Counter);
+ Coeffs[c][0] = hrtfparams->Coeffs[c][0];
+ Coeffs[c][1] = hrtfparams->Coeffs[c][1];
}
- Delay[0] = hrtfparams->Delay[0] - (hrtfparams->DelayStep[0]*Counter);
- Delay[1] = hrtfparams->Delay[1] - (hrtfparams->DelayStep[1]*Counter);
+ Delay[0] = hrtfparams->Delay[0];
+ Delay[1] = hrtfparams->Delay[1];
- for(pos = 0;pos < BufferSize && pos < Counter;pos++)
+ for(pos = 0;pos < BufferSize;pos++)
{
- hrtfstate->History[Offset&SRC_HISTORY_MASK] = data[pos];
- left = lerp(hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
- hrtfstate->History[(Offset-(Delay[0]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
- (Delay[0]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
- right = lerp(hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS))&SRC_HISTORY_MASK],
- hrtfstate->History[(Offset-(Delay[1]>>HRTFDELAY_BITS)-1)&SRC_HISTORY_MASK],
- (Delay[1]&HRTFDELAY_MASK)*(1.0f/HRTFDELAY_FRACONE));
-
- Delay[0] += hrtfparams->DelayStep[0];
- Delay[1] += hrtfparams->DelayStep[1];
-
- hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
- hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
- Offset++;
-
- ApplyCoeffsStep(Offset, hrtfstate->Values, IrSize, Coeffs, hrtfparams->CoeffStep, left, right);
- OutBuffer[FrontLeft][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][0];
- OutBuffer[FrontRight][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1];
- OutPos++;
- }
-
- Delay[0] >>= HRTFDELAY_BITS;
- Delay[1] >>= HRTFDELAY_BITS;
- for(;pos < BufferSize;pos++)
- {
- hrtfstate->History[Offset&SRC_HISTORY_MASK] = data[pos];
- left = hrtfstate->History[(Offset-Delay[0])&SRC_HISTORY_MASK];
- right = hrtfstate->History[(Offset-Delay[1])&SRC_HISTORY_MASK];
+ hrtfstate->History[Offset&HRTF_HISTORY_MASK] = data[pos];
+ left = hrtfstate->History[(Offset-Delay[0])&HRTF_HISTORY_MASK];
+ right = hrtfstate->History[(Offset-Delay[1])&HRTF_HISTORY_MASK];
hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][0] = 0.0f;
hrtfstate->Values[(Offset+IrSize)&HRIR_MASK][1] = 0.0f;
Offset++;
ApplyCoeffs(Offset, hrtfstate->Values, IrSize, Coeffs, left, right);
- OutBuffer[FrontLeft][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][0];
- OutBuffer[FrontRight][OutPos] += hrtfstate->Values[Offset&HRIR_MASK][1];
-
- OutPos++;
+ OutBuffer[0][pos] += hrtfstate->Values[Offset&HRIR_MASK][0];
+ OutBuffer[1][pos] += hrtfstate->Values[Offset&HRIR_MASK][1];
}
}
diff --git a/Alc/mixer_neon.c b/Alc/mixer_neon.c
index 8ce17644..413bd627 100644
--- a/Alc/mixer_neon.c
+++ b/Alc/mixer_neon.c
@@ -9,38 +9,6 @@
#include "hrtf.h"
-static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
- const ALuint IrSize,
- ALfloat (*restrict Coeffs)[2],
- const ALfloat (*restrict CoeffStep)[2],
- ALfloat left, ALfloat right)
-{
- ALuint c;
- float32x4_t leftright4;
- {
- float32x2_t leftright2 = vdup_n_f32(0.0);
- leftright2 = vset_lane_f32(left, leftright2, 0);
- leftright2 = vset_lane_f32(right, leftright2, 1);
- leftright4 = vcombine_f32(leftright2, leftright2);
- }
- for(c = 0;c < IrSize;c += 2)
- {
- const ALuint o0 = (Offset+c)&HRIR_MASK;
- const ALuint o1 = (o0+1)&HRIR_MASK;
- float32x4_t vals = vcombine_f32(vld1_f32((float32_t*)&Values[o0][0]),
- vld1_f32((float32_t*)&Values[o1][0]));
- float32x4_t coefs = vld1q_f32((float32_t*)&Coeffs[c][0]);
- float32x4_t deltas = vld1q_f32(&CoeffStep[c][0]);
-
- vals = vmlaq_f32(vals, coefs, leftright4);
- coefs = vaddq_f32(coefs, deltas);
-
- vst1_f32((float32_t*)&Values[o0][0], vget_low_f32(vals));
- vst1_f32((float32_t*)&Values[o1][0], vget_high_f32(vals));
- vst1q_f32(&Coeffs[c][0], coefs);
- }
-}
-
static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
const ALuint IrSize,
ALfloat (*restrict Coeffs)[2],
diff --git a/Alc/mixer_sse.c b/Alc/mixer_sse.c
index d86cf749..d0dca40e 100644
--- a/Alc/mixer_sse.c
+++ b/Alc/mixer_sse.c
@@ -19,68 +19,6 @@
#include "mixer_defs.h"
-static inline void ApplyCoeffsStep(ALuint Offset, ALfloat (*restrict Values)[2],
- const ALuint IrSize,
- ALfloat (*restrict Coeffs)[2],
- const ALfloat (*restrict CoeffStep)[2],
- ALfloat left, ALfloat right)
-{
- const __m128 lrlr = _mm_setr_ps(left, right, left, right);
- __m128 coeffs, deltas, imp0, imp1;
- __m128 vals = _mm_setzero_ps();
- ALuint i;
-
- if((Offset&1))
- {
- const ALuint o0 = Offset&HRIR_MASK;
- const ALuint o1 = (Offset+IrSize-1)&HRIR_MASK;
-
- coeffs = _mm_load_ps(&Coeffs[0][0]);
- deltas = _mm_load_ps(&CoeffStep[0][0]);
- vals = _mm_loadl_pi(vals, (__m64*)&Values[o0][0]);
- imp0 = _mm_mul_ps(lrlr, coeffs);
- coeffs = _mm_add_ps(coeffs, deltas);
- vals = _mm_add_ps(imp0, vals);
- _mm_store_ps(&Coeffs[0][0], coeffs);
- _mm_storel_pi((__m64*)&Values[o0][0], vals);
- for(i = 1;i < IrSize-1;i += 2)
- {
- const ALuint o2 = (Offset+i)&HRIR_MASK;
-
- coeffs = _mm_load_ps(&Coeffs[i+1][0]);
- deltas = _mm_load_ps(&CoeffStep[i+1][0]);
- vals = _mm_load_ps(&Values[o2][0]);
- imp1 = _mm_mul_ps(lrlr, coeffs);
- coeffs = _mm_add_ps(coeffs, deltas);
- imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2));
- vals = _mm_add_ps(imp0, vals);
- _mm_store_ps(&Coeffs[i+1][0], coeffs);
- _mm_store_ps(&Values[o2][0], vals);
- imp0 = imp1;
- }
- vals = _mm_loadl_pi(vals, (__m64*)&Values[o1][0]);
- imp0 = _mm_movehl_ps(imp0, imp0);
- vals = _mm_add_ps(imp0, vals);
- _mm_storel_pi((__m64*)&Values[o1][0], vals);
- }
- else
- {
- for(i = 0;i < IrSize;i += 2)
- {
- const ALuint o = (Offset + i)&HRIR_MASK;
-
- coeffs = _mm_load_ps(&Coeffs[i][0]);
- deltas = _mm_load_ps(&CoeffStep[i][0]);
- vals = _mm_load_ps(&Values[o][0]);
- imp0 = _mm_mul_ps(lrlr, coeffs);
- coeffs = _mm_add_ps(coeffs, deltas);
- vals = _mm_add_ps(imp0, vals);
- _mm_store_ps(&Coeffs[i][0], coeffs);
- _mm_store_ps(&Values[o][0], vals);
- }
- }
-}
-
static inline void ApplyCoeffs(ALuint Offset, ALfloat (*restrict Values)[2],
const ALuint IrSize,
ALfloat (*restrict Coeffs)[2],
diff --git a/Alc/panning.c b/Alc/panning.c
index f3305233..64be6f4b 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -124,6 +124,18 @@ DECL_CONST static inline const char *GetLabelFromChannel(enum Channel channel)
case BackCenter: return "back-center";
case SideLeft: return "side-left";
case SideRight: return "side-right";
+
+ case TopCenter: return "top-center";
+ case BottomCenter: return "bottom-center";
+ case TopFrontLeft: return "top-front-left";
+ case TopFrontRight: return "top-front-right";
+ case TopBackLeft: return "top-back-left";
+ case TopBackRight: return "top-back-right";
+ case BottomFrontLeft: return "bottom-front-left";
+ case BottomFrontRight: return "bottom-front-right";
+ case BottomBackLeft: return "bottom-back-left";
+ case BottomBackRight: return "bottom-back-right";
+
case InvalidChannel: break;
}
return "(unknown)";
@@ -322,6 +334,21 @@ ALvoid aluInitPanning(ALCdevice *device)
{ BackRight, { { 0.224752f, -0.295009f, -0.170325f, 0.0f, 0.0f, 0.0f, 0.0f, 0.105349f, 0.182473f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065799f }, { 0.224752f, -0.225790f, -0.130361f, 0.0f } } },
{ SideLeft, { { 0.224739f, 0.000002f, 0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065795f }, { 0.224739f, 0.000000f, 0.260717f, 0.0f } } },
{ SideRight, { { 0.224739f, 0.000002f, -0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065795f }, { 0.224739f, 0.000000f, -0.260717f, 0.0f } } },
+ }, CubeDiamond[14] = {
+ { SideLeft, { { 0.130137f, -0.000013f, 0.207620f, 0.000001f, -0.081895f, 0.000001f, 0.000002f, -0.144357f, -0.000015f, -0.000002f, 0.000001f, -0.032339f, -0.000000f, 0.000001f, 0.000005f, -0.057583f }, { 0.130137f, -0.000009f, 0.139199f, 0.000001f } } },
+ { FrontCenter, { { 0.130131f, 0.207613f, -0.000007f, 0.000001f, -0.081898f, 0.000001f, -0.000000f, 0.144354f, -0.000010f, -0.000002f, -0.032343f, 0.000006f, -0.000000f, -0.000001f, 0.057583f, -0.000004f }, { 0.130131f, 0.139195f, -0.000005f, 0.000001f } } },
+ { SideRight, { { 0.130140f, 0.000001f, -0.207624f, -0.000001f, -0.081900f, 0.000005f, 0.000001f, -0.144357f, -0.000002f, 0.000002f, -0.000004f, 0.032342f, -0.000000f, -0.000005f, -0.000002f, 0.057580f }, { 0.130140f, 0.000000f, -0.139202f, -0.000000f } } },
+ { BackCenter, { { 0.130142f, -0.207624f, 0.000006f, -0.000010f, -0.081897f, 0.000011f, 0.000005f, 0.144354f, -0.000006f, 0.000004f, 0.032340f, 0.000000f, -0.000002f, -0.000005f, -0.057579f, 0.000003f }, { 0.130142f, -0.139202f, 0.000004f, -0.000007f } } },
+ { TopCenter, { { 0.072579f, 0.000006f, 0.000001f, 0.123524f, 0.126630f, 0.000008f, 0.000001f, -0.000002f, 0.000001f, 0.070290f, 0.000005f, 0.000001f, -0.000002f, 0.000001f, -0.000001f, 0.000002f }, { 0.072579f, 0.000004f, 0.000001f, 0.082817f } } },
+ { BottomCenter, { { 0.072577f, -0.000008f, -0.000004f, -0.123522f, 0.126628f, 0.000012f, 0.000005f, -0.000001f, 0.000002f, -0.070291f, -0.000008f, -0.000002f, 0.000001f, -0.000002f, 0.000000f, -0.000001f }, { 0.072577f, -0.000006f, -0.000003f, -0.082815f } } },
+ { TopFrontLeft, { { 0.176238f, 0.156939f, 0.156950f, 0.149964f, 0.006362f, 0.101960f, 0.101968f, -0.000003f, 0.117690f, -0.020696f, 0.018718f, 0.018723f, 0.000002f, 0.038069f, -0.025485f, 0.025484f }, { 0.176238f, 0.105220f, 0.105227f, 0.100544f } } },
+ { TopFrontRight, { { 0.176240f, 0.156940f, -0.156956f, 0.149960f, 0.006356f, 0.101955f, -0.101970f, -0.000007f, -0.117691f, -0.020700f, 0.018719f, -0.018722f, -0.000003f, -0.038066f, -0.025485f, -0.025485f }, { 0.176240f, 0.105220f, -0.105231f, 0.100541f } } },
+ { TopBackLeft, { { 0.176245f, -0.156957f, 0.156942f, 0.149971f, 0.006355f, -0.101977f, 0.101961f, 0.000003f, -0.117684f, -0.020701f, -0.018724f, 0.018716f, 0.000001f, -0.038069f, 0.025482f, 0.025479f }, { 0.176245f, -0.105232f, 0.105222f, 0.100548f } } },
+ { TopBackRight, { { 0.176238f, -0.156944f, -0.156942f, 0.149972f, 0.006363f, -0.101976f, -0.101964f, -0.000005f, 0.117687f, -0.020701f, -0.018726f, -0.018716f, 0.000000f, 0.038072f, 0.025486f, -0.025481f }, { 0.176238f, -0.105224f, -0.105222f, 0.100549f } } },
+ { BottomFrontLeft, { { 0.176248f, 0.156943f, 0.156950f, -0.149981f, 0.006371f, -0.101969f, -0.101967f, -0.000008f, 0.117685f, 0.020695f, 0.018723f, 0.018718f, 0.000000f, -0.038067f, -0.025486f, 0.025479f }, { 0.176248f, 0.105223f, 0.105227f, -0.100555f } } },
+ { BottomFrontRight, { { 0.176236f, 0.156947f, -0.156945f, -0.149961f, 0.006353f, -0.101971f, 0.101964f, -0.000002f, -0.117689f, 0.020704f, 0.018723f, -0.018718f, -0.000001f, 0.038071f, -0.025484f, -0.025482f }, { 0.176236f, 0.105225f, -0.105224f, -0.100542f } } },
+ { BottomBackLeft, { { 0.176236f, -0.156936f, 0.156952f, -0.149964f, 0.006358f, 0.101962f, -0.101976f, -0.000005f, -0.117687f, 0.020707f, -0.018720f, 0.018725f, 0.000001f, 0.038071f, 0.025483f, 0.025485f }, { 0.176236f, -0.105218f, 0.105229f, -0.100543f } } },
+ { BottomBackRight, { { 0.176256f, -0.156956f, -0.156954f, -0.149974f, 0.006366f, 0.101960f, 0.101964f, 0.000003f, 0.117692f, 0.020690f, -0.018718f, -0.018722f, 0.000001f, -0.038064f, 0.025483f, -0.025484f }, { 0.176256f, -0.105232f, -0.105230f, -0.100550f } } },
};
const ChannelMap *chanmap = NULL;
size_t count = 0;
@@ -329,6 +356,43 @@ ALvoid aluInitPanning(ALCdevice *device)
memset(device->Channel, 0, sizeof(device->Channel));
device->NumChannels = 0;
+ if(device->Hrtf)
+ {
+ static const struct {
+ enum Channel channel;
+ ALfloat elevation;
+ ALfloat angle;
+ } VirtualChans[14] = {
+ { FrontCenter, DEG2RAD( 0.0f), DEG2RAD( 0.0f) },
+ { BackCenter, DEG2RAD( 0.0f), DEG2RAD(-180.0f) },
+ { SideLeft, DEG2RAD( 0.0f), DEG2RAD( -90.0f) },
+ { SideRight, DEG2RAD( 0.0f), DEG2RAD( 90.0f) },
+ { TopFrontLeft, DEG2RAD( 45.0f), DEG2RAD( -45.0f) },
+ { TopFrontRight, DEG2RAD( 45.0f), DEG2RAD( 45.0f) },
+ { TopBackLeft, DEG2RAD( 45.0f), DEG2RAD(-135.0f) },
+ { TopBackRight, DEG2RAD( 45.0f), DEG2RAD( 135.0f) },
+ { BottomFrontLeft, DEG2RAD(-45.0f), DEG2RAD( -45.0f) },
+ { BottomFrontRight, DEG2RAD(-45.0f), DEG2RAD( 45.0f) },
+ { BottomBackLeft, DEG2RAD(-45.0f), DEG2RAD(-135.0f) },
+ { BottomBackRight, DEG2RAD(-45.0f), DEG2RAD( 135.0f) },
+ { TopCenter, DEG2RAD( 90.0f), DEG2RAD( 0.0f) },
+ { BottomCenter, DEG2RAD(-90.0f), DEG2RAD( 0.0f) },
+ };
+ ALuint i;
+
+ count = COUNTOF(CubeDiamond);
+ chanmap = CubeDiamond;
+
+ for(i = 0;i < count;i++)
+ device->ChannelName[i] = VirtualChans[i].channel;
+ SetChannelMap(device, chanmap, count);
+ for(i = 0;i < count;i++)
+ GetLerpedHrtfCoeffs(device->Hrtf, VirtualChans[i].elevation, VirtualChans[i].angle,
+ device->Hrtf_Params[i].Coeffs, device->Hrtf_Params[i].Delay);
+
+ return;
+ }
+
if(LoadChannelSetup(device))
return;
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 083d2613..bcb278dd 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -37,6 +37,8 @@
#include "vector.h"
#include "alstring.h"
+#include "hrtf.h"
+
#ifndef ALC_SOFT_HRTF
#define ALC_SOFT_HRTF 1
#define ALC_HRTF_SOFT 0x1992
@@ -528,6 +530,17 @@ enum Channel {
SideLeft,
SideRight,
+ TopCenter,
+ BottomCenter,
+ TopFrontLeft,
+ TopFrontRight,
+ TopBackLeft,
+ TopBackRight,
+ BottomFrontLeft,
+ BottomFrontRight,
+ BottomBackLeft,
+ BottomBackRight,
+
InvalidChannel
};
@@ -557,7 +570,7 @@ enum DevFmtChannels {
DevFmtChannelsDefault = DevFmtStereo
};
-#define MAX_OUTPUT_CHANNELS (8)
+#define MAX_OUTPUT_CHANNELS (14)
ALuint BytesFromDevFmt(enum DevFmtType type) DECL_CONST;
ALuint ChannelsFromDevFmt(enum DevFmtChannels chans) DECL_CONST;
@@ -593,6 +606,21 @@ typedef struct ChannelConfig {
} ChannelConfig;
+#define HRTF_HISTORY_BITS (6)
+#define HRTF_HISTORY_LENGTH (1<<HRTF_HISTORY_BITS)
+#define HRTF_HISTORY_MASK (HRTF_HISTORY_LENGTH-1)
+
+typedef struct HrtfState {
+ alignas(16) ALfloat History[HRTF_HISTORY_LENGTH];
+ alignas(16) ALfloat Values[HRIR_LENGTH][2];
+} HrtfState;
+
+typedef struct HrtfParams {
+ alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
+ ALuint Delay[2];
+} HrtfParams;
+
+
/* Size for temporary storage of buffer data, in ALfloats. Larger values need
* more memory, while smaller values may need more iterations. The value needs
* to be a sensible size, however, as it constrains the max stepping value used
@@ -652,6 +680,9 @@ struct ALCdevice_struct
/* HRTF filter tables */
const struct Hrtf *Hrtf;
+ HrtfState Hrtf_State[MAX_OUTPUT_CHANNELS];
+ HrtfParams Hrtf_Params[MAX_OUTPUT_CHANNELS];
+ ALuint Hrtf_Offset;
// Stereo-to-binaural filter
struct bs2b *Bs2b;
diff --git a/OpenAL32/Include/alu.h b/OpenAL32/Include/alu.h
index 6e414633..69452e72 100644
--- a/OpenAL32/Include/alu.h
+++ b/OpenAL32/Include/alu.h
@@ -30,10 +30,6 @@
#define RAD2DEG(x) ((ALfloat)(x) * (180.0f/F_PI))
-#define SRC_HISTORY_BITS (6)
-#define SRC_HISTORY_LENGTH (1<<SRC_HISTORY_BITS)
-#define SRC_HISTORY_MASK (SRC_HISTORY_LENGTH-1)
-
#define MAX_PITCH (10)
@@ -53,19 +49,6 @@ enum ActiveFilters {
};
-typedef struct HrtfState {
- alignas(16) ALfloat History[SRC_HISTORY_LENGTH];
- alignas(16) ALfloat Values[HRIR_LENGTH][2];
-} HrtfState;
-
-typedef struct HrtfParams {
- alignas(16) ALfloat Coeffs[HRIR_LENGTH][2];
- alignas(16) ALfloat CoeffStep[HRIR_LENGTH][2];
- ALuint Delay[2];
- ALint DelayStep[2];
-} HrtfParams;
-
-
typedef struct MixGains {
ALfloat Current;
ALfloat Step;
@@ -88,14 +71,6 @@ typedef struct DirectParams {
} Filters[MAX_INPUT_CHANNELS];
union {
- struct {
- HrtfParams Params[MAX_INPUT_CHANNELS];
- HrtfState State[MAX_INPUT_CHANNELS];
- ALuint IrSize;
- ALfloat Gain;
- ALfloat Dir[3];
- } Hrtf;
-
MixGains Gains[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
} Mix;
} DirectParams;
@@ -125,8 +100,7 @@ typedef void (*MixerFunc)(const ALfloat *data, ALuint OutChans,
ALfloat (*restrict OutBuffer)[BUFFERSIZE], struct MixGains *Gains,
ALuint Counter, ALuint OutPos, ALuint BufferSize);
typedef void (*HrtfMixerFunc)(ALfloat (*restrict OutBuffer)[BUFFERSIZE], const ALfloat *data,
- ALuint Counter, ALuint Offset, ALuint OutPos,
- const ALuint IrSize, const HrtfParams *hrtfparams,
+ ALuint Offset, const ALuint IrSize, const HrtfParams *hrtfparams,
HrtfState *hrtfstate, ALuint BufferSize);
diff --git a/OpenAL32/alSource.c b/OpenAL32/alSource.c
index a716eb74..12bd9436 100644
--- a/OpenAL32/alSource.c
+++ b/OpenAL32/alSource.c
@@ -2597,23 +2597,12 @@ ALvoid SetSourceState(ALsource *Source, ALCcontext *Context, ALenum state)
voice->Source = Source;
}
- voice->Direct.Moving = AL_FALSE;
+ voice->Direct.Moving = AL_FALSE;
voice->Direct.Counter = 0;
- for(i = 0;i < MAX_INPUT_CHANNELS;i++)
- {
- ALsizei j;
- for(j = 0;j < SRC_HISTORY_LENGTH;j++)
- voice->Direct.Mix.Hrtf.State[i].History[j] = 0.0f;
- for(j = 0;j < HRIR_LENGTH;j++)
- {
- voice->Direct.Mix.Hrtf.State[i].Values[j][0] = 0.0f;
- voice->Direct.Mix.Hrtf.State[i].Values[j][1] = 0.0f;
- }
- }
for(i = 0;i < (ALsizei)device->NumAuxSends;i++)
{
- voice->Send[i].Counter = 0;
voice->Send[i].Moving = AL_FALSE;
+ voice->Send[i].Counter = 0;
}
if(BufferList->buffer->FmtChannels == FmtMono)