Cut core/model, reclaim, json, util comment bloat ~26% (comments only, zero code change)
This commit is contained in:
+35
-44
@@ -1,11 +1,7 @@
|
||||
#pragma once
|
||||
// bank_model — the HEART of ReaSampler, deliberately free of any REAPER type so
|
||||
// it compiles and unit-tests OUTSIDE the DAW. It owns the per-project sample
|
||||
// bank: the `Sample` metadata struct and the `BankModel` (add / remove / query /
|
||||
// tier moves / dedup-by-hash + JSON round-trip to/from std::string).
|
||||
//
|
||||
// PURE MODULE (CLAUDE.md §load-bearing split): NO REAPER types, NO SWELL, NO
|
||||
// vendor/ includes. Standard library only.
|
||||
// bank_model — the HEART of ReaSampler: the per-project sample bank. `Sample`
|
||||
// metadata struct + `BankModel` (add/remove/query/tier moves/dedup-by-hash + JSON
|
||||
// round-trip to/from std::string).
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
@@ -14,8 +10,8 @@
|
||||
|
||||
namespace reasampler::model {
|
||||
|
||||
// How the source audio was obtained. Kept in the pure core (no REAPER coupling);
|
||||
// the capture backends (M3/M8) map their own notion onto these.
|
||||
// How the source audio was obtained; the capture backends map their own notion
|
||||
// onto these.
|
||||
enum class SourceMode {
|
||||
MasterMix, // offline render of the master output
|
||||
SelectedTracks, // offline render of selected tracks
|
||||
@@ -31,9 +27,8 @@ enum class Tier {
|
||||
Archive,
|
||||
};
|
||||
|
||||
// Sample-accurate source bounds, in both project seconds and PPQ (ticks). Both
|
||||
// are stored because capture needs seconds and musical placement needs PPQ; we
|
||||
// refuse to re-derive one from the other and risk rounding (precision invariant).
|
||||
// Sample-accurate source bounds, in both project seconds and PPQ (ticks) — both
|
||||
// stored so capture doesn't re-derive one from the other and risk rounding.
|
||||
struct SourceRange {
|
||||
double startSeconds = 0.0;
|
||||
double endSeconds = 0.0;
|
||||
@@ -44,9 +39,9 @@ struct SourceRange {
|
||||
};
|
||||
|
||||
// Present only when a sample was resampled FROM another sample. Carries the
|
||||
// parent's id and the FX-chain snapshot string (a thin drift fingerprint, NOT a
|
||||
// restorable chunk) captured at resample time; the re-capture-from-source action
|
||||
// (M10) uses it to detect chain drift and replay the original capture request.
|
||||
// parent's id and an FX-chain snapshot (a thin drift fingerprint, NOT a restorable
|
||||
// chunk) — re-capture-from-source uses it to detect chain drift and replay the
|
||||
// original capture request.
|
||||
struct Provenance {
|
||||
std::string parentSampleId;
|
||||
std::string fxChainSnapshot;
|
||||
@@ -63,15 +58,13 @@ struct Levels {
|
||||
bool operator==(const Levels& o) const;
|
||||
};
|
||||
|
||||
// Sample-accurate sustain-loop bounds, as frame indices into the captured file
|
||||
// (Phase S seam field, D-B). A bank intrinsic — a fact about the file, like
|
||||
// sampleRate or length — consumed by the future MIDI-playback instrument to hold
|
||||
// notes past the recorded length. Modeled as one optional struct (not two loose
|
||||
// optionals) so "both points or neither" is a structural invariant, not a rule to
|
||||
// re-check at every boundary. Frame indices, not seconds, because the loop is a
|
||||
// per-sample-frame contract; the instrument reads the file's sample rate to relate
|
||||
// them to time. Invariant (enforced at the deserialize boundary): 0 <= start <= end.
|
||||
// start == end is a valid zero-length loop marker.
|
||||
// Sample-accurate sustain-loop bounds, as frame indices into the captured file — a
|
||||
// bank intrinsic (like sampleRate or length) the MIDI-playback instrument uses to
|
||||
// hold notes past the recorded length. One optional struct (not two loose
|
||||
// optionals) so "both points or neither" is structural, not a rule to re-check at
|
||||
// every boundary. Frame indices, not seconds — the instrument relates them to time
|
||||
// via the file's sample rate. Invariant (enforced at deserialize): 0 <= start <=
|
||||
// end; start == end is a valid zero-length loop marker.
|
||||
struct LoopPoints {
|
||||
std::int64_t start = 0;
|
||||
std::int64_t end = 0;
|
||||
@@ -102,23 +95,23 @@ struct Sample {
|
||||
double lengthBeats = 0.0;
|
||||
double captureTempo = 0.0; // project tempo (BPM) at capture time
|
||||
|
||||
// Time signature at capture time (L7 F1 — stamped alongside captureTempo so the
|
||||
// bars.beats.subdivisions read-out is stable under later project meter changes).
|
||||
// 0/0 means UNSTAMPED (pre-L7 sample, or a capture that could not read the meter);
|
||||
// the metadata formatter renders a blank musical read-out for 0/0 and keeps s.ms.
|
||||
// Time signature at capture time, stamped alongside captureTempo so the
|
||||
// bars.beats.subdivisions read-out is stable under later project meter changes.
|
||||
// 0/0 means UNSTAMPED (pre-existing sample, or a capture that could not read the
|
||||
// meter); the metadata formatter renders a blank musical read-out then, keeping s.ms.
|
||||
int captureTimeSigNum = 0; // meter numerator (e.g. 4 in 4/4); 0 = unstamped
|
||||
int captureTimeSigDenom = 0; // meter denominator (e.g. 4 in 4/4); 0 = unstamped
|
||||
|
||||
std::optional<std::string> key; // musical key, when known
|
||||
|
||||
// Phase S seam fields (D-B) — bank intrinsics for the MIDI-playback instrument,
|
||||
// additive like `provenance` (M1). Both default cleanly empty: pre-Phase-S
|
||||
// samples deserialize without them and re-serialize without inventing values.
|
||||
// Bank intrinsics for the MIDI-playback instrument, additive like `provenance`.
|
||||
// Both default cleanly empty: pre-existing samples deserialize without them and
|
||||
// re-serialize without inventing values.
|
||||
// - rootNote: MIDI note (0..127) the sample was recorded at, so the instrument
|
||||
// can repitch it across the keyboard. DISTINCT from the musical `key` above:
|
||||
// `key` is a human label ("F#m"); `rootNote` is the exact pitch for repitch.
|
||||
// Populated at/after capture only where derivable — left empty (never guessed)
|
||||
// when the source is not a single played note.
|
||||
// Populated only where derivable — never guessed when the source isn't a
|
||||
// single played note.
|
||||
// - loop: sustain-loop bounds, populated only where explicitly set.
|
||||
std::optional<int> rootNote;
|
||||
std::optional<LoopPoints> loop;
|
||||
@@ -156,7 +149,7 @@ enum class AddResult {
|
||||
|
||||
// An ordered, id-keyed collection of Samples with content-hash dedup, tier
|
||||
// moves/filtering, and lossless JSON round-trip. Insertion order is preserved
|
||||
// so a future panel (M5) can iterate in stable order.
|
||||
// so a panel can iterate in stable order.
|
||||
class BankModel {
|
||||
public:
|
||||
// Adds a sample. Enforces the relative-paths-only invariant and dedups by
|
||||
@@ -168,16 +161,14 @@ public:
|
||||
bool remove(const std::string& id);
|
||||
|
||||
// Replaces the sample carrying `id` IN PLACE (preserving its position in
|
||||
// insertion order), with `updated`. Used by M10 re-capture-from-source: a
|
||||
// provenanced sample's file is regenerated and its metadata (relativePath,
|
||||
// contentHash, levels, timestamp, ...) refreshed while its identity (id) and
|
||||
// slot are kept, so the bank panel shows the same tile updated rather than a
|
||||
// reordered new entry. `updated.id` should equal `id` (the caller keeps the id
|
||||
// stable); a differing id is written through as given (the caller's contract).
|
||||
// Does NOT dedup — an in-place refresh of one entry is not a new insert, so the
|
||||
// collapse-by-hash rule (which guards NEW inserts) does not apply. Returns false
|
||||
// (no mutation) if `id` is absent or `updated.relativePath` is absolute
|
||||
// (the relative-paths-only invariant still holds for the replacement).
|
||||
// insertion order) with `updated`. Used by re-capture-from-source: a
|
||||
// provenanced sample's file is regenerated and its metadata refreshed while
|
||||
// its identity (id) and slot are kept, so the panel shows the same tile
|
||||
// updated rather than a reordered new entry. `updated.id` should equal `id`;
|
||||
// a differing id is written through as given. Does NOT dedup — an in-place
|
||||
// refresh is not a new insert, so collapse-by-hash (which guards inserts)
|
||||
// does not apply. Returns false (no mutation) if `id` is absent or
|
||||
// `updated.relativePath` is absolute (relative-paths-only still holds here).
|
||||
bool updateInPlace(const std::string& id, const Sample& updated);
|
||||
|
||||
// Returns the sample with `id`, or nullptr if absent. The pointer is
|
||||
|
||||
Reference in New Issue
Block a user