Repository navigation
Give OBR's head-locked and world-locked passes their own encoders - #54
Conversation
d9c1195 to
e647b0b
Compare
ProcessingGroup::Process() encodes the loudspeaker layout and object channels of a group in two passes, the world-locked elements' and the head-locked elements', and copies each pass's channels to the encoder's inputs 0 to k-1. One encoder held all the group's channels as sources, in element order. In a group with both kinds of element a pass's channels were therefore encoded with other channels' positions, the encoder inputs past k still held the other pass's audio, and both passes shared one encoder's interpolation state. Through oar.h, with element 1 head-locked and silent at +90 degrees and element 2 world-locked noise at -90 degrees, element 2 is rendered at +90 degrees: left and right energy 226.695 and 6.799, against 6.577 and 227.456 with element 1 world-locked. Each pass now has its own encoder and input buffer (EncoderPass), with the pass's channels as sources in element order, so input i of a pass is encoded with the position of the pass's i-th channel. UpdateAmbisonicEncoder() sizes and sets both, and SetElementHeadLocked() calls it through UpdateAllAmbisonicEncoders(), because a change moves the element's channels to the other pass; its documentation says that it can allocate. A group whose elements are all world-locked or all head-locked uses one encoder with the same sources as before. test_binaural_mixed_lock.c renders a world-locked object beside a silent head-locked one and requires the output of the world-locked object alone, and the reverse with the head-locked object alone. ObrImplTest.TestSetElementHeadLockedUpdatesEncoders sets a configured group's element head-locked, and back to world-locked so that the head-locked pass is empty, and requires the output of the world-locked object alone. Both fail on main. ctest -L 'oar|obr' (CMake, Release and ASan): 40 pass.
e647b0b to
94df884
Compare
|
Rebased onto |
Fixes #53: in a binaural processing group with both head-locked and world-locked loudspeaker or object elements, channels were encoded with other channels' positions.
renderer/processing_group.{h,cc}).ProcessingGroupkeeps anEncoderPass(encoder and input buffer) for the world-locked and for the head-locked channels. Each holds only its pass's channels as sources, in element order, so input i of a pass is encoded with the position of the pass's i-th channel, and the passes no longer share inputs or interpolation state.UpdateAmbisonicEncoder()sizes and sets both.SetElementHeadLocked()(renderer/obr_impl.{h,cc}) callsUpdateAllAmbisonicEncoders(), because a change moves the element's channels to the other pass. Its documentation says that it can allocate when an encoder's source count changes.A group whose elements are all world-locked or all head-locked uses one encoder with the same sources as before, so its output does not change. With the reproduction from #53, both runs now render element 2 on the right: L 6.577, R 227.456.
Tests:
tests/examples/test_binaural_mixed_lock.crenders, throughoar.h, a world-locked object beside a silent head-locked one and requires the output of the world-locked object alone, and the reverse with the head-locked object alone.ObrImplTest.TestSetElementHeadLockedUpdatesEncoderssets a configured group's element head-locked, and back to world-locked so that the head-locked pass is empty, and requires the output of the world-locked object alone.Both fail on
main.Verified locally on macOS arm64:
ctest --test-dir build -L 'oar|obr' --output-on-failure: 40 of 40 pass, in Release and with-fsanitize=address.//tests/examples:alland@obr//obr/renderer/tests:allpass (21 pass, 1 skipped). The standalone Bazel build fails on this machine onmaintoo, with the XcodeSDKSettings.json"absolute path inclusion" error in untouched files, so these targets were built as modules from a workspace that registersapple_support's toolchain.Closes #53