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.
This commit is contained in:
parent
3ed79cc229
commit
a6e574ba9e
88
Alc/hrtf.c
88
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;
|
||||
|
||||
for(i = 0;i < Hrtf->irSize;i++)
|
||||
assert(num_chans <= MAX_AMBI_COEFFS);
|
||||
|
||||
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 */
|
||||
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) */
|
||||
|
||||
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++)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user