Compose — Musique & production audio
Trois modules embarqués couvrent le volet musique et production audio de speech-swift, tous exécutés nativement sur Apple Silicon via MLX ou CoreML. MAGNeT génère des clips musicaux de 30 secondes à partir d'un prompt textuel. Séparation de sources (Open-Unmix) divise une piste stéréo en quatre stems (voix / batterie / basse / autres). Amélioration de la parole (DeepFilterNet3) supprime le bruit de fond de la parole en temps réel.
| Module | Tâche | Backend | Sortie | CLI |
|---|---|---|---|---|
| MAGNeT | Texte → musique | MLX (INT4 / INT8) | 30 s @ 32 kHz mono | speech compose |
| Open-Unmix | Séparation de stems | MLX | 4 stems @ 44,1 kHz stéréo | speech separate |
| DeepFilterNet3 | Suppression de bruit | CoreML (Neural Engine) | 48 kHz, temps réel | speech denoise |
MAGNeT — génération de musique à partir de texte
Portage MLX Swift de MAGNeT de Meta (Masked Audio Generation with a Single Non-Autoregressive Transformer). Génère des clips de 30 s de musique mono 32 kHz à partir d'un prompt anglais libre — "happy rock", "energetic EDM with synth lead", ou un texte descriptif riche pour des résultats plus propres.
Architecture
Trois composants chargés, téléchargés au premier appel :
| Composant | Rôle | Source |
|---|---|---|
| LM décodeur MAGNeT | Transformer non-autorégressif masqué sur 4 codebooks EnCodec. 24 couches (Small, 300M) ou 48 (Medium, 1.5B). Projections Q/K/V/out quantifiées + linéaires FFN (MLX-affine, groupe 64). | aufklarer/MAGNeT-{Small,Medium}-30secs-MLX-{4,8}bit |
| Encodeur de texte T5-base | Encodeur 110M paramètres pour le conditionnement texte. FP32 (chemin encodeur uniquement ; pas de décodeur, pas de tête LM). | t5-base |
| Décodeur EnCodec 32 kHz | Décodeur SEANet (Conv1d / ConvTranspose1d / ResnetBlock / LSTM 2 couches) + RVQ Euclidien 4 codebooks. Mappe les tokens discrets du LM vers une forme d'onde 32 kHz. | mlx-community/encodec-32khz-float32 |
Décodage parallèle masqué
Contrairement à son cousin autorégressif MusicGen, MAGNeT exécute 50 passes avant au total (répartition par défaut [20, 10, 10, 10] entre les 4 codebooks) avec un re-masquage planifié en cosinus, un recuit de guidance sans classifieur, et des fenêtres d'attention locales par étape. L'étape 0 a une self-attention complète ; les étapes 1–3 utilisent une fenêtre locale |q − k| ≤ 5 car les codebooks supérieurs ne font qu'affiner les détails.
Variantes
| Variante | Paramètres | LM sur disque | RSS max | Temps (série M, 30 s) | RTF |
|---|---|---|---|---|---|
small-int4 | 300M | 287 MB | ~1.4 GB | ~10.8 s | 0.36× |
small-int8 | 300M | 425 MB | ~1.5 GB | ~11 s | 0.37× |
medium-int4 | 1.5B | 1.36 GB | ~2.2 GB | ~36 s | 1.20× |
medium-int8 | 1.5B | 2.10 GB | ~3.0 GB | ~36 s | 1.20× |
RTF inférieur à 1,0 = plus rapide que le temps réel. La quantification déplace à peine le temps d'horloge — l'attention domine, pas les projections linéaires — donc le gain pratique d'INT4 est en mémoire plutôt qu'en latence.
Démarrage rapide
import MAGNeTMusicGen
let model = try await MAGNeTMusicGen.fromPretrained(variant: .smallInt4)
let pcm = model.generate(text: "energetic upbeat rock anthem with electric guitar riffs, driving drums, bass groove")
// pcm: [Float] length 960_000 (30 s × 32 kHz mono)
try WAVWriter.write(samples: pcm, sampleRate: 32_000,
to: URL(fileURLWithPath: "out.wav"))
CLI
# Default: small-int4 (~10 s on M-series for 30 s of audio)
speech compose "happy rock" -o happy_rock.wav
# Larger model — better prompt following, ~3.5× slower
speech compose "lo-fi hip hop with mellow piano and warm vinyl crackle" \
--variant medium-int4 -o lofi.wav
# Reproducible
speech compose "energetic EDM with synth lead" --seed 42 -o edm.wav
Flags : --variant {small,medium}-{int4,int8}, --temperature (recuit, par défaut 3,0), --top-p (par défaut 0,9), --cfg-max / --cfg-min (par défaut 10,0 / 1,0), --steps "20,10,10,10" (itérations par codebook), --seed.
Les tags courts comme "happy rock" fonctionnent mais semblent maigres. Les prompts descriptifs mentionnant instruments + tempo + ambiance améliorent sensiblement la cohérence — dans notre test qualité, le prompt plus riche a donné un taux de passage par zéro plus élevé (0,116 vs 0,093, soit plus de détails haute fréquence) et zéro clipping. Comparez :
"happy rock"— maigre"energetic upbeat rock anthem with electric guitar riffs, driving drums, bass groove"— plus riche, généralement meilleur
Paquets & licence
Les quatre paquets MLX dérivent de facebook/magnet-small-30secs et facebook/magnet-medium-30secs et héritent de la licence de Meta : CC-BY-NC 4.0 — usage non commercial uniquement. L'audio généré est soumis à la même restriction.
Séparation de sources — Open-Unmix (4 stems)
Open-Unmix HQ / UMX-L porté sur MLX. Divise un mix stéréo en quatre stems — voix, batterie, basse, autres instruments — via des prédicteurs BiLSTM par stem et un post-filtre Wiener-EM multicanal, le tout s'exécutant de bout en bout sur MLX via la STFT inverse. RTF réel ~0,031 (32× plus rapide que le temps réel) sur série M pour 30 s d'audio.
# Split mix.wav into vocals/drums/bass/other.wav next to it
speech separate mix.wav
# Or keep stems together
speech separate mix.wav --output stems/
import SourceSeparation
let separator = try await SourceSeparator.fromPretrained()
let stems = try separator.separate(audio: stereoSamples, sampleRate: 44_100)
// stems.vocals, stems.drums, stems.bass, stems.other — each [Float]
Architecture complète, réglage et notes de benchmark dans le guide de séparation de sources.
Amélioration de la parole — DeepFilterNet3
DeepFilterNet3 sur le Neural Engine (CoreML). Supprime le bruit de fond de la parole 48 kHz en temps réel avec un modèle de 2,1M paramètres — assez petit pour s'exécuter aux côtés d'un pipeline ASR comme étape de prétraitement.
speech denoise noisy.wav -o clean.wav
import SpeechEnhancement
let enhancer = try await SpeechEnhancer.fromPretrained()
let clean = try enhancer.enhance(audio: noisy, sampleRate: 48_000)
Configuration complète dans le guide d'amélioration de la parole.
Choisir le bon outil
| Vous voulez… | Utilisez |
|---|---|
| Générer de la musique à partir d'un prompt textuel | MAGNeT (speech compose) |
| Extraire les voix ou la batterie d'une piste existante | Open-Unmix (speech separate) |
| Nettoyer une parole bruyante avant transcription | DeepFilterNet3 (speech denoise) |
| Convertir du texte en parole (synthèse vocale) | VoxCPM2 or Qwen3-TTS |