7b530193b2
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.
124 lines
4.8 KiB
C++
124 lines
4.8 KiB
C++
// 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
|