V45.28: fix wobble preview VST2 loop/tremolo khi nhan chord - ring worklet bridgeAudioWorklet 32->48 block (~256ms) hap thu stall render loop C++ khi chord nhieu voice (stall >170ms -> underrun lap lai fade ve 0 nghe nhu wobble; 16->32 V45.27 da dung crackle, 32 chua du cho chord); overrun crossfade tich luy moi block drop cong 256 mau cap 1024 (~21ms) thay vi co dinh 64 mau (1.3ms qua ngan -> blip/wow khi drop loat block o chord nhieu voice). v=202608311820
This commit is contained in:
@@ -32,7 +32,7 @@
|
|||||||
console.warn('[BridgeAudioNode] AudioWorklet unavailable — ScriptProcessor fallback');
|
console.warn('[BridgeAudioNode] AudioWorklet unavailable — ScriptProcessor fallback');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
var url = '/static/js/services/bridgeAudioWorklet.js?v=202608311809';
|
var url = '/static/js/services/bridgeAudioWorklet.js?v=202608311820';
|
||||||
_ctx.audioWorklet.addModule(url).then(function () {
|
_ctx.audioWorklet.addModule(url).then(function () {
|
||||||
if (!_initialized) return; // disconnect() happened while loading
|
if (!_initialized) return; // disconnect() happened while loading
|
||||||
if (_useWorklet) return; // already set up (init retry)
|
if (_useWorklet) return; // already set up (init retry)
|
||||||
|
|||||||
@@ -1,24 +1,28 @@
|
|||||||
// app/static/js/services/bridgeAudioWorklet.js
|
// app/static/js/services/bridgeAudioWorklet.js
|
||||||
// VSTi crackle fix: audio sink chay tren audio thread (khong jank main thread).
|
// VSTi crackle fix: audio sink chay tren audio thread (khong jank main thread).
|
||||||
// - Ring block 256 mau, toi da 32 block (~170ms @48k) — hap thu jitter pump
|
// - Ring block 256 mau, toi da 48 block (~256ms @48k) — hap thu jitter pump
|
||||||
// (V45.27: 16->32 de dung crackle VST2 loop/tremolo — render loop C++ bi
|
// (V45.28: 32->48 de dung wobble VST2 loop/tremolo khi nhan chord — chord
|
||||||
// stall khi instrument xu li loop/tremolo nang CPU; 8->16 truoc do da dung
|
// nhieu voice -> render loop C++ stall dai hon ~170ms -> underrun lap lai
|
||||||
// tremolo crackle, 16 van chua du cho stall >85ms). Flush o play start
|
// (fade ve 0) nghe nhu wobble; 8->16 (V45) dung tremolo crackle, 16->32
|
||||||
// (app.jsx) xoa ring nen do tre khong tang: ring thuong can o preview.
|
// (V45.27) dung crackle, 32 van chua du cho stall chord). Flush o play
|
||||||
|
// start (app.jsx) xoa ring nen do tre khong tang: ring thuong can o preview.
|
||||||
// - Underrun: fade ve 0 thay vi click (hard silence).
|
// - Underrun: fade ve 0 thay vi click (hard silence).
|
||||||
// - Resume sau silence: fade vao tu 0.
|
// - Resume sau silence: fade vao tu 0.
|
||||||
// - Overrun: drop block cu nhat + crossfade 64 mau tai diem drop (het click).
|
// - Overrun: drop block cu nhat + crossfade tich luy — moi block drop cong
|
||||||
|
// 256 mau fade, cap 1024 (~21ms) — crossfade dai de tranh blip/wow khi
|
||||||
|
// chord nhieu voice bi drop loat block (64 mau = 1.3ms qua ngan).
|
||||||
// - Stats: dem overrun/underrun, gui ve main thread moi ~0.5s — kiem tra
|
// - Stats: dem overrun/underrun, gui ve main thread moi ~0.5s — kiem tra
|
||||||
// con crackle nao la do ring can (underrun) hay ring tran (overrun).
|
// con crackle nao la do ring can (underrun) hay ring tran (overrun).
|
||||||
class BridgeAudioSinkProcessor extends AudioWorkletProcessor {
|
class BridgeAudioSinkProcessor extends AudioWorkletProcessor {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this._ring = [];
|
this._ring = [];
|
||||||
this._MAX = 32;
|
this._MAX = 48;
|
||||||
this._gain = 1.0;
|
this._gain = 1.0;
|
||||||
this._lastOutL = 0.0;
|
this._lastOutL = 0.0;
|
||||||
this._lastOutR = 0.0;
|
this._lastOutR = 0.0;
|
||||||
this._skipFade = 0; // >0: crossfade dang chay sau overrun drop
|
this._skipFade = 0; // >0: con lai cua crossfade dang chay sau overrun drop
|
||||||
|
this._fadeLen = 0; // tong chieu dai crossfade hien tai (cap 1024)
|
||||||
this._skipFromL = 0.0;
|
this._skipFromL = 0.0;
|
||||||
this._skipFromR = 0.0;
|
this._skipFromR = 0.0;
|
||||||
this._wasUnderrun = false;
|
this._wasUnderrun = false;
|
||||||
@@ -31,14 +35,18 @@ class BridgeAudioSinkProcessor extends AudioWorkletProcessor {
|
|||||||
this._ring.push({ l: m.l, r: m.r });
|
this._ring.push({ l: m.l, r: m.r });
|
||||||
while (this._ring.length > this._MAX) {
|
while (this._ring.length > this._MAX) {
|
||||||
// overrun: bo block cu nhat; lan consume toi se crossfade ranh gioi
|
// overrun: bo block cu nhat; lan consume toi se crossfade ranh gioi
|
||||||
|
// (tich luy: moi block drop cong 256 mau fade, cap 1024 — crossfade
|
||||||
|
// dai hon de tranh blip/wow khi drop loat block o chord nhieu voice)
|
||||||
this._ring.shift();
|
this._ring.shift();
|
||||||
this._skipFade = 64;
|
this._skipFade = Math.min(this._skipFade + 256, 1024);
|
||||||
|
this._fadeLen = this._skipFade;
|
||||||
this._stats.overruns++;
|
this._stats.overruns++;
|
||||||
}
|
}
|
||||||
} else if (m.type === 'flush') {
|
} else if (m.type === 'flush') {
|
||||||
this._ring.length = 0;
|
this._ring.length = 0;
|
||||||
this._gain = 1.0;
|
this._gain = 1.0;
|
||||||
this._skipFade = 0;
|
this._skipFade = 0;
|
||||||
|
this._fadeLen = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -56,8 +64,9 @@ class BridgeAudioSinkProcessor extends AudioWorkletProcessor {
|
|||||||
const avail = blk.l.length;
|
const avail = blk.l.length;
|
||||||
const take = Math.min(avail, n - w);
|
const take = Math.min(avail, n - w);
|
||||||
if (this._skipFade > 0) {
|
if (this._skipFade > 0) {
|
||||||
|
const done = this._fadeLen - this._skipFade;
|
||||||
for (let i = 0; i < take; i++) {
|
for (let i = 0; i < take; i++) {
|
||||||
const t = i / 64;
|
const t = (done + i) / this._fadeLen;
|
||||||
L[w + i] = (this._lastOutL * (1 - t) + blk.l[i] * t) * this._gain;
|
L[w + i] = (this._lastOutL * (1 - t) + blk.l[i] * t) * this._gain;
|
||||||
R[w + i] = (this._lastOutR * (1 - t) + blk.r[i] * t) * this._gain;
|
R[w + i] = (this._lastOutR * (1 - t) + blk.r[i] * t) * this._gain;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
<script src="/static/js/services/soundfontStorage.js?v=202608290945"></script>
|
<script src="/static/js/services/soundfontStorage.js?v=202608290945"></script>
|
||||||
<script src="/static/js/services/soundfontPlayer.js?v=202608290945"></script>
|
<script src="/static/js/services/soundfontPlayer.js?v=202608290945"></script>
|
||||||
<script src="/static/js/services/nativeBridgeService.js?v=202608291510"></script>
|
<script src="/static/js/services/nativeBridgeService.js?v=202608291510"></script>
|
||||||
<script src="/static/js/services/bridgeAudioNode.js?v=202608311809"></script>
|
<script src="/static/js/services/bridgeAudioNode.js?v=202608311820"></script>
|
||||||
<script src="/static/js/services/unifiedMidiRouter.js?v=202608311756"></script>
|
<script src="/static/js/services/unifiedMidiRouter.js?v=202608311756"></script>
|
||||||
<script src="/static/js/services/audioRoutingEngine.js?v=202608290945"></script>
|
<script src="/static/js/services/audioRoutingEngine.js?v=202608290945"></script>
|
||||||
<script src="/static/js/services/aiGateway.js?v=202608290945"></script>
|
<script src="/static/js/services/aiGateway.js?v=202608290945"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user