Ψ-W2-T2: collapse a capture whose channels are bit-identical to one lossless mono channel, index value measured off the landed file
This commit is contained in:
@@ -201,11 +201,27 @@ std::string makeUniqueTag(const std::string& prefix) {
|
||||
std::to_string(++counter);
|
||||
}
|
||||
|
||||
void collapseCapturedFileToMono(const std::string& absolutePath) {
|
||||
const std::vector<std::uint8_t> bytes = util::readFileBytes(absolutePath);
|
||||
if (bytes.empty()) return;
|
||||
|
||||
const MonoCollapse collapse = collapseToMono(bytes);
|
||||
if (!collapse.collapsed) return;
|
||||
|
||||
// One truncating write — the same shape, and the same accepted mid-write residual,
|
||||
// as the realtime Auto-tail trim (capture_realtime_finalize.cpp).
|
||||
std::ofstream out(absolutePath, std::ios::binary | std::ios::trunc);
|
||||
if (!out) return;
|
||||
out.write(reinterpret_cast<const char*>(collapse.bytes.data()),
|
||||
static_cast<std::streamsize>(collapse.bytes.size()));
|
||||
}
|
||||
|
||||
void stampCaptureSample(Sample& s, const CaptureRequest& req,
|
||||
ReaProject* rateProj, ReaProject* timeSigProj,
|
||||
const std::string& absolutePath) {
|
||||
// Track GUIDs + channel count: echoed from the request (the caller resolved
|
||||
// the selection; the backends stay source-agnostic).
|
||||
// Track GUIDs echoed from the request (the caller resolved the selection; the
|
||||
// backends stay source-agnostic). channelCount starts at the request value only
|
||||
// as the fallback for an unparseable file — the produced FILE overrides it below.
|
||||
s.trackGuids = req.trackGuids;
|
||||
s.channelCount = req.channelCount;
|
||||
|
||||
@@ -238,6 +254,10 @@ void stampCaptureSample(Sample& s, const CaptureRequest& req,
|
||||
const std::vector<std::uint8_t> fileBytes = util::readFileBytes(absolutePath);
|
||||
if (!fileBytes.empty()) {
|
||||
s.contentHash = hashWavContent(fileBytes);
|
||||
// The one authority for the entry's channel count is the file's own `fmt`
|
||||
// — never the render request, which asks for 2 on every capture path.
|
||||
const WavLayout layout = parseWavLayout(fileBytes);
|
||||
if (layout.valid) s.channelCount = static_cast<int>(layout.channelCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -447,6 +467,14 @@ CaptureResult OfflineRenderBackend::capture(const CaptureRequest& request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Lossless mono collapse, deliberately AFTER the bounds gate: the gate measures
|
||||
// REAPER's own render against the requested window, so nothing of ours may sit
|
||||
// between the render and that measurement, and a refusal must delete the
|
||||
// renderer's file rather than one this step had already rewritten. The collapse
|
||||
// preserves the frame count, so the two are order-independent in outcome — only
|
||||
// in what each is measuring.
|
||||
collapseCapturedFileToMono(expectedPath);
|
||||
|
||||
// Record the request's own bounds (exact) rather than re-measuring the file.
|
||||
Sample s;
|
||||
// Same uniqueTag that named the file — calling makeUniqueTag() again could
|
||||
|
||||
Reference in New Issue
Block a user