Cut shell/capture comment bloat ~33% (comments only, zero code change)

This commit is contained in:
2026-07-29 20:48:59 -04:00
parent 1f24c4b095
commit 54f5f24506
22 changed files with 699 additions and 1215 deletions
+45 -71
View File
@@ -1,11 +1,9 @@
// capture_realtime_finalize.cpp — the FILE-SIDE half of the realtime-record shell
// (Q-W3, T4-08 split): recorded-file discovery, move-into-bank, the Auto-tail PCM
// decay-scan trim, and the finished-Sample population. See the header. The async
// record lifecycle lives in capture_realtime_shell.cpp.
// capture_realtime_finalize.cpp — recorded-file discovery, move-into-bank, the
// Auto-tail decay-scan trim, and finished-Sample population. See the header.
//
// Compiled into the reaper_reasampler MODULE. Includes reaper_plugin_functions.h
// Compiled into the reaper_reasampler module. Includes reaper_plugin_functions.h
// WITHOUT REAPERAPI_IMPLEMENT — main.cpp is the one TU that defines the API
// pointers; here they are extern (CLAUDE.md §contract).
// pointers; here they are extern.
#include "shell/capture/capture_realtime_finalize.h"
@@ -19,7 +17,7 @@
#include "core/capture/capture_realtime.h" // RecordedCapture, sampleFromRecordedCapture
#include "core/capture/render_settings.h" // autoTrimEndRatio
#include "core/capture/wav_codec.h" // parseWavLayout, extractFloatFrames, planWavTruncate, patchU32LE
#include "core/util/file_bytes.h" // shared whole-file loader (Q-W1, T2-03)
#include "core/util/file_bytes.h" // shared whole-file loader
#define REAPERAPI_MINIMAL
#define REAPERAPI_WANT_GetTrackNumMediaItems
@@ -39,26 +37,21 @@ std::string normSlashes(std::string s) {
return s;
}
// ============================================================================
// §TAIL — Auto-mode PCM decay-scan trim (docs/product/capture-tail.md §realtime)
// ============================================================================
// After the recorded file is stable and moved into the bank (the file we OWN — never
// the project), Auto mode trims the trailing decay: read the WAV, scan the tail
// region (frames AFTER the original range end) backward for the last frame above
// -72 dB, and truncate the file there. Rules (spec):
// * no frame in the tail window above -72 dB -> trim back to the original range end
// * signal never falls below -72 dB in window -> keep the full window (cap did its job)
// * otherwise -> trim one frame past the last audible
// Auto-mode PCM decay-scan trim (docs/product/capture-tail.md §realtime): after the
// recorded file is moved into the bank (the file we OWN, never the project), scan
// the tail (frames after the original range end) backward for the last frame above
// -72 dB and truncate there. Rules:
// * no tail frame above -72 dB -> trim back to the range end
// * signal never drops below -72 dB -> keep the full window (cap did its job)
// * otherwise -> trim one frame past the last audible
//
// Returns the trimmed length in SECONDS (for the Sample), or a negative value to
// signal "no trim applied" (caller keeps the pre-trim length). Best-effort and
// non-fatal: any unreadable/unknown/short file skips the trim (keeps the full window)
// rather than risk corrupting the capture — realtime tail is a convenience path.
// Returns the trimmed length in seconds, or negative for "no trim applied". Any
// unreadable/unknown/short file skips the trim rather than risk corrupting the
// capture — this is a convenience path, not a correctness one.
//
// FORMAT / FLUSH ASSUMPTIONS (DAW-verify): the recorded file is a canonical 32-bit
// float WAV (REAPER project record format — the manual procedure sets it) and is fully
// flushed/closed before this runs (the tick() Finalizing size-stable wait guarantees
// that for the normal path; abort()'s best-effort finalize races it, documented).
// Assumes the recorded file is a canonical 32-bit float WAV, fully flushed/closed
// before this runs (tick()'s Finalizing size-stable wait guarantees that on the
// normal path; abort()'s best-effort finalize can race it).
double trimAutoTailInPlace(const std::string& path,
double rangeStartSeconds,
double rangeEndSeconds) {
@@ -73,21 +66,18 @@ double trimAutoTailInPlace(const std::string& path,
const std::size_t totalFrames = layout.frameCount();
if (totalFrames == 0) return kNoTrim;
// The original range end as a frame index within the file (frame 0 == start). Use
// the FILE's own sample rate (authoritative) — the request rate may be 0 (=follow
// project). Clamp to the file so a rounding overshoot cannot exceed it.
// Range end as a frame index (frame 0 == start), using the file's own sample
// rate (authoritative — the request rate may be 0 = follow project). Clamped to
// the file so a rounding overshoot cannot exceed it.
const double rangeSeconds = rangeEndSeconds - rangeStartSeconds;
if (rangeSeconds <= 0.0) return kNoTrim;
std::size_t rangeEndFrame = static_cast<std::size_t>(
rangeSeconds * static_cast<double>(layout.sampleRate) + 0.5);
if (rangeEndFrame > totalFrames) rangeEndFrame = totalFrames;
// Nothing recorded past the range end (the tail window was empty) -> nothing to
// trim; keep as-is. (Shouldn't happen for Auto, but total by construction.)
if (rangeEndFrame >= totalFrames) return kNoTrim;
if (rangeEndFrame >= totalFrames) return kNoTrim; // tail window was empty
// Scan ONLY the tail region (frames after the original range end). The trim never
// eats into the range body — the scan starts at rangeEndFrame.
// Scan only the tail region the trim never eats into the range body.
const std::size_t tailFrames = totalFrames - rangeEndFrame;
const std::vector<AudioSample> tailPcm =
extractFloatFrames(bytes, layout, rangeEndFrame, tailFrames);
@@ -97,11 +87,10 @@ double trimAutoTailInPlace(const std::string& path,
const std::size_t lastAbove = audio::lastFrameAboveThreshold(
tailPcm, layout.channelCount, tailFrames, threshold);
// keptFrames: the total frame count the trimmed file retains.
// no audible tail frame -> trim back to the range end (rangeEndFrame frames)
// an audible frame at idx -> keep range body + up to and including that frame
// The "signal never falls below threshold" case falls out naturally: lastAbove is
// the final tail frame, so keptFrames == totalFrames (the full window is kept).
// keptFrames: the trimmed file's total frame count. No audible tail frame -> trim
// back to rangeEndFrame; an audible frame at idx -> keep through that frame. The
// "never drops below threshold" case falls out naturally: lastAbove is the final
// tail frame, so keptFrames == totalFrames.
std::size_t keptFrames;
if (lastAbove == audio::kNoFrameAboveThreshold) {
keptFrames = rangeEndFrame;
@@ -113,21 +102,17 @@ double trimAutoTailInPlace(const std::string& path,
const WavTruncatePlan plan = planWavTruncate(layout, keptFrames);
if (!plan.valid) return kNoTrim;
// Patch the RIFF + data size fields in the in-memory buffer so they describe the
// kept frame count (wav_codec's patch primitive — the one RIFF owner), then
// rewrite the file as exactly the first newFileByteLength bytes (header +
// patched sizes + retained PCM). A single truncating write is the simplest
// correct truncate — no separate resize step, no partial-write window where the
// on-disk sizes and length disagree. The result is a valid, playable WAV of the
// kept frames (verified by the wav_codec re-parse test).
// Patch RIFF + data size fields to the kept frame count (wav_codec's patch
// primitive — the one RIFF owner), then rewrite the file as exactly the first
// newFileByteLength bytes. A single truncating write avoids a separate resize
// step and any partial-write window where on-disk sizes and length disagree.
patchU32LE(bytes, plan.dataSizeFieldOffset, plan.newDataSize);
patchU32LE(bytes, plan.riffSizeFieldOffset, plan.newRiffSize);
// NOTE (DAW-verify, best-effort): a truncating write that fails MID-write (a full
// disk, a yanked drive) would leave a short file while we return kNoTrim, so the
// Sample length would overstate the file. Vanishingly unlikely for a just-recorded
// local bank file, and realtime tail is a convenience path, so a temp-file+atomic-
// rename is not warranted here; flagged rather than built.
// A mid-write failure (full disk, yanked drive) would leave a short file while we
// return kNoTrim, overstating the Sample length. Vanishingly unlikely for a
// just-recorded local file, and this is a convenience path, so a temp-file+
// atomic-rename isn't warranted; flagged rather than built.
std::ofstream out(path, std::ios::binary | std::ios::trunc);
if (!out) return kNoTrim; // could not reopen to rewrite — leave the full file
out.write(reinterpret_cast<const char*>(bytes.data()),
@@ -190,12 +175,8 @@ CaptureResult finalizeRecording(ReaProject* proj, MediaTrack* temp,
std::filesystem::remove(recorded, rmEc); // best-effort
}
// TAIL (Auto): trim the trailing decay of the recorded window in place — on the
// BANK file we now own (destPath), never the project. Best-effort: an unreadable /
// unknown-format / short file skips the trim (keeps the full window) rather than
// corrupt the capture. Only Auto trims; None recorded exact bounds and Manual is a
// fixed window (spec §The realtime path). Returns the trimmed length in seconds,
// or < 0 for "no trim applied".
// Only Auto trims; None recorded exact bounds and Manual is a fixed window
// (spec §The realtime path).
double trimmedLenSeconds = -1.0;
if (request.tailMode == TailMode::Auto) {
trimmedLenSeconds = trimAutoTailInPlace(destPath,
@@ -203,7 +184,7 @@ CaptureResult finalizeRecording(ReaProject* proj, MediaTrack* temp,
request.endSeconds);
}
// The pure recorded-capture -> Sample mapping (identity, bounds echo, tier).
// Pure recorded-capture -> Sample mapping (identity, bounds echo, tier).
RecordedCapture cap;
cap.relativePath = paths.relativePath;
cap.uniqueTag = uniqueTag;
@@ -218,23 +199,16 @@ CaptureResult finalizeRecording(ReaProject* proj, MediaTrack* temp,
result.status = CaptureStatus::Ok;
result.sample = sampleFromRecordedCapture(cap);
// The SHARED finished-capture stamp (T2-09 dedupe): trackGuids + channelCount
// (request echo), resolved sampleRate (request rate else PROJECT_SRATE — read
// against the record's OWN project), captureTempo, the capture-start time
// signature (timeSigProj = proj: the realtime path PINS the record's own
// project — the divergence from offline's active-project read, kept
// caller-visible here), the WAV-aware contentHash of the (possibly trimmed)
// bank file, and createdTimestamp.
// Shared finished-capture stamp. timeSigProj = proj: the realtime path pins the
// record's own project (offline reads the active project instead) — the
// divergence is kept caller-visible here.
stampCaptureSample(result.sample, request, /*rateProj=*/proj,
/*timeSigProj=*/proj, destPath);
// The recorded file's true length differs from the request range when a tail was
// recorded, so the Sample length must reflect the FILE, not the range:
// Auto with a trim applied -> the trimmed length trimAutoTailInPlace returned.
// Auto with no trim, or Manual -> the full recorded window (end - start).
// None -> the exact range (unchanged; recordWindowEnd == endSeconds).
// sampleFromRecordedCapture already set lengthSeconds = end - start; override it
// to the recorded/trimmed length so downstream (thumbnail, placement) matches disk.
// The recorded length differs from the request range when a tail was recorded,
// so lengthSeconds must reflect the file, not the range: trimmed length if Auto
// trimmed, else the full recorded window (recordWindowEnd - start; equals the
// exact range when tailMode is None).
if (trimmedLenSeconds >= 0.0) {
result.sample.lengthSeconds = trimmedLenSeconds;
} else {