Close three critical review findings on the render-bounds-channel verdict
Verdict can no longer print a false EXACT on an on-grid end, no longer names a bounds channel a content-derived render never consulted, and the grid-align doc premise is corrected without implementing it.
This commit is contained in:
@@ -111,18 +111,26 @@ static void testLabelsSeparateExactlyWhatTheRenderSeparates() {
|
||||
|
||||
// --- tail: TailMode -> RENDER_* mapping (docs/product/capture-tail.md) --------
|
||||
|
||||
// The tail assertions below are about the MODE's mapping; the one value that also
|
||||
// depends on the bounds channel has its own test, so they all pin the channel that
|
||||
// every shipped capture rendered on.
|
||||
static TailRenderSettings tailFor(TailMode mode, double manualTailMs) {
|
||||
return tailRenderSettingsFor(mode, manualTailMs,
|
||||
RenderBoundsChannel::CustomTimeBounds);
|
||||
}
|
||||
|
||||
static void testTailNoneIsExactBounds() {
|
||||
// None -> exact bounds, byte-identical to the pre-tail capture: tail flag clear,
|
||||
// 0 ms, disable-all normalize (the current default), no trim. Asserting the exact
|
||||
// bit values (not just "some value") pins the byte-identical contract: if the
|
||||
// mapping regressed to set a tail bit or a non-disable-all normalize, this fails.
|
||||
TailRenderSettings t = tailRenderSettingsFor(TailMode::None, 0.0);
|
||||
TailRenderSettings t = tailFor(TailMode::None, 0.0);
|
||||
CHECK(t.tailFlag == kTailFlagNone); // 0
|
||||
CHECK(t.tailMs == 0.0);
|
||||
CHECK(t.normalize == kNormalizeDisableAll); // 262144
|
||||
CHECK(t.trimEnd == 0.0);
|
||||
// manualTailMs must be ignored for None (a stray tail from a leftover ms is the bug).
|
||||
TailRenderSettings t2 = tailRenderSettingsFor(TailMode::None, 5000.0);
|
||||
TailRenderSettings t2 = tailFor(TailMode::None, 5000.0);
|
||||
CHECK(t2.tailFlag == kTailFlagNone);
|
||||
CHECK(t2.tailMs == 0.0);
|
||||
}
|
||||
@@ -131,7 +139,7 @@ static void testTailAutoIsSurgicalTrim() {
|
||||
// Auto -> custom-bounds tail bit, 8 s cap, SURGICAL normalize (ONLY &32768), and
|
||||
// the -72 dB TRIMEND ratio. The disable-all bit must NOT be set (it is semantically
|
||||
// opposed to trim — this assertion catches a regression to the None normalize).
|
||||
TailRenderSettings t = tailRenderSettingsFor(TailMode::Auto, 0.0);
|
||||
TailRenderSettings t = tailFor(TailMode::Auto, 0.0);
|
||||
CHECK(t.tailFlag == kTailFlagCustomBounds); // &1
|
||||
CHECK(t.tailMs == kMaxTailMs); // 8000
|
||||
CHECK(t.normalize == kNormalizeTrimEnd); // exactly 32768, nothing else
|
||||
@@ -139,7 +147,7 @@ static void testTailAutoIsSurgicalTrim() {
|
||||
// TRIMEND is the derived -72 dB ratio ~= 0.00025119 (the DAW-confirm value).
|
||||
CHECK(std::fabs(t.trimEnd - 0.00025119) < 1e-8);
|
||||
// manualTailMs is ignored for Auto (Auto always uses the 8 s cap).
|
||||
CHECK(tailRenderSettingsFor(TailMode::Auto, 3000.0).tailMs == kMaxTailMs);
|
||||
CHECK(tailFor(TailMode::Auto, 3000.0).tailMs == kMaxTailMs);
|
||||
}
|
||||
|
||||
static void testAutoTrimRatioDerivesFromDb() {
|
||||
@@ -147,7 +155,7 @@ static void testAutoTrimRatioDerivesFromDb() {
|
||||
// float — recompute it independently and require an exact match with the mapping.
|
||||
double expected = std::pow(10.0, kAutoTrimThresholdDb / 20.0);
|
||||
CHECK(autoTrimEndRatio() == expected);
|
||||
CHECK(tailRenderSettingsFor(TailMode::Auto, 0.0).trimEnd == expected);
|
||||
CHECK(tailFor(TailMode::Auto, 0.0).trimEnd == expected);
|
||||
// Sanity: -72 dB is well below unity but above zero.
|
||||
CHECK(expected > 0.0 && expected < 0.001);
|
||||
}
|
||||
@@ -156,7 +164,7 @@ static void testTailManualFixedNoTrim() {
|
||||
// Manual -> custom-bounds tail, the requested ms (within cap), disable-all
|
||||
// normalize (no trim). A Manual capture is a fixed tail, so it keeps today's
|
||||
// disable-all exactly like the no-tail path.
|
||||
TailRenderSettings t = tailRenderSettingsFor(TailMode::Manual, 2500.0);
|
||||
TailRenderSettings t = tailFor(TailMode::Manual, 2500.0);
|
||||
CHECK(t.tailFlag == kTailFlagCustomBounds);
|
||||
CHECK(t.tailMs == 2500.0);
|
||||
CHECK(t.normalize == kNormalizeDisableAll);
|
||||
@@ -165,12 +173,67 @@ static void testTailManualFixedNoTrim() {
|
||||
|
||||
static void testTailManualClampsToCap() {
|
||||
// The 8 s cap is a runaway guard that applies to Manual too: ms > 8000 -> 8000.
|
||||
CHECK(tailRenderSettingsFor(TailMode::Manual, 9000.0).tailMs == kMaxTailMs);
|
||||
CHECK(tailRenderSettingsFor(TailMode::Manual, 8000.0).tailMs == kMaxTailMs);
|
||||
CHECK(tailFor(TailMode::Manual, 9000.0).tailMs == kMaxTailMs);
|
||||
CHECK(tailFor(TailMode::Manual, 8000.0).tailMs == kMaxTailMs);
|
||||
// Below the cap is passed through unchanged.
|
||||
CHECK(tailRenderSettingsFor(TailMode::Manual, 100.0).tailMs == 100.0);
|
||||
CHECK(tailFor(TailMode::Manual, 100.0).tailMs == 100.0);
|
||||
// A negative request floors to 0 (no negative tail leaks into RENDER_TAILMS).
|
||||
CHECK(tailRenderSettingsFor(TailMode::Manual, -50.0).tailMs == 0.0);
|
||||
CHECK(tailFor(TailMode::Manual, -50.0).tailMs == 0.0);
|
||||
}
|
||||
|
||||
// --- bounds channel: RENDER_BOUNDSFLAG mode + the tail bit it drags along ------
|
||||
|
||||
static void testEachChannelNamesItsOwnBoundsFlagMode() {
|
||||
// The two RENDER_BOUNDSFLAG values, as literals from the SDK header — 0 = custom
|
||||
// time bounds, 2 = time selection. Pinned as numbers so a renumbering of the enum
|
||||
// cannot silently point a capture at "entire project" or "selected media items".
|
||||
CHECK(renderBoundsFlagFor(RenderBoundsChannel::CustomTimeBounds) == 0);
|
||||
CHECK(renderBoundsFlagFor(RenderBoundsChannel::TimeSelection) == 2);
|
||||
}
|
||||
|
||||
static void testTailBitFollowsTheBoundsChannel() {
|
||||
// RENDER_TAILFLAG's bits are per-bounds-mode: &1 covers custom time bounds, &4
|
||||
// covers the time selection. A tail set under the other channel's bit renders no
|
||||
// tail at all, which is why the mapping takes the channel rather than trusting a
|
||||
// caller to OR the right one in.
|
||||
CHECK(tailFlagBitFor(RenderBoundsChannel::CustomTimeBounds) == 1);
|
||||
CHECK(tailFlagBitFor(RenderBoundsChannel::TimeSelection) == 4);
|
||||
|
||||
// Both tail-bearing modes follow it — a fix applied to Auto alone would leave
|
||||
// Manual rendering under a bit the bounds mode does not read.
|
||||
for (TailMode mode : {TailMode::Auto, TailMode::Manual}) {
|
||||
CHECK(tailRenderSettingsFor(mode, 2500.0,
|
||||
RenderBoundsChannel::CustomTimeBounds)
|
||||
.tailFlag == kTailFlagCustomBounds);
|
||||
CHECK(tailRenderSettingsFor(mode, 2500.0,
|
||||
RenderBoundsChannel::TimeSelection)
|
||||
.tailFlag == kTailFlagTimeSelection);
|
||||
}
|
||||
}
|
||||
|
||||
static void testNoneSetsNoTailBitOnEitherChannel() {
|
||||
// None is exact bounds on every channel: no tail bit, so no channel's bit either.
|
||||
CHECK(tailRenderSettingsFor(TailMode::None, 5000.0,
|
||||
RenderBoundsChannel::CustomTimeBounds)
|
||||
.tailFlag == kTailFlagNone);
|
||||
CHECK(tailRenderSettingsFor(TailMode::None, 5000.0,
|
||||
RenderBoundsChannel::TimeSelection)
|
||||
.tailFlag == kTailFlagNone);
|
||||
}
|
||||
|
||||
static void testTheChannelLabelNamesTheModeAndItsStore() {
|
||||
// The console verdict is read by someone deciding which channel to keep, so the
|
||||
// label has to name both the mode number and where the window actually went.
|
||||
const std::string custom = renderBoundsChannelLabel(RenderBoundsChannel::CustomTimeBounds);
|
||||
CHECK(custom.find("RENDER_BOUNDSFLAG=0") != std::string::npos);
|
||||
CHECK(custom.find("RENDER_STARTPOS") != std::string::npos);
|
||||
|
||||
const std::string ts = renderBoundsChannelLabel(RenderBoundsChannel::TimeSelection);
|
||||
CHECK(ts.find("RENDER_BOUNDSFLAG=2") != std::string::npos);
|
||||
CHECK(ts.find("GetSet_LoopTimeRange") != std::string::npos);
|
||||
|
||||
// Two channels that read alike in the console would make the experiment unreadable.
|
||||
CHECK(custom != ts);
|
||||
}
|
||||
|
||||
// --- realtimeRecordWindowEnd: the T2 record-window extension -----------------
|
||||
@@ -321,6 +384,23 @@ static void testMultiTrackStemRenderIsNamedForRefusal() {
|
||||
CHECK(!isMultiTrackStemRender(sourceModeForScope(CaptureScope::Item, true), 2));
|
||||
}
|
||||
|
||||
static void testSourceBypassesBoundsChannelOnlyForContentDerivedSources() {
|
||||
// SelectedItems (&32) and RazorArea (&4096) derive their bounds from the
|
||||
// selected items'/areas' own extents -- RENDER_BOUNDSFLAG is never consulted, so
|
||||
// a bounds-channel verdict is not evidence for either (the regression this
|
||||
// predicate exists to catch: RunBatchCaptureItems always renders through
|
||||
// SelectedItems, so this false-EXACT would fire on every batch-item capture).
|
||||
CHECK(sourceBypassesBoundsChannel(SourceMode::SelectedItems));
|
||||
CHECK(sourceBypassesBoundsChannel(SourceMode::RazorArea));
|
||||
|
||||
// Every other source is genuinely time-bounded through RENDER_STARTPOS/ENDPOS or
|
||||
// the time selection, so the channel IS the evidence for these.
|
||||
CHECK(!sourceBypassesBoundsChannel(SourceMode::MasterMix));
|
||||
CHECK(!sourceBypassesBoundsChannel(SourceMode::TimeSelection));
|
||||
CHECK(!sourceBypassesBoundsChannel(SourceMode::SelectedTracks));
|
||||
CHECK(!sourceBypassesBoundsChannel(SourceMode::Realtime));
|
||||
}
|
||||
|
||||
static void testRefusalMessagesAreSiblingsWithDistinctExits() {
|
||||
const std::string item = multiTrackRefusalMessage(CaptureScope::Item);
|
||||
const std::string track = multiTrackRefusalMessage(CaptureScope::Track);
|
||||
@@ -448,6 +528,10 @@ int main() {
|
||||
testAutoTrimRatioDerivesFromDb();
|
||||
testTailManualFixedNoTrim();
|
||||
testTailManualClampsToCap();
|
||||
testEachChannelNamesItsOwnBoundsFlagMode();
|
||||
testTailBitFollowsTheBoundsChannel();
|
||||
testNoneSetsNoTailBitOnEitherChannel();
|
||||
testTheChannelLabelNamesTheModeAndItsStore();
|
||||
testRealtimeWindowNoneIsExact();
|
||||
testRealtimeWindowAutoAddsCap();
|
||||
testRealtimeWindowManualAddsClampedLength();
|
||||
@@ -459,6 +543,7 @@ int main() {
|
||||
testScopeSourceModes();
|
||||
testRangedItemScopeRendersTimeBounded();
|
||||
testMultiTrackStemRenderIsNamedForRefusal();
|
||||
testSourceBypassesBoundsChannelOnlyForContentDerivedSources();
|
||||
testRefusalMessagesAreSiblingsWithDistinctExits();
|
||||
testRefusalMessagesMatchGoldenLiterals();
|
||||
testRangeInference();
|
||||
|
||||
Reference in New Issue
Block a user