G2: JUCE VST3 hosting + latency that qua FxLatReport - probe pureComp 2108

This commit is contained in:
2026-08-28 15:28:06 +07:00
parent 091abe5a91
commit c72362e088
6 changed files with 255 additions and 22 deletions
+46 -16
View File
@@ -62,6 +62,22 @@ double jsonNumber(const std::string& s, const std::string& key, double def) {
try { return std::stod(s.substr(p, e - p)); } catch (...) { return def; }
}
// Cắt substring mảng JSON "fx_chain":[...] — như RealtimeFxLoop.cpp.
std::string extractChainJson(const std::string& s) {
std::string k = "\"fx_chain\"";
size_t p = s.find(k);
if (p == std::string::npos) return "";
p = s.find('[', p);
if (p == std::string::npos) return "";
size_t depth = 0, i = p;
for (; i < s.size(); ++i) {
if (s[i] == '[') ++depth;
else if (s[i] == ']') { --depth; if (depth == 0) break; }
}
if (i >= s.size()) return "";
return s.substr(p, i - p + 1);
}
} // namespace
int run_juce_fx_loop(const std::string& jobPath, const std::string& shmName,
@@ -77,7 +93,11 @@ int run_juce_fx_loop(const std::string& jobPath, const std::string& shmName,
const uint32_t sampleRate = (uint32_t)srD;
const double blkD = jsonNumber(job, "block_size", (double)FXRT_BLOCK);
const uint32_t block = (uint32_t)std::max<double>(32.0, std::min<double>(blkD, (double)FXRT_BLOCK));
// G1: fx_chain bỏ qua (chain rỗng). G2: đọc fx_chain -> build graph.
// G2: đọc fx_chain -> build graph (VST3 theo chain). Rỗng = passthrough.
const std::string chainJson = extractChainJson(job);
if (chainJson.empty())
std::cerr << "[JuceFxLoop] no fx_chain in job (empty chain = passthrough)"
<< std::endl;
fxshm::ShmView* v = fxshm::openShm(shmName, sizeof(FxRealtimeIPC));
if (!v) {
@@ -104,25 +124,39 @@ int run_juce_fx_loop(const std::string& jobPath, const std::string& shmName,
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
#endif
// Engine: prepare graph (chain rỗng). sr/block từ job; header là nguồn
// thật (engine ghi lúc tạo SHM) — nếu khác, lấy header.
// Engine: prepare graph (chain theo fx_chain). sr/block từ job; header là
// nguồn thật (engine ghi lúc tạo SHM) — nếu khác, lấy header.
uint32_t curSr = sampleRate;
uint32_t curBlock = block;
JuceFxEngine engine;
engine.setChain(chainJson);
if (ipc->h.sampleRate) curSr = ipc->h.sampleRate;
if (ipc->h.blockSize) curBlock = ipc->h.blockSize;
engine.prepare(curSr, curBlock);
std::cerr << "[JuceFxLoop] prepared sr=" << curSr << " block=" << curBlock
<< " latency=" << engine.latencySamples() << std::endl;
// Report latency ban đầu (slot 0 = tổng chain).
{
const uint32_t ls = ipc->h.latWrite & (FXRT_LAT_SLOTS - 1);
ipc->lat[ls].slot = 0;
ipc->lat[ls].samples = engine.latencySamples();
MemoryBarrier();
ipc->h.latWrite++;
}
// Report latency ban đầu: từng slot (giữ giao thức FxLatReport cũ — engine
// Python sum → total). Chain rỗng → slot 0 = 0 (khớp G1).
auto reportLatencies = [&]() {
const auto lats = engine.entryLatencies();
if (lats.empty()) {
const uint32_t ls = ipc->h.latWrite & (FXRT_LAT_SLOTS - 1);
ipc->lat[ls].slot = 0;
ipc->lat[ls].samples = 0;
MemoryBarrier();
ipc->h.latWrite++;
} else {
for (size_t i = 0; i < lats.size(); ++i) {
const uint32_t ls = ipc->h.latWrite & (FXRT_LAT_SLOTS - 1);
ipc->lat[ls].slot = (uint32_t)i;
ipc->lat[ls].samples = lats[i];
MemoryBarrier();
ipc->h.latWrite++;
}
}
};
reportLatencies();
ipc->h.state = FXRT_STATE_READY;
std::cerr << "[JuceFxLoop] ready" << std::endl;
@@ -159,11 +193,7 @@ int run_juce_fx_loop(const std::string& jobPath, const std::string& shmName,
curSr = ipc->h.sampleRate;
curBlock = ipc->h.blockSize;
engine.prepare(curSr, curBlock);
const uint32_t ls = ipc->h.latWrite & (FXRT_LAT_SLOTS - 1);
ipc->lat[ls].slot = 0;
ipc->lat[ls].samples = engine.latencySamples();
MemoryBarrier();
ipc->h.latWrite++;
reportLatencies();
std::cerr << "[JuceFxLoop] re-prepared sr=" << curSr
<< " block=" << curBlock
<< " latency=" << engine.latencySamples() << std::endl;