Skip to content

Keep a segment's boundary time from overflowing and resync a source after its ASRC refuses - #95

Merged
kahrendt merged 1 commit into
mainfrom
issue-24-elapsed-ps
Oct 16, 2026
Merged

kahrendt merged 1 commit into
mainfrom
issue-24-elapsed-ps

Conversation

@kahrendt

Copy link
Copy Markdown
Contributor

Summary

Two rare faults from #24: a segment's boundary time overflowed after about 106.7 days of one anchor, and a live source lost up to a chunk of audio after its ASRC refused one.

Change

  • sched::Segment holds its time from T0 as elapsed_s plus elapsed_ps (the picoseconds past the whole seconds, below 10^12) instead of one int64 count of picoseconds. add_segment() carries the remainder into the seconds; segment_output_index() rounds the absolute boundary instant as before, so rounding still never accumulates across segments and picosecond precision stays.
  • The 64-bit math still runs only in add_segment() (per set_format() and anchor build) and segment_output_index() (per instance start and format boundary): no multiply or divide is added per sample, cell or frame, and segment_output_index() loses two divides.
  • LiveSourceSink::correct(): when the ASRC refuses a chunk, the chunk is written unaltered and the correction restarts (engaged or not), instead of advancing written_ past an ASRC position that did not move, which cut the next output.
  • SinkRig moves to tests/source_sink_rig.h, shared by the sink's two test files. Folded: SourceAsrc::produced()'s doc now mentions reset().
  • Left for the owner: the same kind of overflow in offset_us() and time_position() within one segment after about 278 days at 384 kHz, which runs per frame: Keep a segment's time and position math from overflowing in a run of months #94.

Tests

  • SchedTimeline.SegmentOutputIndexMonthsIntoARun: a Control row at one hour, rows just under and past the old limit (106 and 107 days), a floored remainder, half-up rounding of the remainder and a carry into a whole second, asserting the split fields and the output index. Before the change the 107-day rows trip UBSan's signed overflow.
  • LiveSourceSink.StartsTheCorrectionOverAfterTheAsrcRefuses and ...BeforeIt (new test_source_sink_internals.cpp, white-box): a chunk refused once the correction has started, and one refused before it; both fail before the change (about a chunk lost). The refusal is forced by a zero block size, since no real input makes micro-resampler refuse.
  • Known gap: the ASRC tests skip in the embedded profile, which corrects by slipping frames.

Closes #24
Related: #94

…fter its ASRC refuses

A segment's elapsed time from T0 was one int64 count of picoseconds, which
overflows after about 106.7 days of one anchor. It is now whole seconds plus
the picoseconds past them, carried at each segment, so the boundary keeps its
picosecond precision for any run; the math still runs only per format change
and per instance start.

When a live source sink's ASRC refused a chunk, the chunk was written
unaltered but the ASRC's position did not move with it, so the start of its
next output was cut as already written. The sink now restarts the correction
after a refusal, engaged or not.

Closes #24
@kahrendt
kahrendt marked this pull request as ready for review October 15, 2026 23:51
Copilot AI balanced review requested due to automatic review settings October 15, 2026 23:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused fixes address both reported faults with targeted regression coverage and no identified blocking issues.

0 open findings

What changed in this PR

Addresses #24 by preventing long-running segment boundary overflow and restarting live-source correction after a resampler refusal. The separate within-segment overflow remains tracked in #94.

Changes:

  • Splits boundary elapsed time into seconds and picoseconds while preserving rounding.
  • Restarts correction after writing a refused chunk unaltered.
  • Adds regression tests and extracts a shared sink test fixture.
File Description
tests/​test_source_sink.cpp Uses the shared sink fixture.
tests/​test_source_sink_internals.cpp Tests refusal recovery before and after correction starts.
tests/​test_sched_timeline.cpp Tests long-duration boundaries, rounding and carry.
tests/​source_sink_rig.h Provides the shared sink fixture and tone helpers.
tests/​CMakeLists.txt Registers white-box refusal tests.
src/​source_sink.h Documents correction restarts.
src/​source_sink.cpp Resets correction after resampler refusal.
src/​source_clock.h Clarifies the produced-frame counter documentation.
src/​sched/​timeline.h Stores split boundary elapsed time.
src/​sched/​timeline.cpp Accumulates and rounds split boundary time.
CLAUDE.md Documents the shared test fixture.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@kahrendt
kahrendt merged commit f49ec9b into main Oct 16, 2026
14 checks passed
@kahrendt
kahrendt deleted the issue-24-elapsed-ps branch October 16, 2026 00:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resync the source sink after an ASRC failure, and keep elapsed_ps from overflowing

2 participants