Prove the render bounds at the boundary they cross, and name a short render whose count is exactly a millisecond-floored window

No truncation exists on our side of that boundary, so the read-back is the
only evidence available for whether REAPER kept the window — and it fires on
every tail mode, where only None was ever judged.
This commit is contained in:
2026-08-02 14:28:03 -04:00
parent e589addc54
commit 292d14d14c
6 changed files with 246 additions and 6 deletions
+12 -1
View File
@@ -99,6 +99,17 @@ BoundsVerdict checkRenderedBounds(const std::string& renderedPath,
const long long actualFrames = static_cast<long long>(layout.frameCount());
if (renderHonoredBounds(expectedFrames, actualFrames)) return v;
// Says whether this shortfall has the one shape two live short renders already
// matched to the frame, so every refusal from here on adds to (or breaks) that
// evidence instead of needing the arithmetic done by hand. A count coincidence
// only — it does not establish how the render resolved anything.
const std::string msNote =
actualFrames == msFlooredEndFrameCount(request.startSeconds,
request.endSeconds, rate)
? " Those are exactly the frames this window holds with its end floored to"
" the millisecond -- a match on the count, not a measured cause."
: std::string();
v.refused = true;
v.message = "Render produced " + std::to_string(actualFrames) +
" frames but the requested range is " + std::to_string(expectedFrames) +
@@ -108,7 +119,7 @@ BoundsVerdict checkRenderedBounds(const std::string& renderedPath,
std::to_string(request.endSeconds) + "s) -> frame indices [" +
std::to_string(std::llround(request.startSeconds * rate)) + ", " +
std::to_string(std::llround(request.endSeconds * rate)) + ")." +
retainRefusedRender(renderedPath, projectDir);
msNote + retainRefusedRender(renderedPath, projectDir);
return v;
}