diff options
author | Chris Robinson <[email protected]> | 2014-11-22 04:20:17 -0800 |
---|---|---|
committer | Chris Robinson <[email protected]> | 2014-11-22 04:20:17 -0800 |
commit | a27e5e16523e1f6f166410e9992fc40886064eca (patch) | |
tree | a53e47af1b8afb1afa6c497247c9c462889d9067 /Alc/panning.c | |
parent | 38383671d7d2a4f143f0ac84b48e8a02b91a1ba2 (diff) |
Use a different method for HRTF mixing
This new method mixes sources normally into a 14-channel buffer with the
channels placed all around the listener. HRTF is then applied to the channels
given their positions and written to a 2-channel buffer, which gets written out
to the device.
This method has the benefit that HRTF processing becomes more scalable. The
costly HRTF filters are applied to the 14-channel buffer after the mix is done,
turning it into a post-process with a fixed overhead. Mixing sources is done
with normal non-HRTF methods, so increasing the number of playing sources only
incurs normal mixing costs.
Another benefit is that it improves B-Format playback since the soundfield gets
mixed into speakers covering all three dimensions, which then get filtered
based on their locations.
The main downside to this is that the spatial resolution of the HRTF dataset
does not play a big role anymore. However, the hope is that with ambisonics-
based panning, the perceptual position of panned sounds will still be good. It
is also an option to increase the number of virtual channels for systems that
can handle it, or maybe even decrease it for weaker systems.
Diffstat (limited to 'Alc/panning.c')
-rw-r--r-- | Alc/panning.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/Alc/panning.c b/Alc/panning.c index f3305233..64be6f4b 100644 --- a/Alc/panning.c +++ b/Alc/panning.c @@ -124,6 +124,18 @@ DECL_CONST static inline const char *GetLabelFromChannel(enum Channel channel) case BackCenter: return "back-center"; case SideLeft: return "side-left"; case SideRight: return "side-right"; + + case TopCenter: return "top-center"; + case BottomCenter: return "bottom-center"; + case TopFrontLeft: return "top-front-left"; + case TopFrontRight: return "top-front-right"; + case TopBackLeft: return "top-back-left"; + case TopBackRight: return "top-back-right"; + case BottomFrontLeft: return "bottom-front-left"; + case BottomFrontRight: return "bottom-front-right"; + case BottomBackLeft: return "bottom-back-left"; + case BottomBackRight: return "bottom-back-right"; + case InvalidChannel: break; } return "(unknown)"; @@ -322,6 +334,21 @@ 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 }, { 0.224752f, -0.225790f, -0.130361f, 0.0f } } }, { SideLeft, { { 0.224739f, 0.000002f, 0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, 0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, -0.065795f }, { 0.224739f, 0.000000f, 0.260717f, 0.0f } } }, { SideRight, { { 0.224739f, 0.000002f, -0.340644f, 0.0f, 0.0f, 0.0f, 0.0f, -0.210697f, -0.000002f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000f, 0.065795f }, { 0.224739f, 0.000000f, -0.260717f, 0.0f } } }, + }, CubeDiamond[14] = { + { SideLeft, { { 0.130137f, -0.000013f, 0.207620f, 0.000001f, -0.081895f, 0.000001f, 0.000002f, -0.144357f, -0.000015f, -0.000002f, 0.000001f, -0.032339f, -0.000000f, 0.000001f, 0.000005f, -0.057583f }, { 0.130137f, -0.000009f, 0.139199f, 0.000001f } } }, + { FrontCenter, { { 0.130131f, 0.207613f, -0.000007f, 0.000001f, -0.081898f, 0.000001f, -0.000000f, 0.144354f, -0.000010f, -0.000002f, -0.032343f, 0.000006f, -0.000000f, -0.000001f, 0.057583f, -0.000004f }, { 0.130131f, 0.139195f, -0.000005f, 0.000001f } } }, + { SideRight, { { 0.130140f, 0.000001f, -0.207624f, -0.000001f, -0.081900f, 0.000005f, 0.000001f, -0.144357f, -0.000002f, 0.000002f, -0.000004f, 0.032342f, -0.000000f, -0.000005f, -0.000002f, 0.057580f }, { 0.130140f, 0.000000f, -0.139202f, -0.000000f } } }, + { BackCenter, { { 0.130142f, -0.207624f, 0.000006f, -0.000010f, -0.081897f, 0.000011f, 0.000005f, 0.144354f, -0.000006f, 0.000004f, 0.032340f, 0.000000f, -0.000002f, -0.000005f, -0.057579f, 0.000003f }, { 0.130142f, -0.139202f, 0.000004f, -0.000007f } } }, + { TopCenter, { { 0.072579f, 0.000006f, 0.000001f, 0.123524f, 0.126630f, 0.000008f, 0.000001f, -0.000002f, 0.000001f, 0.070290f, 0.000005f, 0.000001f, -0.000002f, 0.000001f, -0.000001f, 0.000002f }, { 0.072579f, 0.000004f, 0.000001f, 0.082817f } } }, + { BottomCenter, { { 0.072577f, -0.000008f, -0.000004f, -0.123522f, 0.126628f, 0.000012f, 0.000005f, -0.000001f, 0.000002f, -0.070291f, -0.000008f, -0.000002f, 0.000001f, -0.000002f, 0.000000f, -0.000001f }, { 0.072577f, -0.000006f, -0.000003f, -0.082815f } } }, + { TopFrontLeft, { { 0.176238f, 0.156939f, 0.156950f, 0.149964f, 0.006362f, 0.101960f, 0.101968f, -0.000003f, 0.117690f, -0.020696f, 0.018718f, 0.018723f, 0.000002f, 0.038069f, -0.025485f, 0.025484f }, { 0.176238f, 0.105220f, 0.105227f, 0.100544f } } }, + { TopFrontRight, { { 0.176240f, 0.156940f, -0.156956f, 0.149960f, 0.006356f, 0.101955f, -0.101970f, -0.000007f, -0.117691f, -0.020700f, 0.018719f, -0.018722f, -0.000003f, -0.038066f, -0.025485f, -0.025485f }, { 0.176240f, 0.105220f, -0.105231f, 0.100541f } } }, + { TopBackLeft, { { 0.176245f, -0.156957f, 0.156942f, 0.149971f, 0.006355f, -0.101977f, 0.101961f, 0.000003f, -0.117684f, -0.020701f, -0.018724f, 0.018716f, 0.000001f, -0.038069f, 0.025482f, 0.025479f }, { 0.176245f, -0.105232f, 0.105222f, 0.100548f } } }, + { TopBackRight, { { 0.176238f, -0.156944f, -0.156942f, 0.149972f, 0.006363f, -0.101976f, -0.101964f, -0.000005f, 0.117687f, -0.020701f, -0.018726f, -0.018716f, 0.000000f, 0.038072f, 0.025486f, -0.025481f }, { 0.176238f, -0.105224f, -0.105222f, 0.100549f } } }, + { BottomFrontLeft, { { 0.176248f, 0.156943f, 0.156950f, -0.149981f, 0.006371f, -0.101969f, -0.101967f, -0.000008f, 0.117685f, 0.020695f, 0.018723f, 0.018718f, 0.000000f, -0.038067f, -0.025486f, 0.025479f }, { 0.176248f, 0.105223f, 0.105227f, -0.100555f } } }, + { BottomFrontRight, { { 0.176236f, 0.156947f, -0.156945f, -0.149961f, 0.006353f, -0.101971f, 0.101964f, -0.000002f, -0.117689f, 0.020704f, 0.018723f, -0.018718f, -0.000001f, 0.038071f, -0.025484f, -0.025482f }, { 0.176236f, 0.105225f, -0.105224f, -0.100542f } } }, + { BottomBackLeft, { { 0.176236f, -0.156936f, 0.156952f, -0.149964f, 0.006358f, 0.101962f, -0.101976f, -0.000005f, -0.117687f, 0.020707f, -0.018720f, 0.018725f, 0.000001f, 0.038071f, 0.025483f, 0.025485f }, { 0.176236f, -0.105218f, 0.105229f, -0.100543f } } }, + { BottomBackRight, { { 0.176256f, -0.156956f, -0.156954f, -0.149974f, 0.006366f, 0.101960f, 0.101964f, 0.000003f, 0.117692f, 0.020690f, -0.018718f, -0.018722f, 0.000001f, -0.038064f, 0.025483f, -0.025484f }, { 0.176256f, -0.105232f, -0.105230f, -0.100550f } } }, }; const ChannelMap *chanmap = NULL; size_t count = 0; @@ -329,6 +356,43 @@ ALvoid aluInitPanning(ALCdevice *device) memset(device->Channel, 0, sizeof(device->Channel)); device->NumChannels = 0; + if(device->Hrtf) + { + static const struct { + enum Channel channel; + ALfloat elevation; + ALfloat angle; + } VirtualChans[14] = { + { FrontCenter, DEG2RAD( 0.0f), DEG2RAD( 0.0f) }, + { BackCenter, DEG2RAD( 0.0f), DEG2RAD(-180.0f) }, + { SideLeft, DEG2RAD( 0.0f), DEG2RAD( -90.0f) }, + { SideRight, DEG2RAD( 0.0f), DEG2RAD( 90.0f) }, + { TopFrontLeft, DEG2RAD( 45.0f), DEG2RAD( -45.0f) }, + { TopFrontRight, DEG2RAD( 45.0f), DEG2RAD( 45.0f) }, + { TopBackLeft, DEG2RAD( 45.0f), DEG2RAD(-135.0f) }, + { TopBackRight, DEG2RAD( 45.0f), DEG2RAD( 135.0f) }, + { BottomFrontLeft, DEG2RAD(-45.0f), DEG2RAD( -45.0f) }, + { BottomFrontRight, DEG2RAD(-45.0f), DEG2RAD( 45.0f) }, + { BottomBackLeft, DEG2RAD(-45.0f), DEG2RAD(-135.0f) }, + { BottomBackRight, DEG2RAD(-45.0f), DEG2RAD( 135.0f) }, + { TopCenter, DEG2RAD( 90.0f), DEG2RAD( 0.0f) }, + { BottomCenter, DEG2RAD(-90.0f), DEG2RAD( 0.0f) }, + }; + ALuint i; + + count = COUNTOF(CubeDiamond); + chanmap = CubeDiamond; + + for(i = 0;i < count;i++) + device->ChannelName[i] = VirtualChans[i].channel; + SetChannelMap(device, chanmap, count); + for(i = 0;i < count;i++) + GetLerpedHrtfCoeffs(device->Hrtf, VirtualChans[i].elevation, VirtualChans[i].angle, + device->Hrtf_Params[i].Coeffs, device->Hrtf_Params[i].Delay); + + return; + } + if(LoadChannelSetup(device)) return; |