Repository navigation
Keep OLR's position timeline in step with renders without positions - #52
Merged
Merged
Conversation
trsonic
requested review from
felicialim,
jingbo-marquis,
trevorknight,
yeroro and
yilun-zhangs
October 13, 2026 14:20
jingbo-marquis
approved these changes
Oct 16, 2026
yilun-zhangs
approved these changes
Oct 16, 2026
yeroro
approved these changes
Oct 19, 2026
OLR counts the samples it has rendered (the render offset) and where each object's next position block starts. A render without a position advanced only the render offset. Every later position block then started before the next sample to render, _refil_processing_queue() dropped it as a metadata underrun and logged an error, and the object stayed silent until the instance was rebuilt. Through oar.h this happens whenever an object element is rendered for a block without a position queued, for example when a host drains the renderer's tail while paused with silent input and no metadata. _metadata_update() now starts a position block at the next sample to render when that is later than the end of the object's previous block. A host that pushes a position for every rendered block, or pushes ahead, gets the same block starts as before. In the same path: - After a processing block that ends inside a render call, the next block was checked against (uint64_t)-1 instead of the finished block's end, so every block starting inside a call counted as an underrun and was dropped. It is checked against the finished block's last sample. - The render offset was an int and overflowed after 2^31 samples, about 12.4 hours at 48 kHz; it is a uint64_t, like the metadata counters. A processing block also computed its overlap with a render call in int; it uses 64-bit sample positions and narrows only the offsets within the call. - The underrun log passed uint64_t values to %u and %lu; it casts them to unsigned long long for %llu. test_object_position_gap.c renders an object element through oar.h for 4 blocks with positions and 1 to 3 blocks without, fed program input or silence, and requires the next block with a position to be audible and equal to the first block of a new oar_t with the same position and input. test_olr_render_offsets.c calls the object audio renderer directly: 128-sample position blocks rendered in 256-sample calls must give the output of 128-sample calls, and blocks rendered at sample positions around 2^31 and 2^32 must give the output of the same blocks at position 0. It includes object_based_audio_renderer.h, so that header's Bazel target is visible to //tests/examples. Both tests fail on main. ctest -L 'oar|obr' (CMake, Release and ASan): 33 pass.
Once rendering has used up an element's queued gain or position metadata, metadata_item_elapse() leaves the item's start and duration at 0, so metadata pushed afterwards applies from the next rendered sample. Duration-only metadata cannot describe a gap. A note on oar_update_audio_element_metadata() now states this, and that a host holds a gain or a position over a span by pushing metadata that covers it. Discussed in #51.
trsonic
force-pushed
the
fix/olr-position-timeline
branch
from
October 19, 2026 16:19
a396f62 to
c952acd
Compare
Collaborator
Author
|
Hey @yeroro @jingbo-marquis @yilun-zhangs, I've just re-requested your reviews following the addition of 9ae4ca8 and c952acd Thanks! |
jingbo-marquis
approved these changes
Oct 20, 2026
yilun-zhangs
approved these changes
Oct 21, 2026
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes the silent object after a render without position metadata, and the three related problems in the same path, described in #51.
src/renderer/olr/olr.c)._metadata_update()starts a position block at the next sample to render when that is later than the end of the object's previous block. A host that pushes a position for every rendered block, or pushes ahead, gets the same block starts as before, so its output is unchanged.block_processor/block_processing_channel.c). The next block is checked against the finished block's last sample instead of against(uint64_t)-1.olr_context_t::offsetis auint64_t, like the metadata counters, and_processing_block_overlap()(block_processor/processing_block.c) computes the overlap in 64-bit positions and narrows only the offsets within the call toint.uint64_tvalues tounsigned long longfor%llu.include/oar.h). A note onoar_update_audio_element_metadata()states that once rendering has used up an element's queued gain or position metadata, metadata pushed afterwards applies from the next rendered sample, and that a host holds a gain or a position over a span by pushing metadata that covers it (from the discussion in OLR: an object stays silent after one render without position metadata #51).Tests:
tests/examples/test_object_position_gap.crenders an object element throughoar.hfor 4 blocks with positions and 1 to 3 blocks without, fed program input or silence, and requires the next block with a position to be audible and equal to the first block of a newoar_twith the same position and input.tests/examples/test_olr_render_offsets.ccalls the object audio renderer directly, becauseoar_render()always hands it one position block per call at the call's position: 128-sample position blocks rendered in 256-sample calls must give the output of 128-sample calls, and blocks rendered at sample positions around 2^31 and 2^32 must give the output of the same blocks at position 0. It includesobject_based_audio_renderer.h, so that header's Bazel target is now also visible to//tests/examples.Both tests fail on
main: the gap cases render silence after the gap, the shorter blocks are dropped as underruns against18446744073709551615, and the block at 2^31 - 256 renders silent.Verified locally on macOS arm64:
ctest --test-dir build -L 'oar|obr' --output-on-failure: 35 of 35 pass, in Release and with-fsanitize=address,undefined, onmain54a4e89.bazel build //...and//tests/examples/...pass (11 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 were run with a temporarybazel_dep(name = "apple_support", version = "2.8.3")inMODULE.bazel, which is not part of this PR.Closes #51