fix: normalize peak audio render offline chống clip polyphony; TCP wheel điều chỉnh volume/pan

This commit is contained in:
2026-08-17 20:04:34 +07:00
parent dc331f39d8
commit bbde74f1a7
5 changed files with 344 additions and 210 deletions
+30
View File
@@ -39,6 +39,35 @@ def find_bridge_exe() -> str:
return ""
def normalize_audio_peak(audio, target_db=-3.0):
"""Scale audio (numpy array, peak) về target_db nếu vượt; giữ nguyên nếu dưới.
Chống clip do note MIDI chồng (polyphony) — spec midi_polyphony_loudness §II:
render offline nhiều note đồng thời → tổng biên độ vượt 0dBFS → WAV vỡ đỉnh
(hard clip, méo harmonic) trước khi tới client; limiter master không cứu được.
"""
try:
import numpy as np
peak = float(np.max(np.abs(audio))) if audio.size else 0.0
limit = 10 ** (target_db / 20)
if peak > limit and peak > 1e-9:
return audio * (limit / peak)
except Exception:
pass
return audio
def normalize_peak_file(path, target_db=-3.0):
"""Post-render WAV: scan peak, vượt target_db → scale toàn file (giữ format)."""
try:
info = sf.info(path)
data, sr = sf.read(path, dtype="float32", always_2d=True)
data = normalize_audio_peak(data, target_db)
sf.write(path, data, sr, subtype=info.subtype)
except Exception:
pass
def classify_instrument(path: str) -> int:
"""InstrumentType enum của bridge: 0=VST3, 1=VST2, 2=SF2/SF3, 3=SFZ."""
low = path.lower()
@@ -139,6 +168,7 @@ def render_offline(instrument_id, notes, bpm, sample_rate, preset_id=None,
detail=f"Bridge không load được plugin {instrument_id}. {log[-500:]}")
raise HTTPException(status_code=500,
detail=f"Render thất bại (rc={r.returncode}). {log[-500:]}")
normalize_peak_file(out_path)
return out_path, sf.info(out_path).frames / float(sample_rate)
except HTTPException:
raise