S4 Tier 0: the bank plays — VST3 marshals MIDI to the S3 core, reads the live bank + resolves WAV the M4 way, mono downmix, lock-free load handoff, LICE sample-pick

This commit is contained in:
2026-07-26 16:43:04 -04:00
parent b0fc052113
commit 0cde457224
24 changed files with 1239 additions and 302 deletions
+12 -22
View File
@@ -1,18 +1,21 @@
// bridge_marshal.h — PURE marshalling helpers for the REAPER VST-host bridge read
// (Phase S1). NO VST3, NO REAPER types at the boundary.
// bridge_marshal.h — PURE marshalling helper for the REAPER VST-host bridge read.
// NO VST3, NO REAPER types at the boundary.
//
// The bridge shell (reaper_bridge.cpp) resolves REAPER API functions by name over the
// host callback and invokes them; the fiddly-and-easy-to-get-wrong parts around those
// calls — interpreting GetProjExtState's int return, walking EnumProjExtState's
// index-until-false contract into a key set, and extracting a single value out of the
// "reasampler" bank JSON — are pure and unit-tested here. Mirror of capture_paths /
// wav_trim splitting the arithmetic out of a REAPER-facing shell.
// host callback and invokes them; the one fiddly-and-easy-to-get-wrong part around
// GetProjExtState — interpreting its int return against the buffer it filled — is pure
// and unit-tested here. Mirror of capture_paths / wav_trim splitting the arithmetic out
// of a REAPER-facing shell.
//
// The S1 spike ALSO carried a string-scan JSON reader (extractJsonStringField) as a
// stand-in until the instrument could parse the bank properly. S4 retired it: the
// instrument now parses the "reasampler" bank blob through the SHARED bank_book /
// bank_model JSON path (sample_map.cpp), so there is no second JSON parser. This module
// is back to its one honest job — the API-return decode.
//
// Verified against vendor/reaper-sdk/sdk/reaper_plugin_functions.h:
// int GetProjExtState (ReaProject*, extname, key, valOutNeedBig, valOutNeedBig_sz);
// -- returns the length written (0 when the key is absent).
// bool EnumProjExtState(ReaProject*, extname, idx, keyOut, keyOut_sz, valOut, valOut_sz);
// -- returns false when idx is past the last entry.
#pragma once
@@ -31,17 +34,4 @@ namespace reasampler::vst {
std::optional<std::string> decodeGetProjExtState(int apiReturn,
const std::string& buffer);
// Extract the string value for `key` out of a flat one-level JSON object — the shape
// persist.cpp writes under the "reasampler" ext-state (e.g. the bank blob's top-level
// fields). This is a deliberately small, dependency-free reader for the SPIKE's
// "read a known value" proof, NOT a general JSON parser: it finds "key" as an object
// member and returns its string value, handling the common escapes (\" \\ \n \t \/).
// Returns nullopt if the key is absent or its value is not a string.
//
// The real instrument (S4) will read the bank index through the shared bank_model JSON
// path, not this helper; this exists only to give the S1 bridge read a testable,
// REAPER-free decode step.
std::optional<std::string> extractJsonStringField(const std::string& json,
const std::string& key);
} // namespace reasampler::vst