Fix render-bounds EXACT verdict: enumerate floored models instead of trusting grid membership
Grid-ness of an edge was a proxy for "no floor could explain this count," not the test itself — equal remainders on both edges cancel under a full floor. Now checks all three floored models directly and corrects the SHORT/LONG floor-signature docs.
This commit is contained in:
@@ -145,13 +145,16 @@ RenderSettingsChoice renderSettingsFor(SourceMode mode, double wetDry);
|
||||
// naming them apart would assert a render distinction that does not exist.
|
||||
const char* renderSourceLabel(SourceMode mode);
|
||||
|
||||
// True for a render source that derives its bounds from content rather than from
|
||||
// RENDER_BOUNDSFLAG at all: SelectedItems (&32) and RazorArea (&4096) bound
|
||||
// themselves to the selected items'/areas' own extents (see the &32 inference in
|
||||
// src/core/capture/CLAUDE.md §Gotchas; RazorArea is read the same way, sharing the
|
||||
// single-file bit for the same reason). A capture on one of these never consults
|
||||
// RenderBoundsChannel, so describeBoundsExperiment's verdict must not be read as
|
||||
// evidence about the channel for it — the caller names the source instead.
|
||||
// True for a render source INFERRED (not SDK-confirmed) to derive its bounds from
|
||||
// content rather than RENDER_BOUNDSFLAG: SelectedItems (&32), per the observed-defect
|
||||
// inference in src/core/capture/CLAUDE.md §Gotchas, and RazorArea (&4096) by analogy to
|
||||
// it — the SDK header (~3042) actually separates bounds (RENDER_BOUNDSFLAG, its own
|
||||
// value 4 = selected media items) from source (&32), which leans the other way.
|
||||
// RazorArea stays in the set on that inference even though no offline capture path
|
||||
// assigns it today — razor is a RANGE source (capture_batch.cpp's razor units render
|
||||
// through track scope), not a render source of its own. A capture on either never
|
||||
// consults RenderBoundsChannel, so describeBoundsExperiment's verdict must not be read
|
||||
// as evidence about the channel — the caller names the source instead.
|
||||
bool sourceBypassesBoundsChannel(SourceMode mode);
|
||||
|
||||
// --- Capture scope: the FX-scope invariant ------------------------------------
|
||||
|
||||
@@ -76,20 +76,30 @@ std::string describeBoundsExperiment(const char* channelLabel,
|
||||
s += ". ";
|
||||
|
||||
if (bypassingSourceLabel && bypassingSourceLabel[0]) {
|
||||
s += "NOT JUDGED -- rendered from " + std::string(bypassingSourceLabel) +
|
||||
", which derives its bounds from content and never consulted this channel;"
|
||||
" this capture is not evidence either way about it.";
|
||||
s += "NOT JUDGED -- this capture's render source is " +
|
||||
std::string(bypassingSourceLabel) +
|
||||
", INFERRED (not SDK-confirmed) to derive its bounds from content rather"
|
||||
" than consult this channel; this capture is not evidence either way about it.";
|
||||
return s;
|
||||
}
|
||||
|
||||
if (sampleRate <= 0) {
|
||||
s += "NOT JUDGED -- the landed render's frames were never counted against the "
|
||||
s += "NOT JUDGED -- this capture's frames were never counted against the "
|
||||
"window, so this capture is not evidence either way about the channel.";
|
||||
return s;
|
||||
}
|
||||
|
||||
const long long expected = frameCountFor(reqStart, reqEnd, sampleRate);
|
||||
const long long delta = actualFrames - expected;
|
||||
|
||||
// A window under a frame at this rate has nothing to compare: a 0-frame render
|
||||
// against a 0-frame window is a coincidence of degenerate inputs, not a match.
|
||||
if (expected == 0 && actualFrames == 0) {
|
||||
s += "NOT JUDGED -- the requested window rounds to 0 frames at this rate, so a "
|
||||
"0-frame render is not evidence either way about the channel.";
|
||||
return s;
|
||||
}
|
||||
|
||||
// Within the gate's own edge-convention slack (render_window.h): its normal
|
||||
// tolerance, not evidence the millisecond floor was escaped or hit.
|
||||
const bool withinTolerance =
|
||||
@@ -101,13 +111,14 @@ std::string describeBoundsExperiment(const char* channelLabel,
|
||||
" the window asks for at " + std::to_string(sampleRate) + " Hz.";
|
||||
|
||||
// The shape both live short renders matched to the frame. A match says this channel
|
||||
// produced a floored window; it does not locate where inside REAPER the floor is.
|
||||
if (delta != 0) {
|
||||
// produced a floored window; it does not locate where inside REAPER the floor is. A
|
||||
// floor only removes frames, so this can only ever match a SHORT, never a LONG.
|
||||
if (delta < 0) {
|
||||
const long long msFloored =
|
||||
msFlooredEndFrameCount(reqStart, reqEnd, sampleRate);
|
||||
if (msFloored > 0 && actualFrames == msFloored)
|
||||
s += " That is exactly the count this window holds with its end floored to"
|
||||
" the millisecond -- this channel did not escape the floor.";
|
||||
" the millisecond -- the shape REAPER's render was measured producing.";
|
||||
}
|
||||
|
||||
s += isOnMillisecondGrid(reqStart)
|
||||
@@ -117,15 +128,38 @@ std::string describeBoundsExperiment(const char* channelLabel,
|
||||
: " The START edge IS tested here: " + exactly(reqStart) +
|
||||
"s carries a sub-millisecond remainder.";
|
||||
|
||||
// An EXACT verdict on an on-grid END is not proof: a channel that floors the end
|
||||
// would have printed this same count, since floor/ceil/round all leave a grid point
|
||||
// alone. Without this, EXACT reads as settled when this run could not have told the
|
||||
// two apart.
|
||||
if (delta == 0 && isOnMillisecondGrid(reqEnd)) {
|
||||
s += " The END edge is UNTESTED here too: " + exactly(reqEnd) +
|
||||
"s is already on the millisecond grid, so a channel that floors the end"
|
||||
" would have printed this same EXACT count -- re-run over a window whose"
|
||||
" end is off the grid before reading EXACT as the fix.";
|
||||
// EXACT is proof only when no millisecond-floored model of this window could have
|
||||
// produced the same count. Grid membership on an edge is a PROXY for that collision,
|
||||
// not the test itself: sub-millisecond remainders on the two edges can cancel under
|
||||
// a full floor even when neither edge is on the grid (a dragged, fixed-length time
|
||||
// selection reproduces this), and a remainder under half a frame collides with a
|
||||
// floored edge without ever registering as off-grid. Enumerate every floored model
|
||||
// directly rather than inferring from grid membership.
|
||||
if (delta == 0) {
|
||||
const double flooredStart = floorToMilliseconds(reqStart);
|
||||
const double flooredEnd = floorToMilliseconds(reqEnd);
|
||||
const bool startAlone =
|
||||
actualFrames == frameCountFor(flooredStart, reqEnd, sampleRate);
|
||||
const bool endAlone =
|
||||
actualFrames == frameCountFor(reqStart, flooredEnd, sampleRate);
|
||||
const bool bothTogether =
|
||||
actualFrames == frameCountFor(flooredStart, flooredEnd, sampleRate);
|
||||
|
||||
if (startAlone || endAlone || bothTogether) {
|
||||
std::string models;
|
||||
auto addModel = [&](const char* label) {
|
||||
if (!models.empty()) models += ", or ";
|
||||
models += label;
|
||||
};
|
||||
if (startAlone) addModel("floors the START edge alone");
|
||||
if (endAlone) addModel("floors the END edge alone");
|
||||
if (bothTogether) addModel("floors START and END together");
|
||||
|
||||
s += " EXACT here is not proof: a render that " + models +
|
||||
" to the millisecond would print this identical count -- re-run over a"
|
||||
" window where a floored edge would show a different count before"
|
||||
" reading EXACT as the fix.";
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -85,20 +85,32 @@ bool isOnMillisecondGrid(double seconds);
|
||||
// at all. Always non-empty — a capture that answered nothing has to say so, or its
|
||||
// silence reads as a pass.
|
||||
//
|
||||
// EXACT never stands alone as proof: an END that sits on the millisecond grid prints
|
||||
// the SAME EXACT count whether the channel honored the window or floored it and landed
|
||||
// back on the grid by coincidence, so that case is called out in the sentence rather
|
||||
// than left to read as settled — same principle as the existing START-edge caveat.
|
||||
// EXACT never stands alone as proof: the observed count is checked against every
|
||||
// millisecond-floored model of the same window (start floored alone, end floored alone,
|
||||
// both together), and any model that reproduces it is named in the sentence. Grid
|
||||
// membership on an edge is a PROXY for that collision, not the test itself — remainders
|
||||
// on the two edges can cancel under a full floor even when NEITHER edge sits on the
|
||||
// grid, and a remainder under half a frame collides with a floored edge without ever
|
||||
// registering as off-grid at all. Checking the models directly is what a grid test on
|
||||
// either edge alone cannot do.
|
||||
//
|
||||
// A non-zero delta that still falls inside the gate's own tolerance (renderHonoredBounds)
|
||||
// is tagged "(WITHIN TOLERANCE)" — that is the gate's ordinary edge-convention slack, not
|
||||
// evidence of the millisecond floor; a bare SHORT/LONG, or a delta matching
|
||||
// msFlooredEndFrameCount exactly, is the floor's signature.
|
||||
// evidence of the millisecond floor. The floor's signature is ONLY the "floored to the
|
||||
// millisecond" sentence (a delta matching msFlooredEndFrameCount exactly); a bare
|
||||
// SHORT with no such sentence means the shortfall's cause is unestablished, and LONG can
|
||||
// never be the floor's signature — a floor only removes frames, never adds them. A
|
||||
// window whose start and end sit in the same millisecond bucket makes msFlooredEndFrameCount
|
||||
// equal the exact count, so a real one-frame floor there reads as a bare SHORT (WITHIN
|
||||
// TOLERANCE) with no floor sentence at all — that combination is not evidence the floor
|
||||
// didn't happen, just a case this diagnostic can't see into.
|
||||
//
|
||||
// `sampleRate <= 0` means the landed file was never measured: a tail mode adds frames by
|
||||
// design and is not judged, an empty render has none, and a render whose layout failed to
|
||||
// parse or declared no sample rate is refused before it can be judged either — the
|
||||
// sentence then says the run answered nothing rather than inventing a comparison.
|
||||
// sentence then says the run answered nothing rather than inventing a comparison. A
|
||||
// window that rounds to 0 frames at this rate reads NOT JUDGED the same way: a 0-frame
|
||||
// render against a 0-frame window is not a comparison either.
|
||||
//
|
||||
// `bypassingSourceLabel`, when non-null and non-empty, means the render source itself
|
||||
// defined the window (render_settings::sourceBypassesBoundsChannel) — `channelLabel` was
|
||||
|
||||
Reference in New Issue
Block a user