aboutsummaryrefslogtreecommitdiffstats
path: root/Alc
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2015-02-10 11:22:28 -0800
committerChris Robinson <[email protected]>2015-02-10 11:22:28 -0800
commita6e574ba9e1a7dade95b9d4ddf864df5c0724b21 (patch)
treebd75815ca6a1ec7c8d3f6f9d47c3183b1a774ba7 /Alc
parent3ed79cc229affe608e6f672b65a9c56659eeeccc (diff)
Calculate HRTF coefficients for all B-Format channels at once
It's possible to calculate HRTF coefficients for full third-order ambisonics now, but it's still not possible to use them here without upmixing first-order content.
Diffstat (limited to 'Alc')
-rw-r--r--Alc/hrtf.c90
-rw-r--r--Alc/hrtf.h2
-rw-r--r--Alc/panning.c14
3 files changed, 72 insertions, 34 deletions
diff --git a/Alc/hrtf.c b/Alc/hrtf.c
index e9b666c6..c707b819 100644
--- a/Alc/hrtf.c
+++ b/Alc/hrtf.c
@@ -312,20 +312,28 @@ 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 ALuint chan_num, ALfloat (*coeffs)[2], ALuint *delays)
+/* Calculates HRTF coefficients for B-Format channels. */
+void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALuint num_chans, ALfloat (**coeffs_list)[2], ALuint **delay_list)
{
ALuint elev_idx, azi_idx;
ALfloat scale;
- ALuint i;
+ ALuint i, c;
+
+ assert(num_chans <= MAX_AMBI_COEFFS);
- for(i = 0;i < Hrtf->irSize;i++)
+ for(c = 0;c < num_chans;c++)
{
- coeffs[i][0] = 0.0f;
- coeffs[i][1] = 0.0f;
+ ALfloat (*coeffs)[2] = coeffs_list[c];
+ ALuint *delay = delay_list[c];
+
+ for(i = 0;i < Hrtf->irSize;i++)
+ {
+ coeffs[i][0] = 0.0f;
+ coeffs[i][1] = 0.0f;
+ }
+ delay[0] = 0;
+ delay[1] = 0;
}
- 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
@@ -345,18 +353,13 @@ void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALuint chan_num, ALfloa
{
ALuint lidx, ridx;
ALfloat az;
- ALfloat ambi_coeffs[4];
+ ALfloat ambi_coeffs[MAX_AMBI_COEFFS];
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;
@@ -368,29 +371,58 @@ void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALuint chan_num, ALfloa
ambi_coeffs[1] = x; /* X */
ambi_coeffs[2] = y; /* Y */
ambi_coeffs[3] = z; /* Z */
-
- gain = ambi_coeffs[chan_num];
- if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
- continue;
-
- lidx *= Hrtf->irSize;
- ridx *= Hrtf->irSize;
- for(i = 0;i < Hrtf->irSize;i++)
+ ambi_coeffs[4] = 0.5f * (3.0f*z*z - 1.0f); /* 0.5 * (3*Z*Z - 1) */
+ ambi_coeffs[5] = 2.0f * z * x; /* 2*Z*X */
+ ambi_coeffs[6] = 2.0f * y * z; /* 2*Y*Z */
+ ambi_coeffs[7] = x*x - y*y; /* X*X - Y*Y */
+ ambi_coeffs[8] = 2.0f * x * y; /* 2*X*Y */
+ ambi_coeffs[9] = 0.5f * z * (5.0f*z*z - 3.0f); /* 0.5 * Z * (5*Z*Z - 3) */
+ ambi_coeffs[10] = 0.7262f * x * (5.0f*z*z - 1.0f); /* sqrt(135.0 / 256.0) * X * (5*Z*Z - 1) */
+ ambi_coeffs[11] = 0.7262f * y * (5.0f*z*z - 1.0f); /* sqrt(135.0 / 256.0) * Y * (5*Z*Z - 1) */
+ ambi_coeffs[12] = 2.5981f * z * (x*x - y*y); /* sqrt(27.0 / 4.0) * Z * (X*X - Y*Y) */
+ ambi_coeffs[13] = 5.1962f * x * y * z; /* sqrt(27) * X * Y * Z */
+ ambi_coeffs[14] = x * (x*x - 3.0f*y*y); /* X * (X*X - 3*Y*Y) */
+ ambi_coeffs[15] = y * (3.0f*x*x - y*y); /* Y * (3*X*X - Y*Y) */
+
+ for(c = 0;c < num_chans;c++)
{
- coeffs[i][0] += Hrtf->coeffs[lidx + i]*(1.0f/32767.0f) * gain;
- coeffs[i][1] += Hrtf->coeffs[ridx + i]*(1.0f/32767.0f) * gain;
+ ALfloat (*coeffs)[2] = coeffs_list[c];
+ ALuint *delay = delay_list[c];
+
+ /* NOTE: Always include the total delay average since the
+ * channels need to have matching delays. */
+ delay[0] += Hrtf->delays[lidx];
+ delay[1] += Hrtf->delays[ridx];
+
+ gain = ambi_coeffs[c];
+ if(!(fabsf(gain) > GAIN_SILENCE_THRESHOLD))
+ continue;
+
+ for(i = 0;i < Hrtf->irSize;i++)
+ {
+ coeffs[i][0] += Hrtf->coeffs[lidx*Hrtf->irSize + i]*(1.0f/32767.0f) * gain;
+ coeffs[i][1] += Hrtf->coeffs[ridx*Hrtf->irSize + 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++)
+ for(c = 0;c < num_chans;c++)
{
- coeffs[i][0] *= scale;
- coeffs[i][1] *= scale;
+ ALfloat (*coeffs)[2] = coeffs_list[c];
+ ALuint *delay = delay_list[c];
+
+ for(i = 0;i < Hrtf->irSize;i++)
+ {
+ coeffs[i][0] *= scale;
+ coeffs[i][1] *= scale;
+ }
+ delay[0] = minu((ALuint)((ALfloat)delay[0] * scale), HRTF_HISTORY_LENGTH-1);
+ delay[0] <<= HRTFDELAY_BITS;
+ delay[1] = minu((ALuint)((ALfloat)delay[1] * scale), HRTF_HISTORY_LENGTH-1);
+ delay[1] <<= HRTFDELAY_BITS;
}
}
diff --git a/Alc/hrtf.h b/Alc/hrtf.h
index 3d5b8ab6..ba72e45e 100644
--- a/Alc/hrtf.h
+++ b/Alc/hrtf.h
@@ -23,6 +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 ALuint chan_num, ALfloat (*coeffs)[2], ALuint *delays);
+void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, const ALuint num_chans, ALfloat (**coeffs_list)[2], ALuint **delay_list);
#endif /* ALC_HRTF_H */
diff --git a/Alc/panning.c b/Alc/panning.c
index 9b1721cf..151ffe89 100644
--- a/Alc/panning.c
+++ b/Alc/panning.c
@@ -362,12 +362,18 @@ ALvoid aluInitPanning(ALCdevice *device)
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++)
+
{
- GetBFormatHrtfCoeffs(device->Hrtf, i, device->Hrtf_Params[i].Coeffs,
- device->Hrtf_Params[i].Delay);
+ ALfloat (*coeffs_list[4])[2] = {
+ device->Hrtf_Params[0].Coeffs, device->Hrtf_Params[1].Coeffs,
+ device->Hrtf_Params[2].Coeffs, device->Hrtf_Params[3].Coeffs
+ };
+ ALuint *delay_list[4] = {
+ device->Hrtf_Params[0].Delay, device->Hrtf_Params[1].Delay,
+ device->Hrtf_Params[2].Delay, device->Hrtf_Params[3].Delay
+ };
+ GetBFormatHrtfCoeffs(device->Hrtf, 4, coeffs_list, delay_list);
}
return;