Pythonで自動作曲: pydubを使ったシンプルな楽曲生成

## はじめに

音楽制作の世界にAIや自動化の波が押し寄せています。本記事では、Pythonとpydubライブラリを使用して、シンプルながらも興味深い自動作曲システムを構築する方法を紹介します。

基本的な音楽理論と、pydubの機能を組み合わせることで、簡単な楽曲を自動生成できるようになります。この記事を通じて、プログラミングと音楽の融合の可能性を探ってみましょう。

## 準備

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

```bash
pip install pydub numpy
```

pydubはオーディオ操作のために、numpyは数値計算のために使用します。

また、pydubはFFmpegに依存しているので、事前にFFmpegをインストールしておく必要があります。

## 1. 基本的な音の生成

まずは、単純な正弦波を使って音を生成する関数を作成します。

```python
import numpy as np
from pydub import AudioSegment
from pydub.generators import Sine

def generate_tone(frequency, duration, volume=-20.0):
    """指定された周波数、長さ、音量で音を生成する"""
    return Sine(frequency).to_audio_segment(duration=duration).apply_gain(volume)

# 例: A4 (440Hz) の音を1秒間生成
A4 = generate_tone(440, 1000)
A4.export("A4.wav", format="wav")
```

この関数を使って、様々な音程の音を生成できます。

<iframe width="560" height="315" src="https://www.youtube.com/embed/IK6-KwrQoy8?si=cYV9AXNnbYKoEDOs" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 2. 音階の定義

次に、主要な音階を定義します。ここでは、C major スケールを使用します。

```python
# C major スケールの周波数 (C4 から C5 まで)
C_MAJOR_SCALE = {
    'C4': 261.63, 'D4': 293.66, 'E4': 329.63, 'F4': 349.23,
    'G4': 392.00, 'A4': 440.00, 'B4': 493.88, 'C5': 523.25
}

# 音符の長さ（ミリ秒）
WHOLE_NOTE = 2000
HALF_NOTE = WHOLE_NOTE // 2
QUARTER_NOTE = WHOLE_NOTE // 4
EIGHTH_NOTE = WHOLE_NOTE // 8
```

## 3. メロディの生成

ランダムなメロディを生成する関数を作成します。

```python
import random

def generate_melody(num_notes=8):
    """ランダムなメロディを生成する"""
    notes = list(C_MAJOR_SCALE.keys())
    durations = [QUARTER_NOTE, HALF_NOTE, EIGHTH_NOTE]
    melody = AudioSegment.empty()
    
    for _ in range(num_notes):
        note = random.choice(notes)
        duration = random.choice(durations)
        tone = generate_tone(C_MAJOR_SCALE[note], duration)
        melody += tone
    
    return melody

# メロディを生成して保存
melody = generate_melody()
melody.export("random_melody.wav", format="wav")
```

この関数は、C major スケールからランダムに音を選び、指定された数の音符でメロディを生成します。

<iframe width="560" height="315" src="https://www.youtube.com/embed/rXBVpJfA7Fk?si=hRUlI6jLxfiZ5mjy" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 4. コード進行の生成

シンプルなコード進行を生成する関数を作成します。ここでは、よくある I-V-vi-IV の進行を使用します。

```python
import numpy as np
from pydub import AudioSegment

# 音を生成するための関数
def generate_tone(frequency, duration_ms, volume):
    sample_rate = 44100
    t = np.linspace(0, duration_ms / 1000, int(sample_rate * duration_ms / 1000), False)
    tone = np.sin(frequency * t * 2 * np.pi)
    audio = np.array(tone * (2**15 - 1), dtype=np.int16)
    return AudioSegment(audio.tobytes(), frame_rate=sample_rate, sample_width=2, channels=1).apply_gain(volume)

WHOLE_NOTE = 1000  # 1秒
C_MAJOR_SCALE = {'C4': 261.63, 'G4': 392.00, 'A4': 440.00, 'F4': 349.23}

def generate_chord(root_freq, chord_type='major'):
    """ルート音から和音を生成する"""
    if chord_type == 'major':
        ratios = [1, 1.25, 1.5]  # ルート音、長3度、完全5度
    elif chord_type == 'minor':
        ratios = [1, 1.2, 1.5]   # ルート音、短3度、完全5度
    
    chord = AudioSegment.silent(duration=WHOLE_NOTE)
    for ratio in ratios:
        tone = generate_tone(root_freq * ratio, WHOLE_NOTE, volume=-30)
        chord = chord.overlay(tone)
    
    return chord

def generate_chord_progression():
    """I-V-vi-IV のコード進行を生成する"""
    progression = AudioSegment.silent(duration=0)
    
    # I  (C major)
    progression += generate_chord(C_MAJOR_SCALE['C4'])
    # V  (G major)
    progression += generate_chord(C_MAJOR_SCALE['G4'])
    # vi (A minor)
    progression += generate_chord(C_MAJOR_SCALE['A4'], 'minor')
    # IV (F major)
    progression += generate_chord(C_MAJOR_SCALE['F4'])
    
    return progression

# コード進行を生成して保存
chord_progression = generate_chord_progression()
chord_progression.export("chord_progression.wav", format="wav")
```

<iframe width="560" height="315" src="https://www.youtube.com/embed/Wv0gvXCJvZc?si=Vsj7Kj9XowBKNnnl" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 5. メロディとコード進行の組み合わせ

最後に、生成したメロディとコード進行を組み合わせて、1つの楽曲にします。

```python
def create_song():
    """メロディとコード進行を組み合わせて曲を作る"""
    melody = generate_melody(16)  # 16音符のメロディ
    chords = generate_chord_progression()
    
    # コード進行を2回繰り返してメロディの長さに合わせる
    chords = chords * 2
    
    # メロディとコード進行を合成
    song = melody.overlay(chords)
    
    return song

# 曲を生成して保存
song = create_song()
song.export("auto_generated_song.wav", format="wav")
```

この関数は、メロディとコード進行を生成し、それらを重ね合わせて1つの楽曲を作り出します。

<iframe width="560" height="315" src="https://www.youtube.com/embed/vS-xBZ92BWQ?si=9TthGHBUgmVrgYJC" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

電話の待ち受け音みたいですね・・・

## まとめ

この記事では、Pythonとpydubを使用して、シンプルな自動作曲システムを構築する方法を紹介しました。基本的な音の生成から始まり、メロディの作成、コード進行の生成、そして最終的に1つの楽曲にまとめる過程を見てきました。

このシステムは非常にシンプルで、生成される音楽もまだ原始的ですが、自動作曲の基本的な概念を理解するのに役立ちます。ここから更に発展させる方法はたくさんあります：

- より複雑なメロディ生成アルゴリズムの実装
- 多様なコード進行パターンの追加
- リズムやテンポの変化の導入
- 異なる楽器音の使用
- 機械学習モデルの導入による、より洗練された作曲

自動作曲の世界は広大で、まだまだ探求の余地があります。この記事が、音楽とプログラミングの融合に興味を持つきっかけになれば幸いです。

## 参考リンク

- [pydub公式ドキュメント](https://github.com/jiaaro/pydub)
- [音楽理論の基礎](https://www.musictheory.net/)
- [Algorithmic Composition: A Gentle Introduction to Music Composition Using Common LISP and Common Music](https://quod.lib.umich.edu/s/spobooks/bbv9810.0001.001/1:4/--algorithmic-composition-a-gentle-introduction-to-music?rgn=div1;view=fulltext)