diff options
-rw-r--r-- | Alc/ALu.c | 2 | ||||
-rw-r--r-- | Alc/hrtf.c | 76 | ||||
-rw-r--r-- | Alc/hrtf.h | 7 | ||||
-rw-r--r-- | Alc/panning.c | 61 | ||||
-rw-r--r-- | OpenAL32/Include/alMain.h | 5 |
5 files changed, 109 insertions, 42 deletions
@@ -1505,7 +1505,7 @@ ALvoid aluMixData(ALCdevice *device, ALvoid *buffer, ALsizei size) if(lidx != -1 && ridx != -1) { HrtfMixerFunc HrtfMix = SelectHrtfMixer(); - ALuint irsize = device->Hrtf->irSize; + ALuint irsize = device->Hrtf_IrSize; MixHrtfParams hrtfparams; memset(&hrtfparams, 0, sizeof(hrtfparams)); for(c = 0;c < device->Dry.NumChannels;c++) @@ -172,6 +172,82 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi } +ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][2], ALuint NumChannels) +{ + ALuint total_hrirs = 0; + ALuint max_length = 0; + ALuint eidx, aidx, i, j; + ALfloat scale; + + assert(NumChannels == 4); + + for(eidx = 0;eidx < Hrtf->evCount;++eidx) + { + const ALfloat elev = (ALfloat)eidx/(ALfloat)(Hrtf->evCount-1)*F_PI - F_PI_2; + const ALuint evoffset = Hrtf->evOffset[eidx]; + const ALuint azcount = Hrtf->azCount[eidx]; + + for(aidx = 0;aidx < azcount;++aidx) + { + ALfloat ambcoeffs[4]; + const ALshort *fir; + ALuint length, delay; + ALuint lidx, ridx; + ALfloat x, y, z; + ALfloat azi; + + lidx = evoffset + aidx; + ridx = evoffset + ((azcount - aidx) % azcount); + + azi = (ALfloat)aidx/(ALfloat)azcount * -F_TAU; + x = cosf(azi) * cosf(elev); + y = sinf(azi) * cosf(elev); + z = sinf(elev); + + ambcoeffs[0] = 1.0f; + ambcoeffs[1] = y / 1.732050808f; + ambcoeffs[2] = z / 1.732050808f; + ambcoeffs[3] = x / 1.732050808f; + + /* Apply left ear response */ + delay = Hrtf->delays[lidx]; + fir = &Hrtf->coeffs[lidx * Hrtf->irSize]; + length = minu(delay + Hrtf->irSize, HRIR_LENGTH); + for(i = 0;i < NumChannels;++i) + { + for(j = delay;j < length;++j) + coeffs[i][j][0] += fir[j-delay]/32767.0f * ambcoeffs[i]; + } + max_length = maxu(max_length, length); + + /* Apply right ear response */ + delay = Hrtf->delays[ridx]; + fir = &Hrtf->coeffs[ridx * Hrtf->irSize]; + length = minu(delay + Hrtf->irSize, HRIR_LENGTH); + for(i = 0;i < NumChannels;++i) + { + for(j = delay;j < length;++j) + coeffs[i][j][1] += fir[j-delay]/32767.0f * ambcoeffs[i]; + } + max_length = maxu(max_length, length); + + total_hrirs++; + } + } + + scale = (ALfloat)total_hrirs; + for(i = 0;i < NumChannels;++i) + { + for(j = 0;j < max_length;++j) + { + coeffs[i][j][0] /= scale; + coeffs[i][j][1] /= scale; + } + } + return max_length; +} + + static struct Hrtf *LoadHrtf00(FILE *f, const_al_string filename) { const ALubyte maxDelay = HRTF_HISTORY_LENGTH-1; @@ -42,4 +42,11 @@ void FreeHrtfList(vector_HrtfEntry *list); void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azimuth, ALfloat spread, ALfloat gain, ALfloat (*coeffs)[2], ALuint *delays); +/* Produces HRTF filter coefficients for decoding B-Format. The result will + * have ACN ordering with N3D normalization. NumChannels must currently be 4, + * for first-order. Returns the maximum impulse-response length of the + * generated coefficients. + */ +ALuint BuildBFormatHrtf(const struct Hrtf *Hrtf, ALfloat (*coeffs)[HRIR_LENGTH][2], ALuint NumChannels); + #endif /* ALC_HRTF_H */ diff --git a/Alc/panning.c b/Alc/panning.c index 2d7502ec..65506303 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -758,52 +758,35 @@ static void InitHQPanning(ALCdevice *device, const AmbDecConf *conf, const ALuin static void InitHrtfPanning(ALCdevice *device) { - static const enum Channel CubeChannels[MAX_OUTPUT_CHANNELS] = { - UpperFrontLeft, UpperFrontRight, UpperBackLeft, UpperBackRight, - LowerFrontLeft, LowerFrontRight, LowerBackLeft, LowerBackRight, - InvalidChannel, InvalidChannel, InvalidChannel, InvalidChannel, - InvalidChannel, InvalidChannel, InvalidChannel, InvalidChannel - }; - static const ChannelMap Cube8Cfg[8] = { - { UpperFrontLeft, { 0.176776695f, 0.072168784f, 0.072168784f, 0.072168784f } }, - { UpperFrontRight, { 0.176776695f, 0.072168784f, -0.072168784f, 0.072168784f } }, - { UpperBackLeft, { 0.176776695f, -0.072168784f, 0.072168784f, 0.072168784f } }, - { UpperBackRight, { 0.176776695f, -0.072168784f, -0.072168784f, 0.072168784f } }, - { LowerFrontLeft, { 0.176776695f, 0.072168784f, 0.072168784f, -0.072168784f } }, - { LowerFrontRight, { 0.176776695f, 0.072168784f, -0.072168784f, -0.072168784f } }, - { LowerBackLeft, { 0.176776695f, -0.072168784f, 0.072168784f, -0.072168784f } }, - { LowerBackRight, { 0.176776695f, -0.072168784f, -0.072168784f, -0.072168784f } }, - }; - static const struct { - enum Channel Channel; - ALfloat Angle; - ALfloat Elevation; - } CubeInfo[8] = { - { UpperFrontLeft, DEG2RAD( -45.0f), DEG2RAD( 45.0f) }, - { UpperFrontRight, DEG2RAD( 45.0f), DEG2RAD( 45.0f) }, - { UpperBackLeft, DEG2RAD(-135.0f), DEG2RAD( 45.0f) }, - { UpperBackRight, DEG2RAD( 135.0f), DEG2RAD( 45.0f) }, - { LowerFrontLeft, DEG2RAD( -45.0f), DEG2RAD(-45.0f) }, - { LowerFrontRight, DEG2RAD( 45.0f), DEG2RAD(-45.0f) }, - { LowerBackLeft, DEG2RAD(-135.0f), DEG2RAD(-45.0f) }, - { LowerBackRight, DEG2RAD( 135.0f), DEG2RAD(-45.0f) }, - }; - const ChannelMap *chanmap = Cube8Cfg; - size_t count = COUNTOF(Cube8Cfg); - ALuint i; + ALfloat hrtf_coeffs[4][HRIR_LENGTH][2]; + size_t count = 4; + ALuint i, j; - SetChannelMap(CubeChannels, device->Dry.Ambi.Coeffs, chanmap, count, - &device->Dry.NumChannels, AL_TRUE); - device->Dry.CoeffCount = 4; + for(i = 0;i < count;i++) + { + device->Dry.Ambi.Map[i].Scale = 1.0f; + device->Dry.Ambi.Map[i].Index = i; + } + device->Dry.CoeffCount = 0; + device->Dry.NumChannels = count; device->FOAOut.Ambi = device->Dry.Ambi; device->FOAOut.CoeffCount = device->Dry.CoeffCount; + memset(hrtf_coeffs, 0, sizeof(hrtf_coeffs)); + device->Hrtf_IrSize = BuildBFormatHrtf(device->Hrtf, hrtf_coeffs, device->Dry.NumChannels); + + /* Round up to the nearest multiple of 8 */ + device->Hrtf_IrSize = (device->Hrtf_IrSize+7)&~7; for(i = 0;i < device->Dry.NumChannels;i++) { - int chan = GetChannelIndex(CubeChannels, CubeInfo[i].Channel); - GetLerpedHrtfCoeffs(device->Hrtf, CubeInfo[i].Elevation, CubeInfo[i].Angle, 1.0f, 0.0f, - device->Hrtf_Params[chan].Coeffs, device->Hrtf_Params[chan].Delay); + for(j = 0;j < HRIR_LENGTH;j++) + { + device->Hrtf_Params[i].Coeffs[j][0] = hrtf_coeffs[i][j][0]; + device->Hrtf_Params[i].Coeffs[j][1] = hrtf_coeffs[i][j][1]; + } + device->Hrtf_Params[i].Delay[0] = 0; + device->Hrtf_Params[i].Delay[1] = 0; } } diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h index 3b6113ef..3d099ca2 100644 --- a/OpenAL32/Include/alMain.h +++ b/OpenAL32/Include/alMain.h @@ -599,9 +599,10 @@ struct ALCdevice_struct ALCenum Hrtf_Status; /* HRTF filter state for dry buffer content */ - HrtfState Hrtf_State[8]; - HrtfParams Hrtf_Params[8]; + HrtfState Hrtf_State[4]; + HrtfParams Hrtf_Params[4]; ALuint Hrtf_Offset; + ALuint Hrtf_IrSize; /* UHJ encoder state */ struct Uhj2Encoder *Uhj_Encoder; |