Compose — 音楽 & オーディオ制作

speech-swift の音楽・オーディオ制作面は 3 つのオンデバイスモジュールでカバーされ、すべて MLX または CoreML を介して Apple Silicon 上でネイティブに動作します。MAGNeT はテキストプロンプトから 30 秒の音楽クリップを生成します。音源分離 (Open-Unmix) はステレオトラックを 4 つのステム (ボーカル / ドラム / ベース / その他) に分割します。音声強調 (DeepFilterNet3) は音声から背景ノイズをリアルタイムで除去します。

モジュールタスクバックエンド出力CLI
MAGNeTテキスト → 音楽MLX (INT4 / INT8)30 秒 @ 32 kHz モノラルspeech compose
Open-Unmixステム分離MLX4 ステム @ 44.1 kHz ステレオspeech separate
DeepFilterNet3ノイズ抑制CoreML (Neural Engine)48 kHz、リアルタイムspeech denoise

MAGNeT — テキストから音楽生成

Meta の MAGNeT (単一の非自己回帰 Transformer によるマスク付きオーディオ生成) の MLX Swift 移植版です。フリーフォームの英語プロンプトから 32 kHz モノラル音楽の 30 秒クリップを生成します — 「happy rock」、「energetic EDM with synth lead」、またはよりクリーンな結果を得るための豊富な説明テキスト。

アーキテクチャ

初回呼び出し時にダウンロードされる 3 つのコンポーネント:

コンポーネント役割ソース
MAGNeT デコーダー LM4 つの EnCodec コードブックに対するマスク付き非自己回帰 Transformer。24 層 (Small, 300M) または 48 層 (Medium, 1.5B)。量子化された Q/K/V/out 投影 + FFN 線形層 (MLX-affine、グループ 64)。aufklarer/MAGNeT-{Small,Medium}-30secs-MLX-{4,8}bit
T5-base テキストエンコーダーテキスト条件付け用の 110M パラメータエンコーダー。FP32 (エンコーダーのみのパス; デコーダーなし、LM ヘッドなし)。t5-base
EnCodec 32 kHz デコーダーSEANet デコーダー (Conv1d / ConvTranspose1d / ResnetBlock / 2 層 LSTM) + 4 コードブック Euclidean RVQ。LM の離散トークンを 32 kHz 波形にマッピングします。mlx-community/encodec-32khz-float32

マスク並列デコーディング

自己回帰の兄弟である MusicGen とは異なり、MAGNeT は 合計 50 回の順伝播 (4 つのコードブックに対するデフォルト分割は [20, 10, 10, 10]) を実行し、コサインスケジュールによる再マスキング、分類器なしガイダンスのアニーリング、ステージごとのローカルアテンションウィンドウを使用します。ステージ 0 は完全な自己注意を持ち、ステージ 1〜3 は上位コードブックが詳細を洗練するだけなので |q − k| ≤ 5 のローカルウィンドウを使用します。

バリアント

バリアントパラメータLM ディスク容量ピーク RSS実時間 (M シリーズ、30 秒)RTF
small-int4300M287 MB~1.4 GB~10.8 s0.36×
small-int8300M425 MB~1.5 GB~11 s0.37×
medium-int41.5B1.36 GB~2.2 GB~36 s1.20×
medium-int81.5B2.10 GB~3.0 GB~36 s1.20×

RTF が 1.0 未満 = リアルタイムより高速。量子化は実時間にほとんど影響しません — 主導するのはアテンションであり線形投影ではありません — そのため INT4 の実際的な勝利は遅延ではなくメモリです。

クイックスタート

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

フラグ: --variant {small,medium}-{int4,int8}--temperature (アニーリング、デフォルト 3.0)、--top-p (デフォルト 0.9)、--cfg-max / --cfg-min (デフォルト 10.0 / 1.0)、--steps "20,10,10,10" (コードブックごとの反復回数)、--seed

プロンプトエンジニアリングのヒント

"happy rock" のような短いタグは機能しますが、薄く感じます。楽器 + テンポ + ムード に言及する記述的なプロンプトは、コヒーレンスを大幅に改善します — 品質スイープでは、より豊富なプロンプトはより高いゼロ交差率 (0.116 vs 0.093、つまりより多くの高周波の詳細) とクリッピングゼロをもたらしました。比較:

  • "happy rock" — 薄い
  • "energetic upbeat rock anthem with electric guitar riffs, driving drums, bass groove" — より豊富、通常はより良い

バンドルとライセンス

4 つの MLX バンドルはすべて facebook/magnet-small-30secsfacebook/magnet-medium-30secs から派生し、Meta のライセンスを継承します: CC-BY-NC 4.0 — 非商用利用のみ。生成されたオーディオも同じ制限の対象となります。

音源分離 — Open-Unmix (4 ステム)

Open-Unmix HQ / UMX-L を MLX に移植。ステムごとの BiLSTM 予測器とマルチチャネル Wiener-EM ポストフィルタを介してステレオミックスを 4 つのステム — ボーカルドラムベースその他の楽器 — に分割し、すべて逆 STFT を通じて MLX 上でエンドツーエンドに実行されます。M シリーズで 30 秒のオーディオに対する実際の RTF は約 0.031 (リアルタイムより 32 倍高速)。

# 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]

完全なアーキテクチャ、チューニング、ベンチマークノートは音源分離ガイドを参照してください。

音声強調 — DeepFilterNet3

Neural Engine (CoreML) 上の DeepFilterNet3。2.1M パラメータモデルで 48 kHz 音声から背景ノイズをリアルタイムで除去します — 前処理ステップとして ASR パイプラインと並行して実行できるほど小さいです。

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)

完全な構成は音声強調ガイドを参照してください。

適切なツールの選択

やりたいこと…使用するもの
テキストプロンプトから音楽を生成するMAGNeT (speech compose)
既存のトラックからボーカルやドラムを抽出するOpen-Unmix (speech separate)
文字起こし前に騒がしい音声をクリーンアップするDeepFilterNet3 (speech denoise)
テキストを音声に変換する (音声合成)VoxCPM2 or Qwen3-TTS