Cut shell/capture comment bloat ~33% (comments only, zero code change)
This commit is contained in:
+45
-90
@@ -1,36 +1,18 @@
|
||||
#pragma once
|
||||
// capture — the REAPER-facing capture shell (CLAUDE.md §load-bearing split).
|
||||
// The shared capture seam: CaptureRequest/CaptureResult (types both backends
|
||||
// speak), OfflineRenderBackend, and the makeUniqueTag/stampCaptureSample helpers.
|
||||
// Realtime's async begin/tick/abort surface lives in capture_realtime_shell.h.
|
||||
//
|
||||
// This header declares the SHARED capture seam (Q-W6 split of the former fat
|
||||
// header — the realtime backend's async begin/tick/abort surface now lives in
|
||||
// capture_realtime_shell.h):
|
||||
// * CaptureRequest / CaptureResult — everything a capture needs and yields,
|
||||
// source-mode-agnostic; the types BOTH backends speak.
|
||||
// * OfflineRenderBackend — the deterministic default; a plain CONCRETE class
|
||||
// (the former ICaptureBackend interface was deleted in
|
||||
// Q-W3, T4-26 — it had one deriver and zero polymorphic
|
||||
// call sites; every construction site instantiates the
|
||||
// concrete type).
|
||||
// * makeUniqueTag / stampCaptureSample — the shared file-tag mint and the shared
|
||||
// finished-capture metadata stamp both backends call
|
||||
// (Q-W3 riders T1-11 / T2-09).
|
||||
//
|
||||
// It includes bank_model (pure) to hand back a populated Sample, but NO REAPER
|
||||
// headers — the .cpp is the REAPER-facing translation unit. Keeping this header
|
||||
// REAPER-free lets callers (the capture orchestration TUs) depend on the seam
|
||||
// without dragging the SDK into every include site.
|
||||
// REAPER-free on purpose (bank_model only) so callers can depend on the seam
|
||||
// without dragging the SDK into every include site; the .cpp is the REAPER TU.
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/model/bank_model.h"
|
||||
#include "core/capture/render_settings.h" // TailMode (pure) — the three-state tail contract
|
||||
#include "core/capture/render_settings.h" // TailMode — the three-state tail contract
|
||||
|
||||
// MediaTrack / ReaProject are forward-declared (like track_guid.h) so this header
|
||||
// stays REAPER-free while RealtimeRecordBackend::begin can take the resolved source
|
||||
// MediaTrack* to tap and stampCaptureSample can take the project handles its reads
|
||||
// pin. The pointers are opaque here — never dereferenced in a pure/header context;
|
||||
// only the REAPER-facing capture TUs touch them.
|
||||
// Forward-declared, never dereferenced here — only the REAPER-facing .cpp touches these.
|
||||
class MediaTrack;
|
||||
class ReaProject;
|
||||
|
||||
@@ -38,71 +20,55 @@ namespace reasampler::capture {
|
||||
|
||||
using model::Sample;
|
||||
|
||||
// Audio bit-depth for the rendered wav. 32-bit float is the M3 default —
|
||||
// rationale lives in capture.cpp next to the sink-config bytes.
|
||||
// 32-bit float is the default; rationale lives in capture.cpp next to the sink-config bytes.
|
||||
enum class WavBitDepth {
|
||||
Int16,
|
||||
Int24,
|
||||
Float32,
|
||||
};
|
||||
|
||||
// One capture, independent of source mode. Populated by the caller (the action
|
||||
// handler in M3; the action family in M7) and consumed by a backend.
|
||||
//
|
||||
// M3 fills only the fields the master-mix/time-selection path needs; the rest
|
||||
// are declared now so M7/M8 do not reshape the struct (they are the seam).
|
||||
// One capture, independent of source mode.
|
||||
struct CaptureRequest {
|
||||
SourceMode sourceMode = SourceMode::MasterMix;
|
||||
|
||||
// Sample-accurate render bounds in project seconds. For the M3 spike these
|
||||
// come straight from the time selection (GetSet_LoopTimeRange) — NO rounding.
|
||||
// Sample-accurate render bounds in project seconds — NO rounding.
|
||||
double startSeconds = 0.0;
|
||||
double endSeconds = 0.0;
|
||||
|
||||
// 1.0 = fully wet, 0.0 = fully dry. All three-scope capture actions set this to 1.0 (wet).
|
||||
// The field is kept as the seam for future true-dry work (M10 null test):
|
||||
// true pre-FX dry offline is NOT available via RENDER_SETTINGS — it requires
|
||||
// FX-bypass-around-render or the M8 realtime pre-FX path, and will be
|
||||
// designed alongside the M10 null test. Also recorded on the Sample.
|
||||
// 1.0 = fully wet, 0.0 = fully dry. Every current capture action sets 1.0;
|
||||
// true pre-FX dry isn't available via RENDER_SETTINGS (needs FX-bypass-around-render
|
||||
// or the realtime pre-FX path) so this stays a seam for that future work.
|
||||
double wetDry = 1.0;
|
||||
|
||||
// Track GUID(s) the capture came from, when the source mode is track-scoped
|
||||
// (SelectedTracks). Empty for master/items/razor. The action layer (M7)
|
||||
// resolves the selection to canonical GUID strings and passes them here; the
|
||||
// backend copies them onto the Sample (it does NOT itself read the selection —
|
||||
// it stays source-agnostic, driven entirely by the request).
|
||||
// Track GUID(s) when source mode is track-scoped (SelectedTracks); empty otherwise.
|
||||
// The backend only copies these onto the Sample — it never reads selection itself.
|
||||
std::vector<std::string> trackGuids;
|
||||
|
||||
// Render tail (docs/product/capture-tail.md §The three tail states). Default
|
||||
// None: exact bounds, no added silence — the precision invariant, and the only
|
||||
// mode valid for null-test / verify captures. `tailMs` is meaningful ONLY for
|
||||
// TailMode::Manual (clamped to the 8 s cap by the pure mapping); Auto uses the
|
||||
// 8 s cap + -72 dB trim internally, None ignores it.
|
||||
// Render tail (docs/product/capture-tail.md §The three tail states). None = exact
|
||||
// bounds, no added silence — the only mode valid for null-test/verify captures.
|
||||
// tailMs applies only to Manual (clamped to 8s by the pure mapping); Auto uses
|
||||
// the 8s cap + -72 dB trim internally, None ignores it.
|
||||
TailMode tailMode = TailMode::None;
|
||||
double tailMs = 0.0;
|
||||
|
||||
// Output format. 0 sampleRate => follow project rate (deterministic: the
|
||||
// project rate is fixed for a given project).
|
||||
// 0 sampleRate => follow project rate.
|
||||
int sampleRate = 0;
|
||||
int channelCount = 2;
|
||||
WavBitDepth bitDepth = WavBitDepth::Float32;
|
||||
|
||||
// Human base name for the file stem; sanitized by capture_paths. The unique
|
||||
// tag (disambiguator) is supplied separately by the backend caller so the
|
||||
// pure naming logic stays testable.
|
||||
// Sanitized by capture_paths. uniqueTag (disambiguator) is supplied by the
|
||||
// backend caller so the pure naming logic stays testable.
|
||||
std::string baseName = "capture";
|
||||
std::string uniqueTag; // e.g. a timestamp/counter; may be empty
|
||||
std::string uniqueTag;
|
||||
};
|
||||
|
||||
// Outcome of a capture attempt. `Ok` carries the populated Sample; every failure
|
||||
// is an explicit code (never a thrown exception across the REAPER boundary) so
|
||||
// the action handler can log a precise reason.
|
||||
// Every failure is an explicit code, never a thrown exception across the REAPER boundary.
|
||||
enum class CaptureStatus {
|
||||
Ok,
|
||||
NoProject, // no active project to render / resolve a bank folder
|
||||
EmptyRange, // start >= end: nothing to render
|
||||
UnsupportedMode, // backend does not implement this source mode (M3 scope)
|
||||
UnsupportedFormat, // requested bit depth has no known REAPER blob (M3: Float32 only)
|
||||
UnsupportedMode, // backend does not implement this source mode
|
||||
UnsupportedFormat, // requested bit depth has no known REAPER blob (Float32 only)
|
||||
RenderFailed, // the render action ran but produced no output file
|
||||
TransportBusy, // realtime backend: transport already playing/recording — refused
|
||||
};
|
||||
@@ -113,44 +79,33 @@ struct CaptureResult {
|
||||
std::string message; // human-readable detail for the console log
|
||||
};
|
||||
|
||||
// Deterministic offline-render backend. Drives the full offline source family —
|
||||
// master mix / time selection, selected tracks, selected items, razor area — all
|
||||
// wet-only (render_settings.h) with optional tail. The source selection + range
|
||||
// are resolved by the caller (the action layer) and handed in via the
|
||||
// CaptureRequest; the backend drives RENDER_* and never reads the DAW selection
|
||||
// itself. SourceMode::Realtime returns UnsupportedMode (that is the M8 backend).
|
||||
// Non-destructive: restores every RENDER_* setting it touches on every path.
|
||||
// A plain concrete class — the former ICaptureBackend interface was deleted
|
||||
// (Q-W3, T4-26): it had one deriver, zero polymorphic call sites, and the async
|
||||
// realtime backend deliberately never implemented it (see SEAM CHOICE below).
|
||||
// Deterministic offline-render backend: master mix / time selection / selected
|
||||
// tracks / selected items / razor area, all wet-only, optional tail. Source
|
||||
// selection + range are resolved by the caller and handed in via CaptureRequest —
|
||||
// the backend drives RENDER_* and never reads the DAW selection itself.
|
||||
// SourceMode::Realtime returns UnsupportedMode. Non-destructive: restores every
|
||||
// RENDER_* setting it touches on every path. Plain concrete class — see the
|
||||
// no-shared-interface note in capture_realtime_shell.h before adding one back.
|
||||
class OfflineRenderBackend {
|
||||
public:
|
||||
CaptureResult capture(const CaptureRequest& request);
|
||||
};
|
||||
|
||||
// --- Shared backend helpers (Q-W3 riders) ------------------------------------
|
||||
|
||||
// Mints the filesystem-safe disambiguating tag for one capture's file stem +
|
||||
// Sample id: "<prefix><unix-epoch-seconds>-<n>" where <n> is a PER-SESSION
|
||||
// MONOTONIC counter (T1-11 fix). The wall-clock second alone had a collision
|
||||
// window: two captures of the same baseName within one second derived the same
|
||||
// stem, so the second render silently overwrote the first file (reachable via
|
||||
// batch capture driving short renders back-to-back). The counter makes every tag
|
||||
// of a session distinct regardless of timing. `prefix` is the backend's family
|
||||
// marker ("" offline, "rt-" realtime).
|
||||
// Sample id: "<prefix><unix-epoch-seconds>-<n>", <n> a per-session monotonic
|
||||
// counter. Wall-clock seconds alone collide when batch capture drives short
|
||||
// renders back-to-back, silently overwriting the first file. `prefix` is the
|
||||
// backend's family marker ("" offline, "rt-" realtime).
|
||||
std::string makeUniqueTag(const std::string& prefix);
|
||||
|
||||
// Stamps the SHARED finished-capture metadata onto `s` (T2-09 dedupe — this stamp
|
||||
// was copy-pasted per backend and had silently diverged): trackGuids +
|
||||
// channelCount (echoed from the request), the resolved sampleRate (request rate,
|
||||
// else PROJECT_SRATE read from `rateProj`; 0 stays 0 when unknown), captureTempo
|
||||
// (Master_GetTempo), the capture-start time signature (TimeMap_GetTimeSigAtTime
|
||||
// against `timeSigProj` — the offline path passes nullptr = active project, the
|
||||
// realtime path pins the record's own project; the divergence stays caller-visible
|
||||
// as this argument), the WAV-aware contentHash of the finished file at
|
||||
// `absolutePath` (left empty when unreadable — the safe, confirm-eliciting
|
||||
// direction), and createdTimestamp (now). The per-backend bits (id, paths, bounds,
|
||||
// tier, realtime's recorded-length override) stay with each caller.
|
||||
// Stamps the metadata shared by both backends onto `s`: trackGuids + channelCount
|
||||
// (echoed from the request), resolved sampleRate (request rate, else PROJECT_SRATE
|
||||
// from `rateProj`), captureTempo, the capture-start time signature
|
||||
// (TimeMap_GetTimeSigAtTime against `timeSigProj` — offline passes nullptr for the
|
||||
// active project, realtime pins the record's own project), the WAV-aware
|
||||
// contentHash of `absolutePath` (left empty when unreadable), and createdTimestamp.
|
||||
// Per-backend bits (id, paths, bounds, tier, realtime's length override) stay
|
||||
// with each caller.
|
||||
void stampCaptureSample(Sample& s, const CaptureRequest& req,
|
||||
ReaProject* rateProj, ReaProject* timeSigProj,
|
||||
const std::string& absolutePath);
|
||||
|
||||
Reference in New Issue
Block a user