Pythonで作るボイスチェンジャー: pydubを使った音声変換

## はじめに

ボイスチェンジャーは、入力された音声を変調して異なる声質や特徴を持つ音声に変換するツールです。この記事では、Pythonのpydubライブラリを中心に使用して、簡単なボイスチェンジャーを実装する方法を紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/cb864fec-5f13-9c55-5af3-e11c9a88c301.png)

## 目次

1. 環境設定
2. 基本的な音声の読み込みと保存
3. ピッチシフト
4. スピード変更
5. フォルマントシフト
6. エコー効果
7. 複数の効果の組み合わせ
8. リアルタイム処理の考慮事項

## 1. 環境設定

まず、必要なライブラリをインストールします：

```bash
pip install pydub numpy scipy
```

## 2. 基本的な音声の読み込みと保存

pydubを使用して音声ファイルを読み込み、保存する基本的な方法を見てみましょう：

```python
from pydub import AudioSegment

# 音声ファイルの読み込み
audio = AudioSegment.from_wav("input.wav")

# 音声ファイルの保存
audio.export("output.wav", format="wav")
```

## 3. ピッチシフト

ピッチシフトは声の高さを変える効果です。pydubには直接的なピッチシフト機能がないため、scipyを使用して実装します：

```python
import numpy as np
from scipy.signal import resample
from pydub.utils import get_array_type

def pitch_shift(audio, semitones):
    # AudioSegmentをNumPy配列に変換
    samples = np.array(audio.get_array_of_samples())
    
    # モノラルでない場合は変換
    if audio.channels > 1:
        samples = samples.reshape((-1, audio.channels))
    
    # ピッチシフトの計算
    factor = 2 ** (semitones / 12)
    new_length = int(len(samples) / factor)
    
    # リサンプリング
    new_samples = resample(samples, new_length)
    
    # 新しいAudioSegmentの作成
    new_audio = audio._spawn(new_samples.astype(get_array_type(audio.sample_width)))
    return new_audio.set_frame_rate(int(audio.frame_rate * factor))

# 使用例
audio = AudioSegment.from_wav("input.wav")
shifted_audio = pitch_shift(audio, 4)  # 4半音上げる
shifted_audio.export("pitch_shifted.wav", format="wav")
```

## 4. スピード変更

音声の速度を変更することで、声の特徴を変えることができます：

```python
def change_speed(audio, speed_factor):
    # オーディオの速度を変更
    new_audio = audio._spawn(audio.raw_data, overrides={
        "frame_rate": int(audio.frame_rate * speed_factor)
    })
    return new_audio.set_frame_rate(audio.frame_rate)

# 使用例
speed_changed = change_speed(audio, 1.2)  # 20%速く
speed_changed.export("speed_changed.wav", format="wav")
```

## 5. フォルマントシフト

フォルマントシフトは、声の特徴を保ちながらピッチを変更する高度な技術です。簡易的な実装は以下の通りです：

```python
from scipy.signal import stft, istft

def formant_shift(audio, shift_factor):
    # AudioSegmentをNumPy配列に変換
    samples = np.array(audio.get_array_of_samples()).astype(np.float32)
    
    # STFTを適用
    f, t, Zxx = stft(samples, fs=audio.frame_rate, nperseg=1024)
    
    # フォルマントシフト
    new_f = f * shift_factor
    new_Zxx = np.zeros_like(Zxx)
    for i in range(len(t)):
        new_Zxx[:, i] = np.interp(f, new_f, Zxx[:, i])
    
    # 逆STFTを適用
    _, new_samples = istft(new_Zxx, fs=audio.frame_rate, nperseg=1024)
    
    # 新しいAudioSegmentの作成
    new_audio = audio._spawn(new_samples.astype(np.int16))
    return new_audio

# 使用例
formant_shifted = formant_shift(audio, 1.2)  # フォルマントを20%上げる
formant_shifted.export("formant_shifted.wav", format="wav")
```

## 6. エコー効果

エコー効果を加えることで、声に空間的な広がりを持たせることができます：

```python
def add_echo(audio, delay, decay):
    # エコーを生成
    echo = audio.fade_out(duration=decay)
    silence = AudioSegment.silent(duration=delay)
    return audio.overlay(silence + echo)

# 使用例
echo_audio = add_echo(audio, delay=500, decay=1000)
echo_audio.export("echo_audio.wav", format="wav")
```

## 7. 複数の効果の組み合わせ

これまでに実装した効果を組み合わせて、より複雑な音声変換を行うことができます：

```python
def voice_changer(audio, pitch_semitones, speed_factor, formant_shift_factor, echo_delay, echo_decay):
    # ピッチシフト
    audio = pitch_shift(audio, pitch_semitones)
    
    # スピード変更
    audio = change_speed(audio, speed_factor)
    
    # フォルマントシフト
    audio = formant_shift(audio, formant_shift_factor)
    
    # エコー効果
    audio = add_echo(audio, echo_delay, echo_decay)
    
    return audio

# 使用例
transformed_audio = voice_changer(audio, 
                                  pitch_semitones=2, 
                                  speed_factor=1.1, 
                                  formant_shift_factor=1.1, 
                                  echo_delay=300, 
                                  echo_decay=500)
transformed_audio.export("transformed_voice.wav", format="wav")
```

## 8. リアルタイム処理の考慮事項

ここまでの例はファイルベースの処理でしたが、リアルタイムのボイスチェンジャーを実装する場合は以下の点を考慮する必要があります：

1. 入力音声のストリーミング処理
2. 低遅延処理の実装
3. バッファリングの最適化
4. マルチスレッドまたは非同期処理の利用

リアルタイム処理の詳細な実装は本記事の範囲を超えますが、PyAudioライブラリを使用することで、マイク入力のリアルタイム処理が可能になります。

## まとめ

この記事では、Pythonとpydubを使用して基本的なボイスチェンジャーを実装する方法を紹介しました。ピッチシフト、スピード変更、フォルマントシフト、エコー効果など、様々な音声変換技術を組み合わせることで、創造的な音声加工が可能になります。

これらの基本的な技術を理解し、さらに発展させることで、より高度なボイスチェンジャーやオーディオエフェクトプロセッサーの開発に挑戦することができます。音声処理の世界は奥深く、探求の価値があります。ぜひ、自分なりのアイデアを実装してみてください！

## 参考リンク

- [pydub公式ドキュメント](https://github.com/jiaaro/pydub)
- [SciPy公式ドキュメント](https://docs.scipy.org/doc/scipy/reference/)
- [音声信号処理の基礎](https://ccrma.stanford.edu/~jos/sasp/)
- [PyAudio documentation](https://people.csail.mit.edu/hubert/pyaudio/docs/)