diff options
Diffstat (limited to 'Alc/hrtf.c')
-rw-r--r-- | Alc/hrtf.c | 90 |
1 files changed, 61 insertions, 29 deletions
@@ -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; } } |