初めに
LinearVC は、線形回帰のみで音声変換(Voice Conversion)を行う手法です。 Interspeech 2025 に採択された論文の実装になります。
処理パイプラインは以下の3ステップで構成されています。
- WavLM Large(レイヤー6)で自己教師あり特徴量を抽出
- ソース話者とターゲット話者の特徴量から線形回帰で射影行列を学習
- 特徴量を変換し HiFiGAN で波形を生成
開発環境
| 項目 | 詳細 |
|---|---|
| OS | Windows 11 |
| CPU | AMD Ryzen 9 7950X |
| GPU | NVIDIA GeForce RTX 4090 |
| メモリ | 128GB |
| Python | 3.13.8 |
| CUDA | 12.6 |
| uv | 0.6.x |
環境構築
fork したリポジトリを clone します。
git clone https://github.com/ayutaz/linearvc.git cd linearvc
pyproject.toml は以下の内容です。
PyTorch を CUDA 12.6 対応版でインストールするため、explicit = true で専用のインデックスを指定しています。
[project] name = "linearvc" version = "0.1.0" description = "Add your description here" requires-python = ">=3.13" dependencies = [ "celer>=0.7.4", "ipython>=9.10.0", "jupyter>=1.1.1", "numpy>=2.4.2", "torch>=2.10.0", "torchaudio>=2.10.0", "tqdm>=4.67.3", ] [[tool.uv.index]] name = "pytorch-cu126" url = "https://download.pytorch.org/whl/cu126" explicit = true [tool.uv.sources] torch = [{ index = "pytorch-cu126" }] torchaudio = [{ index = "pytorch-cu126" }]
依存パッケージをインストールします。
uv sync
データの準備
音声変換には、ソース話者(変換元)とターゲット話者(変換先)の音声データが必要です。
今回はソース話者に LibriSpeech dev-clean の話者 1272(英語男性)、ターゲット話者につくよみちゃんコーパス Vol.1(日本語女性)を使用します。
LibriSpeech dev-clean のダウンロード
mkdir -p data cd data wget https://www.openslr.org/resources/12/dev-clean.tar.gz tar xzf dev-clean.tar.gz cd ..
展開すると以下のようなディレクトリ構成になります。
data/LibriSpeech/dev-clean/ ├── 1272/ # 話者ID │ ├── 128104/ # チャプターID │ │ ├── 1272-128104-0000.flac │ │ ├── 1272-128104-0001.flac │ │ └── ... │ └── 135031/ │ └── ... └── ...
サブセットの作成
linearvc.py の --extension オプションはソースとターゲット両方に適用されるため、拡張子を .wav に統一します。
LibriSpeech の .flac を .wav に変換し、それぞれ数ファイルずつのサブセットを作成します。
import torchaudio from pathlib import Path src_dir = Path("data/LibriSpeech/dev-clean/1272") wav_dir = Path("data/subset_libri1272") wav_dir.mkdir(exist_ok=True) for flac_file in sorted(src_dir.rglob("*.flac"))[:3]: wav, sr = torchaudio.load(flac_file) out_path = wav_dir / flac_file.name.replace(".flac", ".wav") torchaudio.save(str(out_path), wav, sr)
つくよみちゃんコーパスも同様に数ファイルコピーします。
mkdir -p data/subset_tsukuyomi
cp path/to/つくよみちゃんコーパス/02\ WAV(+12dB増幅)/VOICEACTRESS100_00{1,2,3}.wav data/subset_tsukuyomi/
実行
linearvc.py を実行して音声変換を行います。
ソース話者のディレクトリ、ターゲット話者のディレクトリ、変換したい入力音声ファイル、出力ファイル名を指定します。
文では非並列モードで話者あたり約3分以上のデータを推奨しています。そのため3-5分程度を最低限指定するようにしてください
パターン1: LibriSpeech 1272 → つくよみちゃん(英語男性 → 日本語女性)
uv run python linearvc.py \
data/subset_libri1272 \
data/subset_tsukuyomi \
data/subset_libri1272/1272-128104-0000.wav \
output.wav
実行すると以下のようなログが出力されます。
Reading from: data\subset_libri1272 Reading from: data\subset_tsukuyomi Reading: data\subset_libri1272\1272-128104-0000.wav Source features: 100%|██████████| 3/3 [00:00<00:00, 14.13it/s] Target features: 100%|██████████| 3/3 [00:00<00:00, 21.18it/s] Writing: output.wav
パターン2: つくよみちゃん → LibriSpeech 1272(日本語女性 → 英語男性)
uv run python linearvc.py \
data/subset_tsukuyomi \
data/subset_libri1272 \
data/subset_tsukuyomi/VOICEACTRESS100_001.wav \
output_tsukuyomi2libri.wav
Reading from: data\subset_tsukuyomi Reading from: data\subset_libri1272 Reading: data\subset_tsukuyomi\VOICEACTRESS100_001.wav Source features: 100%|██████████| 3/3 [00:00<00:00, 20.83it/s] Target features: 100%|██████████| 3/3 [00:00<00:00, 36.68it/s] Writing: output_tsukuyomi2libri.wav
パターン3: LibriSpeech 1272 → LibriSpeech 1462(英語男性 → 英語女性)
uv run python linearvc.py \
data/subset_libri1272 \
data/subset_libri1462 \
data/subset_libri1272/1272-128104-0000.wav \
output_libri2libri.wav
Reading from: data\subset_libri1272 Reading from: data\subset_libri1462 Reading: data\subset_libri1272\1272-128104-0000.wav Source features: 100%|██████████| 3/3 [00:00<00:00, 20.81it/s] Target features: 100%|██████████| 3/3 [00:00<00:00, 20.43it/s] Writing: output_libri2libri.wav
各パターンとも output.wav が生成されていれば成功です。
精度はそれなりのものができてそうでした