From a27e5e16523e1f6f166410e9992fc40886064eca Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Sat, 22 Nov 2014 04:20:17 -0800 Subject: Use a different method for HRTF mixing This new method mixes sources normally into a 14-channel buffer with the channels placed all around the listener. HRTF is then applied to the channels given their positions and written to a 2-channel buffer, which gets written out to the device. This method has the benefit that HRTF processing becomes more scalable. The costly HRTF filters are applied to the 14-channel buffer after the mix is done, turning it into a post-process with a fixed overhead. Mixing sources is done with normal non-HRTF methods, so increasing the number of playing sources only incurs normal mixing costs. Another benefit is that it improves B-Format playback since the soundfield gets mixed into speakers covering all three dimensions, which then get filtered based on their locations. The main downside to this is that the spatial resolution of the HRTF dataset does not play a big role anymore. However, the hope is that with ambisonics- based panning, the perceptual position of panned sounds will still be good. It is also an option to increase the number of virtual channels for systems that can handle it, or maybe even decrease it for weaker systems. --- Alc/ALc.c | 14 ++- Alc/ALu.c | 163 +++++++++++----------------------- Alc/hrtf.c | 222 +++------------------------------------------- Alc/hrtf.h | 4 +- Alc/midi/fluidsynth.c | 8 +- Alc/mixer.c | 25 +----- Alc/mixer_c.c | 17 ---- Alc/mixer_defs.h | 15 ++-- Alc/mixer_inc.c | 54 +++-------- Alc/mixer_neon.c | 32 ------- Alc/mixer_sse.c | 62 ------------- Alc/panning.c | 64 +++++++++++++ OpenAL32/Include/alMain.h | 33 ++++++- OpenAL32/Include/alu.h | 28 +----- OpenAL32/alSource.c | 15 +--- 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<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) -- cgit v1.2.3