aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
Diffstat (limited to 'Alc')
-rw-r--r--Alc/ALu.c8
-rw-r--r--Alc/hrtf.c84
-rw-r--r--Alc/hrtf.h1
-rw-r--r--Alc/panning.c37
4 files changed, 97 insertions, 33 deletions
diff --git a/Alc/ALu.c b/Alc/ALu.c
index 2e94ad63..33a9c410 100644
--- a/Alc/ALu.c
+++ b/Alc/ALu.c
@@ -98,10 +98,10 @@ extern inline void aluMatrixSet(aluMatrix *restrict matrix, ALfloat m00, ALfloat
* output mixing format, and the DryBuffer is then converted and written to the
* backend's audio buffer.
*
- * With HRTF, these fields correspond to a virtual format (typically 8-channel
- * cube), and the actual output is stored in DryBuffer[NumChannels] for the
- * left channel and DryBuffer[NumChannels+1] for the right. As a final output
- * step, the virtual channels will have HRTF applied and written to the actual
+ * With HRTF, these fields correspond to a virtual format (typically B-Format),
+ * and the actual output is stored in DryBuffer[NumChannels] for the left
+ * channel and DryBuffer[NumChannels+1] for the right. As a final output step,
+ * the virtual channels will have HRTF applied and written to the actual
* output. Things like effects and B-Format decoding will want to write to the
* virtual channels so that they can be mixed with HRTF in full 3D.
*
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index 54e16cc7..98bcefc2 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -82,7 +82,7 @@ static void CalcEvIndices(ALuint evcount, ALfloat ev, ALuint *evidx, ALfloat *ev
*/
static void CalcAzIndices(ALuint azcount, ALfloat az, ALuint *azidx, ALfloat *azmu)
{
- az = (F_2PI + az) * azcount / (F_2PI);
+ az = (F_2PI + az) * azcount / F_2PI;
azidx[0] = fastf2u(az) % azcount;
azidx[1] = (azidx[0] + 1) % azcount;
*azmu = az - floorf(az);
@@ -312,6 +312,88 @@ ALuint GetMovingHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat a
}
+/* Calculates HRTF coefficients for a B-Format channel (first order only). */
+void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALfloat ambi_coeffs[4], ALfloat (*coeffs)[2], ALuint *delays)
+{
+ ALuint elev_idx, azi_idx;
+ ALfloat scale;
+ ALuint i;
+
+ for(i = 0;i < Hrtf->irSize;i++)
+ {
+ coeffs[i][0] = 0.0f;
+ coeffs[i][1] = 0.0f;
+ }
+ delays[0] = 0;
+ delays[1] = 0;
+
+ /* NOTE: HRTF coefficients are generated by combining all the HRIRs in the
+ * dataset, with each entry scaled according to how much it contributes to
+ * the given B-Format channel based on its direction (including negative
+ * contributions!).
+ */
+ scale = 0.0f;
+ for(elev_idx = 0;elev_idx < Hrtf->evCount;elev_idx++)
+ {
+ ALfloat elev = (ALfloat)elev_idx/(ALfloat)(Hrtf->evCount-1)*F_PI - F_PI_2;
+ ALuint evoffset = Hrtf->evOffset[elev_idx];
+ ALuint azcount = Hrtf->azCount[elev_idx];
+
+ scale += (ALfloat)azcount;
+
+ for(azi_idx = 0;azi_idx < azcount;azi_idx++)
+ {
+ ALuint lidx, ridx;
+ ALfloat az;
+ ALfloat x, y, z;
+ ALfloat gain;
+
+ lidx = evoffset + azi_idx;
+ ridx = evoffset + ((azcount-azi_idx) % azcount);
+
+ /* NOTE: Always include the total delay average since the channels
+ * need to have matching delays. */
+ delays[0] += Hrtf->delays[lidx];
+ delays[1] += Hrtf->delays[ridx];
+
+ az = (ALfloat)azi_idx / (ALfloat)azcount * F_2PI;
+ if(az > F_PI) az -= F_2PI;
+
+ x = cosf(az) * cosf(elev);
+ y = -sinf(az) * cosf(elev);
+ z = sinf(elev);
+
+ gain = 0.0f;
+ gain += ambi_coeffs[0]*0.7071f; /* sqrt(1.0 / 2.0) */
+ gain += ambi_coeffs[1]*x; /* X */
+ gain += ambi_coeffs[2]*y; /* Y */
+ gain += ambi_coeffs[3]*z; /* Z */
+
+ if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
+ continue;
+
+ lidx *= Hrtf->irSize;
+ ridx *= Hrtf->irSize;
+ for(i = 0;i < Hrtf->irSize;i++)
+ {
+ coeffs[i][0] += Hrtf->coeffs[lidx + i]*(1.0f/32767.0f) * gain;
+ coeffs[i][1] += Hrtf->coeffs[ridx + i]*(1.0f/32767.0f) * gain;
+ }
+ }
+ }
+
+ scale = 1.0f/scale;
+
+ delays[0] = minu((ALuint)((ALfloat)delays[0] * scale), HRTF_HISTORY_LENGTH-1)<<HRTFDELAY_BITS;
+ delays[1] = minu((ALuint)((ALfloat)delays[1] * scale), HRTF_HISTORY_LENGTH-1)<<HRTFDELAY_BITS;
+ for(i = 0;i < Hrtf->irSize;i++)
+ {
+ coeffs[i][0] *= scale;
+ coeffs[i][1] *= scale;
+ }
+}
+
+
static struct Hrtf *LoadHrtf00(FILE *f, ALuint deviceRate)
{
const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1;
diff --git a/Alc/hrtf.h b/Alc/hrtf.h
index 3eaa4e28..122a4c58 100644
--- a/Alc/hrtf.h
+++ b/Alc/hrtf.h
@@ -23,5 +23,6 @@ void FreeHrtfs(void);
ALuint GetHrtfIrSize(const struct Hrtf *Hrtf);
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 GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALfloat ambi_coeffs[4], ALfloat (*coeffs)[2], ALuint *delays);
#endif /* ALC_HRTF_H */
diff --git a/Alc/panning.c b/Alc/panning.c
index 4a3541c2..b7b8a0c7 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -339,15 +339,6 @@ 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 } } },
- }, Cube8[8] = {
- { TopFrontLeft, { { 0.176777f, 0.125000f, 0.125000f, 0.125000f }, { 0.176777f, 0.125000f, 0.125000f, 0.125000f } } },
- { TopFrontRight, { { 0.176777f, 0.125000f, -0.125000f, 0.125000f }, { 0.176777f, 0.125000f, -0.125000f, 0.125000f } } },
- { TopBackLeft, { { 0.176777f, -0.125000f, 0.125000f, 0.125000f }, { 0.176777f, -0.125000f, 0.125000f, 0.125000f } } },
- { TopBackRight, { { 0.176777f, -0.125000f, -0.125000f, 0.125000f }, { 0.176777f, -0.125000f, -0.125000f, 0.125000f } } },
- { BottomFrontLeft, { { 0.176777f, 0.125000f, 0.125000f, -0.125000f }, { 0.176777f, 0.125000f, 0.125000f, -0.125000f } } },
- { BottomFrontRight, { { 0.176777f, 0.125000f, -0.125000f, -0.125000f }, { 0.176777f, 0.125000f, -0.125000f, -0.125000f } } },
- { BottomBackLeft, { { 0.176777f, -0.125000f, 0.125000f, -0.125000f }, { 0.176777f, -0.125000f, 0.125000f, -0.125000f } } },
- { BottomBackRight, { { 0.176777f, -0.125000f, -0.125000f, -0.125000f }, { 0.176777f, -0.125000f, -0.125000f, -0.125000f } } },
}, BFormat3D[4] = {
{ Aux0, { { 1.0f, 0.0f, 0.0f, 0.0f }, { 1.0f, 0.0f, 0.0f, 0.0f } } },
{ Aux1, { { 0.0f, 1.0f, 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f, 0.0f } } },
@@ -362,33 +353,23 @@ ALvoid aluInitPanning(ALCdevice *device)
if(device->Hrtf)
{
- static const struct {
- enum Channel channel;
- ALfloat elevation;
- ALfloat angle;
- } VirtualChans[8] = {
- { 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) },
- };
ALuint i;
- count = COUNTOF(Cube8);
- chanmap = Cube8;
+ count = COUNTOF(BFormat3D);
+ chanmap = BFormat3D;
for(i = 0;i < count;i++)
- device->ChannelName[i] = VirtualChans[i].channel;
+ device->ChannelName[i] = chanmap[i].ChanName;
+ for(;i < MAX_OUTPUT_CHANNELS;i++)
+ device->ChannelName[i] = InvalidChannel;
+
SetChannelMap(device, chanmap, count);
for(i = 0;i < count;i++)
- GetLerpedHrtfCoeffs(
- device->Hrtf, VirtualChans[i].elevation, VirtualChans[i].angle, 1.0f, 1.0f,
+ {
+ GetBFormatHrtfCoeffs(device->Hrtf, chanmap[i].Config.FOACoeff,
device->Hrtf_Params[i].Coeffs, device->Hrtf_Params[i].Delay
);
+ }
return;
}