M19: fix fx PWR OFF->ON crackle/wobble — wake clear_queue play + cho started (het phat audio cu + underrun)

This commit is contained in:
2026-09-07 08:54:47 +07:00
parent 7b27065ed8
commit e4c678aabd
4 changed files with 47 additions and 11 deletions
+26 -5
View File
@@ -2006,13 +2006,34 @@ async function fxRtStart() {
fxRt.inQueue = [];
fxRt.outL = null;
fxRt.outR = null;
// Không clear_queue (hole ~128ms resumeFill=FILL) — chỉ flush engine ring
// (bỏ backlog stale); worklet drop output stale tới flush_done.
// M19 Bug A fix: wake PWR ON sau warm-bypass. Trước đây chỉ flush engine
// ring + fadedIn=true NGAY — nhưng worklet lúc bypass rời graph không
// process: outQueue còn ~FILL block audio CŨ + hasStarted=true (không gửi
// 'started' lại) → reconnect xong phát stale block ngay + crossfade dry→fx
// khi wet chưa có audio mới → gap → underrun/wobble (log u4-u8). Giờ giống
// cold start: clear_queue mode 'play' (worklet wipe queue + resumeFill=FILL
// + hasStarted=false → gửi 'started' khi đủ FILL block MỚI) → crossfade +
// PDC chỉ khi audio mới thực sự chảy. Engine flush vẫn giữ (bỏ backlog).
if (fxRt.ws.readyState === 1) { try { fxRt.ws.send(JSON.stringify({ cmd: 'flush' })); } catch (e) {} }
try { fxRtPushAllParams(); } catch (e) {}
fxRt.fadedIn = true;
fxRtCrossfade(true, wToken);
setTimeout(() => { if (wToken === fxRt.startToken) fxRtApplyPdc(); }, 250);
try { fxRt.node.port.postMessage({ type: 'clear_queue', mode: 'play' }); } catch (e) {}
fxRt.fadedIn = false;
// port.onmessage hiện tại là closure của cold-start cũ — guard 'started'
// bằng token CŨ (≠ wToken) nên sẽ bỏ qua. Hook tạm bắt 'started' cho wake
// (crossfade + PDC đúng lúc), forward mọi message khác; restore sau 3s.
const _wOld = fxRt.node.port.onmessage;
const _wHook = (ev) => {
try {
if (ev.data && ev.data.type === 'started' && wToken === fxRt.startToken) {
fxRt.fadedIn = true;
fxRtCrossfade(true, wToken);
setTimeout(() => { if (wToken === fxRt.startToken) fxRtApplyPdc(); }, 250);
}
} catch (e) {}
try { _wOld(ev); } catch (e) {}
};
fxRt.node.port.onmessage = _wHook;
setTimeout(() => { try { if (fxRt.node && fxRt.node.port.onmessage === _wHook) fxRt.node.port.onmessage = _wOld; } catch (e) {} }, 3000);
return;
}
}