// native_bridge/juce_fx/JuceFxEngine.h // JUCE AudioProcessorGraph engine (G1): đọc input ring → graph (rỗng) → // ghi output ring. Tách khỏi loop để G2 chỉ thêm plugin vào graph. #pragma once #include #include #include #include class JuceFxEngine { public: JuceFxEngine(); ~JuceFxEngine(); // Không copy. JuceFxEngine(const JuceFxEngine&) = delete; JuceFxEngine& operator=(const JuceFxEngine&) = delete; // Tạo graph mới (input node -> [VST3 theo chain] -> output node). // sampleRate/blockSize đổi → teardown graph cũ + prepare lại (validate // header G1). blockSize là kích thước mỗi SHM block (256). void prepare(uint32_t sampleRate, uint32_t blockSize); // G2: đặt chain (mảng JSON fx_chain) trước prepare — các slot bypass / // không phải vst3 / load fail chạy passthrough (latency 0). void setChain(const std::string& chainJson); // Audio thread: xử lý n mẫu stereo in-place (n <= blockSize * FXRT_IN_SLOTS). void process(float* inL, float* inR, uint32_t n); // Graph latency samples (G1 chain rỗng = 0; G2 = getLatencySamples thật). uint32_t latencySamples() const; // Latency thật từng slot theo thứ tự chain (0 = skip/bypass/fail). std::vector entryLatencies() const; void shutdown(); private: struct Slot; // G2: một mục fx_chain (type/path/presetB64/bypass) struct Impl; std::unique_ptr impl_; };