feat(build): Phase 7 — verify 10 mục + fix export MIDI thiếu delta-time + fix WAV float32

This commit is contained in:
2026-08-21 15:29:47 +07:00
parent a667d0354f
commit bcd8e37e86
4 changed files with 2194 additions and 2164 deletions
+1
View File
@@ -275,6 +275,7 @@ def _build_midi_file(req: MidiExportRequest) -> bytes:
events.sort(key=lambda e: (e[0], 0 if e[1] == 0x80 else 1))
body = bytearray()
name_bytes = (tr.name or "Track").encode("utf-8", "replace")[:255]
_write_vlq(body, 0) # delta-time 0 bat buoc truoc meta event - file chuan MIDI (mido/DAW parse duoc)
body.append(0xFF); body.append(0x03); body.append(len(name_bytes)); body.extend(name_bytes)
last = 0
for tick, status, pitch, vel in events:
+6 -3
View File
@@ -11479,7 +11479,7 @@ const MasteringKnob = ({ param, min, max, value, unit, label, color, onChange, s
};
// ──────────────────────────────────────────────
// UNIFIED FX RACK PANEL (unified_fx_rack_panel.md) — một panel dùng chung,
// UNIFIED FX RACK (unified_fx_rack_panel.md) — một panel dùng chung,
// bind động vào track khi bấm [FX]; mọi thay đổi rebuild graph RIÊNG của track.
// ──────────────────────────────────────────────
const TRACK_FX_META = {
@@ -27337,7 +27337,8 @@ const App = () => {
showToast("Đang trộn âm thanh đa kênh (Offline Mixdown)...", "info");
try {
const targetRate = parseInt(exportSettings.sampleRate);
const bitDepth = parseInt(exportSettings.bitDepth);
const isFloatWav = exportSettings.bitDepth === 'float';
const bitDepth = isFloatWav ? 32 : parseInt(exportSettings.bitDepth);
// MAIN SESSION end time (items trên track main — sections theo bounds) —
// offline render không cắt sớm; MIDI cache (preview) giữ max với cache.
// LOOP export: độ dài chính xác = loopDur (không kéo đuôi, không fade)
@@ -27426,7 +27427,7 @@ const App = () => {
writeString(8, 'WAVE');
writeString(12, 'fmt ');
view.setUint32(16, 16, true);
view.setUint16(20, 1, true);
view.setUint16(20, isFloatWav ? 3 : 1, true);
view.setUint16(22, numExportCh, true);
view.setUint32(24, targetRate, true);
view.setUint32(28, targetRate * bytesPerSample * numExportCh, true);
@@ -27448,6 +27449,8 @@ const App = () => {
view.setUint8(offset, val24 & 0xFF);
view.setUint8(offset + 1, val24 >> 8 & 0xFF);
view.setUint8(offset + 2, val24 >> 16 & 0xFF);
} else if (isFloatWav) {
view.setFloat32(offset, sample, true);
}
offset += bytesPerSample;
}
File diff suppressed because one or more lines are too long