diff options
author | Chris Robinson <[email protected]> | 2016-02-20 00:53:01 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2016-02-20 00:53:01 -0800 |
commit | e1ce7f9180d8127397faebf36eb815a5a575d7c8 (patch) | |
tree | de56927ad814a6a41a893cdc5332332bc27aeaf0 /Alc | |
parent | e90cdbcf98662a86326b5b3f84f3b46534d7766e (diff) |
Use an 8-channel cube for HRTF's virtual format.
There were phase issues caused by applying HRTF directly to the B-Format
channels, since the HRIR delays were all averaged which removed the inter-aural
time-delay, which in turn removed significant spatial information.
Diffstat (limited to 'Alc')
-rw-r--r-- | Alc/ALu.c | 14 | ||||
-rw-r--r-- | Alc/hrtf.c | 102 | ||||
-rw-r--r-- | Alc/hrtf.h | 1 | ||||
-rw-r--r-- | Alc/panning.c | 51 |
4 files changed, 46 insertions, 122 deletions
@@ -100,14 +100,14 @@ extern inline void aluMatrixdSet(aluMatrixd *matrix, ALdouble m30, ALdouble m31, ALdouble m32, ALdouble m33); -/* NOTE: HRTF is set up a bit special in the device. By default, the device's - * DryBuffer, NumChannels, ChannelName, and Channel fields correspond to the - * output mixing format, and the DryBuffer is then converted and written to the - * backend's audio buffer. +/* NOTE: HRTF is set up a bit special in the device. By default, without HRTF, + * the device's DryBuffer, NumChannels, ChannelName, and Channel fields + * correspond to the output 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 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, + * With HRTF, these fields correspond to a virtual 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. @@ -181,108 +181,6 @@ void GetLerpedHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat elevation, ALfloat azi } } -/* Calculates HRTF coefficients for B-Format channels (only up to first-order). - * Note that these will decode a B-Format output mix, which uses FuMa ordering - * and scaling, not N3D! - */ -void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat (*coeffs_list[4])[2], ALuint *delay_list[4]) -{ - ALuint elev_idx, azi_idx; - ALfloat scale; - ALuint i, c; - - for(c = 0;c < 4;c++) - { - 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; - } - - /* 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 ambi_coeffs[4]; - ALfloat az, gain; - ALfloat x, y, z; - - lidx = evoffset + azi_idx; - ridx = evoffset + ((azcount-azi_idx) % azcount); - - az = (ALfloat)azi_idx / (ALfloat)azcount * F_TAU; - if(az > F_PI) az -= F_TAU; - - x = cosf(-az) * cosf(elev); - y = sinf(-az) * cosf(elev); - z = sinf(elev); - - ambi_coeffs[0] = 1.414213562f; - ambi_coeffs[1] = x; - ambi_coeffs[2] = y; - ambi_coeffs[3] = z; - - for(c = 0;c < 4;c++) - { - 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; - - for(c = 0;c < 4;c++) - { - 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; - } -} - static struct Hrtf *LoadHrtf00(FILE *f) { @@ -34,6 +34,5 @@ ALuint GetHrtfSampleRate(const struct Hrtf *Hrtf); 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); -void GetBFormatHrtfCoeffs(const struct Hrtf *Hrtf, ALfloat (*coeffs_list[4])[2], ALuint *delay_list[4]); #endif /* ALC_HRTF_H */ diff --git a/Alc/panning.c b/Alc/panning.c index 5013ec16..9f1e87d7 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -184,6 +184,15 @@ DECL_CONST static inline const char *GetLabelFromChannel(enum Channel channel) case SideLeft: return "side-left"; case SideRight: return "side-right"; + case UpperFrontLeft: return "upper-front-left"; + case UpperFrontRight: return "upper-front-right"; + case UpperBackLeft: return "upper-back-left"; + case UpperBackRight: return "upper-back-right"; + case LowerFrontLeft: return "lower-front-left"; + case LowerFrontRight: return "lower-front-right"; + case LowerBackLeft: return "lower-back-left"; + case LowerBackRight: return "lower-back-right"; + case BFormatW: return "bformat-w"; case BFormatX: return "bformat-x"; case BFormatY: return "bformat-y"; @@ -466,6 +475,15 @@ 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 } }, { SideLeft, { 0.224739f, 0.000000f, 0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065795f } }, { SideRight, { 0.224739f, 0.000000f, -0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000000f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065795f } }, + }, 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 } }, }, BFormat3D[4] = { { BFormatW, { 1.0f, 0.0f, 0.0f, 0.0f } }, { BFormatX, { 0.0f, 1.0f, 0.0f, 0.0f } }, @@ -482,13 +500,25 @@ ALvoid aluInitPanning(ALCdevice *device) if(device->Hrtf) { - ALfloat (*coeffs_list[4])[2]; - ALuint *delay_list[4]; + 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) }, + }; ALuint i; - count = COUNTOF(BFormat3D); - chanmap = BFormat3D; - ambiscale = 1.0f; + count = COUNTOF(Cube8Cfg); + chanmap = Cube8Cfg; + ambiscale = FIRST_ORDER_SCALE; for(i = 0;i < count;i++) device->ChannelName[i] = chanmap[i].ChanName; @@ -498,15 +528,12 @@ ALvoid aluInitPanning(ALCdevice *device) &device->NumChannels, AL_TRUE); device->AmbiScale = ambiscale; - for(i = 0;i < 4;++i) + for(i = 0;i < device->NumChannels;i++) { - static const enum Channel inputs[4] = { BFormatW, BFormatX, BFormatY, BFormatZ }; - int chan = GetChannelIdxByName(device, inputs[i]); - coeffs_list[i] = device->Hrtf_Params[chan].Coeffs; - delay_list[i] = device->Hrtf_Params[chan].Delay; + int chan = GetChannelIdxByName(device, CubeInfo[i].Channel); + GetLerpedHrtfCoeffs(device->Hrtf, CubeInfo[i].Elevation, CubeInfo[i].Angle, 1.0f, 1.0f, + device->Hrtf_Params[chan].Coeffs, device->Hrtf_Params[chan].Delay); } - GetBFormatHrtfCoeffs(device->Hrtf, coeffs_list, delay_list); - return; } |