feat(capture): bindable capture family — master/tracks/items/razor (M7)
Four wet capture actions route to OfflineRenderBackend (snapshot/restore RENDER_*, 32-bit float), produce a Sample, add to the bank, persist. Pure render_settings maps source mode to RENDER_SETTINGS and parses P_RAZOREDITS (tested). No arrange insertion. True dry deferred to M10.
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
// render_settings.cpp — pure logic for the M7 capture action family. See header.
|
||||
// NO REAPER types; unit-tested by tests/test_render_settings.cpp.
|
||||
|
||||
#include "render_settings.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace reasampler {
|
||||
|
||||
RenderSettingsChoice renderSettingsFor(SourceMode mode, double /*wetDry*/) {
|
||||
// All M7 actions are wet-only. `wetDry` is accepted so CaptureRequest.wetDry
|
||||
// remains the seam for future M10 dry work, but it does not affect the mapping.
|
||||
RenderSettingsChoice c;
|
||||
|
||||
switch (mode) {
|
||||
case SourceMode::MasterMix:
|
||||
case SourceMode::TimeSelection:
|
||||
// Master IS the mix — wet-only; &(1|2)==0, no source bits.
|
||||
c.settings = kRenderMasterMix;
|
||||
c.supported = true;
|
||||
return c;
|
||||
|
||||
case SourceMode::SelectedTracks:
|
||||
// Selected tracks via master (&128) — wet (post-FX). Header ~3041.
|
||||
c.settings = kRenderSelTracksViaMaster;
|
||||
c.supported = true;
|
||||
return c;
|
||||
|
||||
case SourceMode::SelectedItems:
|
||||
// Selected media items, rendered to ONE file (single-file bit) so a
|
||||
// multi-item selection yields a single bank entry, not N wavs.
|
||||
c.settings = kRenderSelItems | kRenderSingleFile;
|
||||
c.supported = true;
|
||||
return c;
|
||||
|
||||
case SourceMode::RazorArea:
|
||||
// Render razor edits to ONE file (same single-file rationale as items).
|
||||
c.settings = kRenderRazorEdits | kRenderSingleFile;
|
||||
c.supported = true;
|
||||
return c;
|
||||
|
||||
case SourceMode::Realtime:
|
||||
// Not an offline-render source — the realtime backend (M8) owns it.
|
||||
c.settings = kRenderMasterMix;
|
||||
c.supported = false;
|
||||
return c;
|
||||
}
|
||||
// Unreachable for a valid enum; fail closed (unsupported) rather than render.
|
||||
c.supported = false;
|
||||
return c;
|
||||
}
|
||||
|
||||
std::vector<RazorRange> parseRazorEdits(const std::string& razorString) {
|
||||
std::vector<RazorRange> ranges;
|
||||
std::istringstream in(razorString);
|
||||
|
||||
// The string is space-separated TRIPLES: <start> <end> <envGuidString>.
|
||||
// A track-audio area's third token is the literal two-char string `""`; an
|
||||
// envelope-lane area's is a GUID `{…}`. We keep only track-audio triples.
|
||||
std::string startTok, endTok, guidTok;
|
||||
while (in >> startTok >> endTok >> guidTok) {
|
||||
// Envelope-lane areas carry a real GUID; skip them (M7 = track audio).
|
||||
// A track-audio area's GUID token is the empty quoted string `""`.
|
||||
if (guidTok != "\"\"") continue;
|
||||
|
||||
// Parse the two time tokens. std::stod throws on garbage — guard so one
|
||||
// malformed triple does not abort the whole parse.
|
||||
double start = 0.0, end = 0.0;
|
||||
try {
|
||||
std::size_t sp = 0, ep = 0;
|
||||
start = std::stod(startTok, &sp);
|
||||
end = std::stod(endTok, &ep);
|
||||
// Reject tokens with trailing garbage (e.g. "1.0x") — a partial parse
|
||||
// is a malformed area, not a valid range.
|
||||
if (sp != startTok.size() || ep != endTok.size()) continue;
|
||||
} catch (...) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (end > start) ranges.push_back({start, end}); // drop empty/inverted
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
RazorRange razorUnionBounds(const std::vector<RazorRange>& ranges) {
|
||||
if (ranges.empty()) return {0.0, 0.0};
|
||||
RazorRange u = ranges.front();
|
||||
for (const RazorRange& r : ranges) {
|
||||
if (r.startSeconds < u.startSeconds) u.startSeconds = r.startSeconds;
|
||||
if (r.endSeconds > u.endSeconds) u.endSeconds = r.endSeconds;
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
const std::vector<CaptureActionDef>& captureActionTable() {
|
||||
// Built once (function-local static): four wet-only actions. Tail OFF for all
|
||||
// (exact bounds). Ids are FOREVER-STABLE — never edit a shipped string.
|
||||
// Dry variants deferred to M10; see kRenderPreFaderStems note in the header.
|
||||
static const std::vector<CaptureActionDef> table = {
|
||||
// Master mix — wet only (master IS the mix; no pre-FX concept applies).
|
||||
{"CEREBELLUM_REASAMPLER_CAPTURE_MASTER",
|
||||
"ReaSampler: capture master mix", "master_mix",
|
||||
SourceMode::MasterMix, 1.0},
|
||||
|
||||
// Selected tracks — wet (via master, &128).
|
||||
{"CEREBELLUM_REASAMPLER_CAPTURE_TRACKS_WET",
|
||||
"ReaSampler: capture selected tracks", "tracks_wet",
|
||||
SourceMode::SelectedTracks, 1.0},
|
||||
|
||||
// Selected items — wet, single file (&32 | single-file).
|
||||
{"CEREBELLUM_REASAMPLER_CAPTURE_ITEMS_WET",
|
||||
"ReaSampler: capture selected items", "items_wet",
|
||||
SourceMode::SelectedItems, 1.0},
|
||||
|
||||
// Razor area — wet, single file (&4096 | single-file).
|
||||
{"CEREBELLUM_REASAMPLER_CAPTURE_RAZOR_WET",
|
||||
"ReaSampler: capture razor area", "razor_wet",
|
||||
SourceMode::RazorArea, 1.0},
|
||||
};
|
||||
return table;
|
||||
}
|
||||
|
||||
} // namespace reasampler
|
||||
Reference in New Issue
Block a user