3.4 KiB
3.4 KiB
G3 — 1 clock: PDC latency thật + playhead engine-derived (kết quả)
Ngày: 2026-08-28. Plan: JUCE_LATENCY_PLAN.md G3. Option A — 1 clock.
Nội dung
- Bridge báo processed samples qua lat ring slot đặc biệt
0xFFFFFFFE(JuceFxLoop.cpp, mỗi block sau++processed):samples = processed*n(n=curBlock). Python_lat_draintách slot này riêng →self.processed(KHÔNG vàolatenciesdict — tổng chain không đổi). Thêmget_processed(). - WS latency message thêm
processed(plugins.py): gửi khiprocessedđổi (mỗi block ~5.33ms), bỏ gate chỉ theo total — total chỉ đổi khi chain đổi. - Playhead engine-derived (
app.jsx): khi FX active và có anchor,position = startOffset + (processed - anchor - latencyTotal)/sr(đã trừ latency → bám vị trí mẫu NGHE được; pre-roll tự giữ tại startOffset qua clamp). Anchor = raw processed tại play/wrap start (fxRtAnchorProcessedgọi từ__fxRtPlayheadFreeze, mọi play/resume path đều đi qua). Bỏ freeze/snap khi active; fallback wall-clock khi không active. Áp dụng 4 chỗ: bridge position block, sub-tab_ph, sub-tabwallTime, main branch_playheadSec→setCurrentTime. - Worklet nhận latency thật qua port message
{type:'latency', samples};clear_queue('loop'):wrapFadeBlocks = outQueue.length + ceil(latencySamples/BLOCK)— align processed-tail, crossfade đúng seam end→start kể cả khi FX latency (pureComp 2108 mẫu) còn in-flight trong bridge.
Verify (đã chạy)
- Build:
cmake --build native_bridge/build_juce --config Release --target juce_fx_bridgeOK. Copysrc-tauri/binaries/juce_fx_bridge-x86_64-pc-windows-msvc.exe, SHA256 khớp bản build (07621b81...). - Probe SHM thật (
native_bridge/debug/g3_probe_check.py, JUCE bridge quaSF_JUCE_FX_BRIDGE_PATH, chain pureComp, SR 48k, 400 block ~2.1s):latenciesdict KHÔNG đổi:{0: 2108}trước/sau — processed tách riêng không làm sai tổng chain.processedtiến 0 → 102400 (= 400 block × 256 mẫu) — bridge báo đúng.
- Cú pháp:
python -m py_compilefx_realtime.py + plugins.py OK;node --checkworklet OK;babel(node_modules) parse app.jsx OK (node thuần không hiểu JSX — dùng babel, exit 0). - Fake session (object.new, không shm):
get_processed()→ None,get_latencies()→{0: 2108}— path không-SHM an toàn.
Done-when trạng thái
- ✅ processed tách riêng, tổng latency chain không đổi (probe)
- ✅ playhead công thức engine-derived đã cài đủ 4 chỗ; freeze/snap vô hiệu khi active (code path)
- ⏳ Chưa verify bằng tai: 100-pass loop không click với crossfade tối thiểu; playhead bám vị trí mẫu trong app thật (cần user chạy GUI + nghe).
Ghi chú
- Probe check script giữ ở
native_bridge/debug/g3_probe_check.py(chạy lại:python native_bridge/debug/g3_probe_check.py). - BufferError lúc thoát (
cannot close exported pointers) là quirk teardown shared_memory Python 3.13, không ảnh hưởng kết quả. - Latency WS ~5.33ms/msg = 187 msg/s — nhỏ so với pump audio; nếu cần tiết
kiệm sau này: batch processed 4 block/lần (giảm 4×) —
ponytail: chỉ làm khi có bằng chứng quá tải.