色々な波形を聴き比べる(正弦波、三角波、矩形波、ノコギリ波)

Python

波形と音色の関係

この記事では4種類の波形を比較しながら「音色」について考えていきます。
※音声の再生時は音量にご注意ください。

正弦波(Sine Wave)

正弦波はサイン波(sine wave)とも呼ばれ、音声信号解析では最も重要で基本となる波形です。
周波数解析をする際は、解析の対象となる波形を「周波数の異なる正弦波を集めた合成波である」と仮定して解析を進めます。
以下のグラフでは上段に元となった正弦波の波形、下段に元波形に周波数分解(フーリエ変換)を施した波形を描画しています。今回は440Hzの正弦波を扱っているため、ちょうど下段グラフの440Hz部分にピークが存在します。

\(y = A sin({2}πft)\)

三角波(Triangle Wave)

三角波は波形の見た目が三角形になっており、周波数分解を行うと奇数倍音※1のみを含むことが分かります。また、高い倍音成分は急速に小さくなることが特徴です。

\(y = \dfrac{8}{π^2} \sum_{k=1}^∞ sin\Bigl(\dfrac{kπ}{2}\Bigr) \dfrac{sin(kt)}{k^2} \)

矩形波(Square Wave)

矩形波は波形の見た目が矩形(四角形)をしており、周波数分解すると三角波のように奇数倍音※1のみを含むことが分かります。三角波との違いは高周波成分も比較的多く含まれている点です。

\(y = \dfrac{4}{π} \sum_{k=1}^∞\dfrac{sin\{(2k – 1)2πft\}}{2k – 1}\)

ノコギリ波(Sawtooth Wave)

ノコギリ波は波形は見た目がのこぎりの歯のような形状をしており、周波数分解すると奇数倍音※1と偶数倍音※1の両方を含んでいることが分かります。

\( y = \dfrac{2}{π} \sum_{k=1}^∞\dfrac{sin(kt)}{k} \)

※1:「倍音」とは、基準となる音波(基音)の周波数に対して、整数倍の周波数を持つ音波のことを指します。特に周波数が奇数倍の音波を奇数倍音、偶数倍の音波を偶数倍音と呼びます。

Pythonでの実装方法

今回紹介した音声波形をグラフ化、音声ファイル化するためのプログラムを示します。

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
from scipy.io import wavfile

# パラメータの設定
RATE = 44100        # 標本化周波数(サンプリングレート)
DURATION = 3        # 録音時間[s]
FREQ = 440          # 波形周波数
AMP = 0.5           # 振幅
FRAMES = 500

AMP = AMP * 2**15-1

# 時間軸の作成
time = np.arange(RATE * DURATION) / RATE

# 正弦波
sin_wave = AMP * np.sin(2 * np.pi * FREQ * time)

# 三角波
triangle_wave = AMP * signal.sawtooth(2 * np.pi * FREQ * time, 0.5)

# 矩形波
square_wave = AMP * signal.square(2 * np.pi * FREQ * time, duty=0.5)

# ノコギリ波
sawtooth_wave = AMP * signal.sawtooth(2 * np.pi * FREQ * time)

# グラフの描画
fig, axs = plt.subplots(4, 1, figsize=(8, 8))
axs[0].plot(time[: FRAMES], sin_wave[: FRAMES])
axs[0].set_title('Sine Wave')
axs[1].plot(time[: FRAMES], triangle_wave[: FRAMES])
axs[1].set_title('Triangle Wave')
axs[2].plot(time[: FRAMES], square_wave[: FRAMES])
axs[2].set_title('Square Wave')
axs[3].plot(time[: FRAMES], sawtooth_wave[: FRAMES])
axs[3].set_title('Sawtooth Wave')

for ax in axs:
    ax.set_xlabel('Time [s]')
    ax.set_ylabel('Amplitude')

plt.tight_layout()
plt.show()

# 音声ファイルにして保存
wavfile.write("sin_wave.wav", RATE, sin_wave.astype(np.int16))
wavfile.write("triangle_wave.wav", RATE, triangle_wave.astype(np.int16))
wavfile.write("square_wave.wav", RATE, square_wave.astype(np.int16))
wavfile.write("sawtooth_wave.wav", RATE, sawtooth_wave.astype(np.int16))

コメント