FIX: sửa lỗi hiển thị animation của VU meter
This commit is contained in:
+94
-9
@@ -13900,6 +13900,12 @@ const App = () => {
|
||||
selectedItemIdsRef.current = selectedItemIds;
|
||||
const [currentTime, setCurrentTime] = useState(0);
|
||||
const [isPlaying, setIsPlaying] = useState(false);
|
||||
// Ref theo dõi isPlaying — setTimeout VU trigger (main-midi delayed + section
|
||||
// delayed) check ref này trước khi fire: stop → isPlaying=false → setTimeout
|
||||
// sót không fire → VU không nhảy sau khi âm đã dừng (user: VU vẫn animation
|
||||
// khi hết âm).
|
||||
const isPlayingRef = useRef(false);
|
||||
isPlayingRef.current = isPlaying;
|
||||
const [selectionStart, setSelectionStart] = useState(null);
|
||||
const [selectionEnd, setSelectionEnd] = useState(null);
|
||||
const [selectionFollowsTempo, setSelectionFollowsTempo] = useState(true);
|
||||
@@ -14988,6 +14994,14 @@ const App = () => {
|
||||
const velFactor = typeof velocity === 'number' ? (velocity > 1 ? velocity / 127 : velocity) : 0.8;
|
||||
const peak = Math.min(1.0, Math.max(0.15, velFactor));
|
||||
midiVuActivityRef.current[trackId] = peak;
|
||||
// Log nguồn trigger (rate-limited 1/20 fire): xác định ai còn fire VU khi
|
||||
// âm đã ngừng (user: VU vẫn animation sau khi hết âm).
|
||||
try {
|
||||
const _tf = (window.__trigFrame = (window.__trigFrame || 0) + 1);
|
||||
if (_tf % 20 === 1) {
|
||||
console.log('[VUTrig]', trackId, 'vel=', velocity, 'peak=', peak.toFixed(2), 'play=', isPlaying, 'tab=', activeTabRef.current);
|
||||
}
|
||||
} catch (e) { }
|
||||
};
|
||||
window.triggerMidiVuActivity = triggerMidiVuActivity;
|
||||
|
||||
@@ -19349,6 +19363,9 @@ const App = () => {
|
||||
);
|
||||
// Trigger VU meter flash when the note starts playing
|
||||
setTimeout(() => {
|
||||
// ⚠️ Guard: stop → setTimeout sót không được fire (VU nhảy
|
||||
// sau khi âm đã dừng — user bug 05:45).
|
||||
if (!isPlayingRef.current) return;
|
||||
if (window.triggerMidiVuActivity) {
|
||||
window.triggerMidiVuActivity(track.id, note.velocity || 0.8);
|
||||
}
|
||||
@@ -19480,6 +19497,20 @@ const App = () => {
|
||||
subCh,
|
||||
subTrack.synth_engine
|
||||
);
|
||||
// Trigger VU meter flash đúng nhịp (cả subTrack — VU
|
||||
// section tab + parent track — VU MAIN): MIDI section đi
|
||||
// SF → masterBus.input (không qua sub-node analyser) →
|
||||
// VU track chỉ nhảy qua midiVuActivity. (Bị mất khi
|
||||
// commit gộp — khôi phục fix 00:30/02:00.)
|
||||
setTimeout(() => {
|
||||
// ⚠️ Guard: stop → setTimeout sót không được fire (VU
|
||||
// nhảy sau khi âm đã dừng — user bug 05:45).
|
||||
if (!isPlayingRef.current) return;
|
||||
if (window.triggerMidiVuActivity) {
|
||||
window.triggerMidiVuActivity(subTrack.id, note.velocity || 0.8);
|
||||
window.triggerMidiVuActivity(track.id, note.velocity || 0.8);
|
||||
}
|
||||
}, delay * 1000);
|
||||
} else {
|
||||
const remainingDurMs = (notePlayEndMain - offsetTime) * 1000;
|
||||
window.SonicSF.playNote(
|
||||
@@ -19492,14 +19523,10 @@ const App = () => {
|
||||
subCh,
|
||||
subTrack.synth_engine
|
||||
);
|
||||
}
|
||||
// Trigger VU meter flash đúng nhịp (giống main-track midi 19066)
|
||||
// Cả subTrack (VU section tab) + parent track (VU MAIN — section
|
||||
// item đang play) — midiVuActivity keyed theo track id → trigger
|
||||
// cả 2 để VU main nhảy theo section.
|
||||
if (window.triggerMidiVuActivity) {
|
||||
window.triggerMidiVuActivity(subTrack.id, note.velocity || 0.8);
|
||||
window.triggerMidiVuActivity(track.id, note.velocity || 0.8);
|
||||
if (window.triggerMidiVuActivity) {
|
||||
window.triggerMidiVuActivity(subTrack.id, note.velocity || 0.8);
|
||||
window.triggerMidiVuActivity(track.id, note.velocity || 0.8);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -24932,8 +24959,17 @@ STRICT CONSTRAINTS:
|
||||
const v = Math.abs(data[i] - 128) / 128;
|
||||
if (v > peak) peak = v;
|
||||
}
|
||||
// Deadband: bỏ noise nền (log 06:00 — master peak 0.008 liên tục dù
|
||||
// không âm → master VU nhảy nhẹ mãi)
|
||||
if (peak < 0.01) peak = 0;
|
||||
setMasterVU(peak);
|
||||
setMasterMeterPeak(prev => Math.max(prev * 0.97, peak));
|
||||
// Log master VU khi đang nhảy (chẩn đoán 06:00 — VU nhảy ngoài vùng âm)
|
||||
if (peak > 0.001) {
|
||||
try {
|
||||
console.log('[VU-master] peak=', peak.toFixed(3));
|
||||
} catch (e) { }
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Track VU Meters
|
||||
@@ -24989,20 +25025,69 @@ STRICT CONSTRAINTS:
|
||||
}
|
||||
}
|
||||
|
||||
// MIDI THỰC: đọc từ SF output (âm post-FluidSynth) — thay velocity
|
||||
// trigger (GIẢ — fire lúc schedule — click playhead → re-schedule →
|
||||
// VU nhảy dù âm không ra — log 06:00: midi=0.98 nhưng master=0.008).
|
||||
// Track MIDI đi SF → masterBus (không qua node analyser) → tap tại SF
|
||||
// output gain.
|
||||
let sfAudioPeak = 0;
|
||||
let _sfTapped = false;
|
||||
if (audioPeak <= 0.001) {
|
||||
try {
|
||||
if (window.SonicSF && window.SonicSF.getOutputNode) {
|
||||
const sfNode = window.SonicSF.getOutputNode();
|
||||
if (sfNode) {
|
||||
if (!sfNode.__vuAnalyser) {
|
||||
const _sa = getAudioContext().createAnalyser();
|
||||
_sa.fftSize = 256;
|
||||
_sa.smoothingTimeConstant = 0.2;
|
||||
sfNode.connect(_sa);
|
||||
sfNode.__vuAnalyser = _sa;
|
||||
}
|
||||
_sfTapped = true;
|
||||
const d3 = new Uint8Array(128);
|
||||
sfNode.__vuAnalyser.getByteTimeDomainData(d3);
|
||||
for (let i = 0; i < d3.length; i++) {
|
||||
const v = Math.abs(d3[i] - 128) / 128;
|
||||
if (v > sfAudioPeak) sfAudioPeak = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
// midiVuActivityRef được set bởi triggerMidiVuActivity — cả khi play
|
||||
// MIDI item LẪN khi ARM + nhấn phím MIDI keyboard (preview) — nên VU
|
||||
// nhảy trong cả 2 trường hợp (không chặn bởi isPlaying).
|
||||
let midiPeak = isAudible ? (midiVuActivityRef.current[trackId] || 0) : 0;
|
||||
// SF analyser đã tap → CHỈ dùng âm THỰC (velocity trigger = giả — bỏ)
|
||||
if (_sfTapped) midiPeak = 0;
|
||||
if (midiPeak > 0) {
|
||||
midiVuActivityRef.current[trackId] = midiPeak * 0.90;
|
||||
// Decay nhanh hơn (0.72/frame ≈ tắt sau ~0.35s) — hết note → VU
|
||||
// dừng nhanh, không "vẫn diễn animation" khi không còn âm.
|
||||
midiVuActivityRef.current[trackId] = midiPeak * 0.72;
|
||||
if (midiVuActivityRef.current[trackId] < 0.01) {
|
||||
midiVuActivityRef.current[trackId] = 0;
|
||||
}
|
||||
}
|
||||
// Gộp âm MIDI THỰC vào audioPeak
|
||||
if (sfAudioPeak > audioPeak) audioPeak = sfAudioPeak;
|
||||
// Deadband: bỏ noise nền analyser (log 06:05 — audio=0.008 dù không
|
||||
// âm → VU hiển thị đoạn nhỏ "vẽ nhưng không animation") — hết âm →
|
||||
// VU tắt NGAY LẬP TỨC (user yêu cầu).
|
||||
if (audioPeak < 0.01) audioPeak = 0;
|
||||
|
||||
const peak = Math.max(audioPeak, midiPeak);
|
||||
const db = peak > 0 ? 20 * Math.log10(peak) : -60;
|
||||
|
||||
// Log chẩn đoán VU: CHỈ in khi peak > 0 (VU đang nhảy thật) — xác định
|
||||
// nguồn nào còn nhảy khi playhead ngoài vùng âm (user bug 06:00).
|
||||
if (peak > 0.001) {
|
||||
try {
|
||||
console.log('[VU]', trackId, 'audio=', audioPeak.toFixed(3), 'midi=', midiPeak.toFixed(3), 'key=', key);
|
||||
} catch (e) { }
|
||||
}
|
||||
|
||||
if (peak > 0.001) {
|
||||
if (key.endsWith('_mixer')) {
|
||||
drawMixerVuMeter(canvas, peak);
|
||||
|
||||
Reference in New Issue
Block a user