Resolve ReaSampler 9000 samples against the instance's own project, not the focused tab
sampleRoots matches getReaperParent(3) among EnumProjects' open projects; every instrument sample read goes through an ordered root list (one root today) so a later temp-bank root slots in after it.
This commit is contained in:
@@ -17,10 +17,10 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "core/capture/capture_paths.h" // resolveBankFile (shared path resolution)
|
||||
#include "core/capture/wav_codec.h" // parseWavLayout, extractFloatFrames (shared WAV parse)
|
||||
#include "core/instrument/map/bank_sync.h" // pure decisions: parseBankGeneration, consumeDecision
|
||||
#include "core/instrument/map/sample_map.h" // refs resolve, buildSampleData (self-contained)
|
||||
#include "core/instrument/map/sample_roots.h" // readFromFirstRoot (own-project resolution)
|
||||
#include "core/util/file_bytes.h" // shared whole-file loader
|
||||
#include "core/wire/assignment_request.h" // decodeAssignmentRequest (request wire parse)
|
||||
#include "core/wire/sample_usage.h" // usage publish plan + wire (prune-protection seam)
|
||||
@@ -32,7 +32,6 @@ using namespace instrument::map; // resolution + bank-sync vocabulary this TU
|
||||
using namespace reasampler::wire; // assignment_request + sample_usage wire records
|
||||
using capture::extractFloatFrames;
|
||||
using capture::parseWavLayout;
|
||||
using capture::resolveBankFile;
|
||||
using capture::WavLayout;
|
||||
using util::readFileBytes;
|
||||
|
||||
@@ -58,16 +57,15 @@ std::string mintUsageInstanceGuid() {
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
// Resolves a project-relative WAV path, reads + decodes it (file I/O, off-thread only),
|
||||
// and applies the cross-mode channel policy for `mode` (mono downmix; stereo -> dual-mono
|
||||
// for a mono source, L/R for a stereo source — see decodeChannels). Returns nullopt on any
|
||||
// resolve/read/decode failure — the caller plays silence.
|
||||
std::optional<DecodedPcm> decodeRelative(const std::string& projectDir,
|
||||
// Resolves a project-relative WAV path against the instance's sample roots, reads + decodes
|
||||
// it (file I/O, off-thread only), and applies the cross-mode channel policy for `mode` (mono
|
||||
// downmix; stereo -> dual-mono for a mono source, L/R for a stereo source — see
|
||||
// decodeChannels). Returns nullopt on any resolve/read/decode failure — the caller plays
|
||||
// silence.
|
||||
std::optional<DecodedPcm> decodeRelative(const std::vector<std::string>& roots,
|
||||
const std::string& relativePath,
|
||||
ChannelMode mode) {
|
||||
const std::string abs = resolveBankFile(projectDir, relativePath);
|
||||
if (abs.empty()) return std::nullopt;
|
||||
const std::vector<std::uint8_t> bytes = readFileBytes(abs);
|
||||
const std::vector<std::uint8_t> bytes = readFromFirstRoot(roots, relativePath, readFileBytes);
|
||||
const WavLayout layout = parseWavLayout(bytes);
|
||||
if (!layout.valid) return std::nullopt;
|
||||
std::vector<AudioSample> interleaved =
|
||||
@@ -82,9 +80,9 @@ std::optional<DecodedPcm> decodeRelative(const std::string& projectDir,
|
||||
// never be built from a different fold than the one the user is hearing.
|
||||
BuiltCapture buildFromRef(const SelectedSample& sel,
|
||||
const InstrumentParams& params,
|
||||
const std::string& projectDir,
|
||||
const std::vector<std::string>& roots,
|
||||
ChannelMode mode, int renderRate) {
|
||||
std::optional<DecodedPcm> pcm = decodeRelative(projectDir, sel.relativePath, mode);
|
||||
std::optional<DecodedPcm> pcm = decodeRelative(roots, sel.relativePath, mode);
|
||||
if (!pcm) return {};
|
||||
if (!sourceRateSupported(pcm->sampleRate, renderRate)) return {std::nullopt, true};
|
||||
SampleData sample =
|
||||
@@ -125,7 +123,7 @@ std::string ReaSamplerProcessor::reloadInstrument() {
|
||||
// (getState filters via retainRefs to what the instance plays).
|
||||
refs = sampleRefs_; // snapshot for the decode below (outside the refs lock)
|
||||
}
|
||||
const std::string projectDir = bridge_.activeProjectDir();
|
||||
const std::vector<std::string> roots = bridge_.sampleRoots();
|
||||
// Governs how the WAV decodes (mono downmix vs 2-channel); auto-defaulted from the
|
||||
// capture's own channel count below, before the decode.
|
||||
ChannelMode mode = channelMode();
|
||||
@@ -152,7 +150,7 @@ std::string ReaSamplerProcessor::reloadInstrument() {
|
||||
channelModeExplicit_);
|
||||
mode = channelMode_;
|
||||
}
|
||||
BuiltCapture decoded = buildFromRef(*sel, params, projectDir, mode, hostRenderRate());
|
||||
BuiltCapture decoded = buildFromRef(*sel, params, roots, mode, hostRenderRate());
|
||||
rateRefused = decoded.rateRefused;
|
||||
if (decoded.sample) {
|
||||
sample = std::move(*decoded.sample);
|
||||
@@ -220,7 +218,7 @@ BuiltCapture ReaSamplerProcessor::bakeSnapshot(int renderRate) {
|
||||
if (!sel) return {};
|
||||
// No live block is attached: the bake renders the stored parameter set, which is what
|
||||
// every knob has already written, rather than whatever the audio thread is observing.
|
||||
return buildFromRef(*sel, params, bridge_.activeProjectDir(), channelMode(), renderRate);
|
||||
return buildFromRef(*sel, params, bridge_.sampleRoots(), channelMode(), renderRate);
|
||||
}
|
||||
|
||||
void ReaSamplerProcessor::adoptBakedCapture(const SampleRefEntry& entry,
|
||||
|
||||
Reference in New Issue
Block a user