Pythonで作る波形生成アプリケーション – 音声合成の基礎を学ぼう

この記事は約12分で読めます。
スポンサーリンク

音声合成の基礎となる波形生成について、Pythonを使って実践的に学べるGUIアプリケーションを作成します。このアプリケーションでは、基本的な波形の生成、可視化、そして音声出力までを実装します。

開発環境と必要なライブラリ

アプリケーションの開発には以下のライブラリを使用します:

  • tkinter: GUIの作成
  • numpy: 波形データの生成
  • matplotlib: 波形の可視化
  • sounddevice: 音声出力

アプリケーションの構成・プログラム

アプリケーションは2つのPythonファイルで構成されています:

generate_wave.py

  • メインのGUIアプリケーション
  • 周波数制御とユーザーインターフェース
  • 波形タイプの選択機能
import tkinter as tk
from tkinter import ttk
from wave_creator import wave_creator

class WaveGenerator:
    def __init__(self):
        self.root = tk.Tk()
        self.root.title("Wave Generator")
        
        # プロット表示用フレーム
        self.plot_frame = tk.Frame(self.root)
        self.plot_frame.pack(pady=10)
        
        # wave_creatorインスタンス作成
        self.wave_creator = wave_creator(self.plot_frame)
        
        # 周波数コントロール用フレーム
        freq_frame = tk.Frame(self.root)
        freq_frame.pack(pady=5)
        
        # 周波数ラベル
        tk.Label(freq_frame, text="Frequency (Hz):").pack(side=tk.LEFT)
        
        # 周波数数値入力の文字列変数
        self.freq_var = tk.StringVar()
        self.freq_var.set("440")
        self.freq_var.trace_add("write", self.on_freq_change)  # 値変更時のコールバック
        
        # 周波数数値入力
        self.freq_entry = tk.Entry(freq_frame, width=10, textvariable=self.freq_var)
        self.freq_entry.pack(side=tk.LEFT, padx=5)
        
        # 周波数スライダー
        self.freq_slider = ttk.Scale(
            self.root, from_=20, to=2000,
            orient='horizontal', length=200,
            command=self.update_frequency_from_slider
        )
        self.freq_slider.set(440)
        self.freq_slider.pack(pady=5)
        
        # 波形選択
        self.wave_type = ttk.Combobox(
            self.root, 
            values=['sine', 'square', 'sawtooth', 'triangle']
        )
        self.wave_type.set('sine')
        self.wave_type.pack(pady=5)
        
        # 再生ボタン
        ttk.Button(
            self.root, 
            text="Play", 
            command=self.play_wave
        ).pack(pady=5)
        
        self.current_freq = 440
        self.root.mainloop()
    
    def on_freq_change(self, *args):
        try:
            freq = float(self.freq_var.get())
            if 20 <= freq <= 2000:
                self.current_freq = freq
                self.freq_slider.set(freq)
        except ValueError:
            pass
    
    def update_frequency_from_slider(self, value):
        self.current_freq = float(value)
        # StringVarの更新(Entry更新のトリガー)
        self.freq_var.set(str(int(self.current_freq)))
    
    def play_wave(self):
        try:
            freq = float(self.freq_var.get())
            if 20 <= freq <= 2000:
                self.current_freq = freq
            else:
                self.freq_var.set(str(int(self.current_freq)))
        except ValueError:
            self.freq_var.set(str(int(self.current_freq)))
            
        self.wave_creator.generate_and_play_wave(
            self.current_freq, 
            wave_type=self.wave_type.get()
        )
        
# GUIの起動
if __name__ == "__main__":
    app = WaveGenerator()

wave_creator.py

  • 波形生成のコアロジック
  • 波形の描画処理
  • 音声出力の制御
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import sounddevice as sd

class wave_creator:
    def __init__(self, frame):
        self.frame = frame
    
    def generate_and_play_wave(self, frequency, duration=1.0, wave_type='sine', amplitude=0.5, sample_rate=44100):
        # 時間配列の生成
        t = np.linspace(0, duration, int(sample_rate * duration), False)
        
        # 波形の生成
        if wave_type == 'sine':
            wave = amplitude * np.sin(2 * np.pi * frequency * t)
        elif wave_type == 'square':
            wave = amplitude * np.sign(np.sin(2 * np.pi * frequency * t))
        elif wave_type == 'sawtooth':
            wave = amplitude * 2 * (frequency * t - np.floor(0.5 + frequency * t))
        elif wave_type == 'triangle':
            wave = amplitude * 2 * np.abs(2 * (frequency * t - np.floor(0.5 + frequency * t))) - 1
        
        # 波形のプロット
        fig, ax = plt.subplots(figsize=(5, 2))
        ax.plot(t[:1000], wave[:1000])
        ax.set_title(f'{wave_type} wave - {frequency}Hz')
        ax.set_xlabel('Time [s]')
        ax.set_ylabel('Amplitude')
        ax.grid(True)
        
        # GUIフレームに描画
        for widget in self.frame.winfo_children():
            widget.destroy()
        canvas = FigureCanvasTkAgg(fig, master=self.frame)
        canvas.draw()
        canvas.get_tk_widget().pack()
        
        # 音声出力
        sd.play(wave, sample_rate)
        sd.wait()

詳細説明

波形生成の実装

波形生成では、4種類の基本波形を実装しています:

  • サイン波(純音)
  • 矩形波
  • のこぎり波
  • 三角波
def generate_and_play_wave(self, frequency, duration=1.0, wave_type='sine', amplitude=0.5, sample_rate=44100):
    t = np.linspace(0, duration, int(sample_rate * duration), False)
    
    if wave_type == 'sine':
        wave = amplitude * np.sin(2 * np.pi * frequency * t)
    elif wave_type == 'square':
        wave = amplitude * np.sign(np.sin(2 * np.pi * frequency * t))
    elif wave_type == 'sawtooth':
        wave = amplitude * 2 * (frequency * t - np.floor(0.5 + frequency * t))
    elif wave_type == 'triangle':
        wave = amplitude * 2 * np.abs(2 * (frequency * t - np.floor(0.5 + frequency * t))) - 1

ユーザーインターフェースの実装

GUIでは、以下の機能を提供します:

  • 周波数の数値入力(20Hz~2000Hz)
  • スライダーによる周波数調整
  • 波形タイプの選択(コンボボックス)
  • 波形の可視化
  • 再生ボタン
def __init__(self):
    self.root = tk.Tk()
    self.root.title("Wave Generator")
    
    # 周波数コントロール
    self.freq_var = tk.StringVar()
    self.freq_var.set("440")
    
    # 周波数スライダー
    self.freq_slider = ttk.Scale(
        self.root, from_=20, to=2000,
        orient='horizontal', length=200,
        command=self.update_frequency_from_slider
    )

波形の可視化と音声出力

matplotlib.pyplotを使用して波形を可視化し、sounddeviceライブラリで音声出力を行います

# 波形のプロット
fig, ax = plt.subplots(figsize=(5, 2))
ax.plot(t[:1000], wave[:1000])
ax.set_title(f'{wave_type} wave - {frequency}Hz')

# 音声出力
sd.play(wave, sample_rate)
sd.wait()

実行方法

以下で実行します。

python generate_wave.py

以下が表示されれば実行成功です。

“周波数”と”波形”を選択して「Play」をクリックで、波形を生成して数秒間 指定の音声が出力されます。

まとめ

このアプリケーションを通じて、基本的な波形生成の仕組みと音声合成の基礎を学ぶことができます。GUIを使用することで、波形の変化をリアルタイムで観察でき、音声合成の理解を深めることができます。また、このコードをベースに、より複雑な波形生成や音声処理機能を追加することも可能です。

コメント

タイトルとURLをコピーしました