fix: normalize peak audio render offline chống clip polyphony; TCP wheel điều chỉnh volume/pan
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user