add loudnorm; default model to hf hub

This commit is contained in:
slSeanWU
2025-10-30 14:07:49 -04:00
parent 2b9d0a8227
commit cd7b889626
3 changed files with 38 additions and 8 deletions
+3 -3
View File
@@ -2,6 +2,7 @@
"""
This script generates MIDI files from text prompts using the MIDI-LLM model with vLLM backend.
vLLM provides faster inference compared to standard HuggingFace model.generate() mixin.
Caveat is that initialization + compilation takes more time, so best used for inference with many prompts.
"""
import json
@@ -235,8 +236,8 @@ Examples:
parser.add_argument(
"--model",
type=str,
required=True,
help="Path to MIDI-LLM model checkpoint"
default="slseanwu/MIDI-LLM_Llama-3.2-1B",
help="Path to MIDI-LLM model checkpoint, can be HuggingFace model ID or local path (default: slseanwu/MIDI-LLM_Llama-3.2-1B)"
)
# Input arguments (not required if using --interactive only)
@@ -494,4 +495,3 @@ Examples:
if __name__ == "__main__":
main()
+32 -4
View File
@@ -23,12 +23,20 @@ except ImportError:
# Optional dependencies for audio synthesis
SYNTHESIS_AVAILABLE = False
LOUDNESS_NORM_AVAILABLE = False
try:
import midi2audio
import librosa
import librosa.effects
import soundfile as sf
SYNTHESIS_AVAILABLE = True
# Optional loudness normalization
try:
import pyloudnorm as pyln
LOUDNESS_NORM_AVAILABLE = True
except ImportError:
pass
except ImportError:
pass
@@ -89,16 +97,18 @@ def synthesize_midi_to_audio(
midi_path: str,
soundfont_path: str,
save_mp3: bool = True,
samplerate: Optional[int] = None
samplerate: Optional[int] = None,
target_loudness: float = -18.0
) -> bool:
"""
Synthesize MIDI file to audio (WAV/MP3) using FluidSynth.
Synthesize MIDI file to audio (WAV/MP3) using FluidSynth with loudness normalization.
Args:
midi_path: Path to MIDI file
soundfont_path: Path to SoundFont (.sf2) file
save_mp3: If True, convert to MP3 and delete WAV
samplerate: Optional sample rate for audio
target_loudness: Target loudness in LUFS (default: -14.0, Spotify standard)
Returns:
True if successful, False otherwise
@@ -106,7 +116,7 @@ def synthesize_midi_to_audio(
if not SYNTHESIS_AVAILABLE:
print("Warning: Audio synthesis libraries not available. Skipping synthesis.")
print("Install with: conda install conda-forge::fluidsynth conda-forge::ffmpeg")
print(" pip install midi2audio librosa soundfile")
print(" pip install midi2audio librosa soundfile pyloudnorm")
return False
try:
@@ -120,9 +130,27 @@ def synthesize_midi_to_audio(
# Synthesize MIDI to WAV
fs.midi_to_audio(midi_path, wav_path)
# Trim silence from audio
# Load and trim silence from audio
wav, sr = librosa.load(wav_path)
wav, _ = librosa.effects.trim(wav, top_db=30)
# Apply loudness normalization
if LOUDNESS_NORM_AVAILABLE:
try:
# Measure the loudness
meter = pyln.Meter(sr)
loudness = meter.integrated_loudness(wav)
# Normalize to target loudness
wav = pyln.normalize.loudness(wav, loudness, target_loudness)
# Prevent clipping
if wav.max() > 1.0 or wav.min() < -1.0:
wav = wav / max(abs(wav.max()), abs(wav.min()))
except Exception as e:
print(f"Warning: Loudness normalization failed: {e}")
# Write normalized audio
sf.write(wav_path, wav, sr)
if save_mp3:
+3 -1
View File
@@ -50,6 +50,7 @@ jsonschema-specifications==2025.9.1
lark==1.2.2
lazy_loader==0.4
librosa==0.11.0
pyloudnorm==0.1.1
llguidance==0.7.30
llvmlite==0.44.0
lm-format-enforcer==0.11.3
@@ -149,4 +150,5 @@ watchfiles==1.1.1
websockets==15.0.1
xformers==0.0.32.post1
xgrammar==0.1.25
yarl==1.22.0
yarl==1.22.0
future==1.0.0