はじめに
本記事では、音の合成に関連する数学的な公式を使い、Pythonコードでその実装を行います。具体的には、基本的な正弦波の加算や乗算をはじめ、和積・積和変換、倍角公式、さらには加法定理に至るまで、音波を数式で操作する方法について解説します。
Pythonコード
# ライブラリのインポート
import numpy as np
import matplotlib.pyplot as plt
from IPython.display import Audio, display
# サンプリング設定
fs = 44100 # サンプリング周波数(44.1kHz)
duration = 2.0 # 音の長さ(秒)
t = np.linspace(0, duration, int(fs * duration), endpoint=False) # 時間軸
# 周波数設定:ドとレ
f_do = 261.63 # ドの周波数(Hz)
f_re = 293.66 # レの周波数(Hz)
omega1 = 2 * np.pi * f_do # ドの角周波数(rad/s)
omega2 = 2 * np.pi * f_re # レの角周波数(rad/s)
# 基本波形
sin1 = np.sin(omega1 * t) # sin(ω₁t) [ド]
sin2 = np.sin(omega2 * t) # sin(ω₂t) [レ]
sum_sin = sin1 + sin2 # sin(ω₁t) + sin(ω₂t) [和音]
prod_sin = sin1 * sin2 # sin(ω₁t) × sin(ω₂t) [積]
# 和積公式
sum_to_prod = 2 * np.sin((omega1 + omega2) / 2 * t) * np.cos((omega1 - omega2) / 2 * t) # 和積公式
# 積和公式
prod_to_sum = 0.5 * (np.cos((omega1 - omega2) * t) - np.cos((omega1 + omega2) * t)) # 積和公式
# 倍角の公式(Double Angle)
double_sin = 2 * sin1 * np.cos(omega1 * t) # sin(2ω₁t)
double_cos = 2 * np.cos(omega1 * t) ** 2 - 1 # cos(2ω₁t)
# 加法定理(Addition Formulas)
sin_add = np.sin(omega1 * t) * np.cos(omega2 * t) + np.cos(omega1 * t) * np.sin(omega2 * t) # sin(ω₁t + ω₂t)
cos_add = np.cos(omega1 * t) * np.cos(omega2 * t) - np.sin(omega1 * t) * np.sin(omega2 * t) # cos(ω₁t + ω₂t)
# 🔊 正規化
normalize = lambda x: x / np.max(np.abs(x)) # 音声を-1から1の範囲に正規化
# 📈 波形プロット(6段構成)
plt.figure(figsize=(14, 14))
# 1. sin(ω₁t), sin(ω₂t)
plt.subplot(6, 1, 1)
plt.plot(t[:1000], sin1[:1000], label='sin(ω₁t) [Do]', alpha=0.7)
plt.plot(t[:1000], sin2[:1000], label='sin(ω₂t) [Re]', alpha=0.7)
plt.title('Basic Sine Waves')
plt.legend(), plt.grid()
# 2. sin(ω₁t) + sin(ω₂t)
plt.subplot(6, 1, 2)
plt.plot(t[:1000], sum_sin[:1000], color='green', label='sin(ω₁t) + sin(ω₂t)')
plt.title('Addition of Sine Waves')
plt.legend(), plt.grid()
# 3. sin(ω₁t) × sin(ω₂t)
plt.subplot(6, 1, 3)
plt.plot(t[:1000], prod_sin[:1000], color='red', label='sin(ω₁t) × sin(ω₂t)')
plt.title('Product of Sine Waves')
plt.legend(), plt.grid()
# 4. 和積・積和
plt.subplot(6, 1, 4)
plt.plot(t[:1000], sum_to_prod[:1000], color='purple', label='Sum-to-Product')
plt.plot(t[:1000], prod_to_sum[:1000], color='orange', linestyle='--', label='Product-to-Sum')
plt.title('Sum-to-Product vs Product-to-Sum')
plt.legend(), plt.grid()
# 5. 倍角(sin, cos)
plt.subplot(6, 1, 5)
plt.plot(t[:1000], double_sin[:1000], label='sin(2ω₁t)', color='blue')
plt.plot(t[:1000], double_cos[:1000], label='cos(2ω₁t)', color='gray')
plt.title('Double Angle Formulas: sin(2ωt), cos(2ωt)')
plt.legend(), plt.grid()
# 6. 加法定理(sin(a+b), cos(a+b))
plt.subplot(6, 1, 6)
plt.plot(t[:1000], sin_add[:1000], label='sin(ω₁t + ω₂t)', color='teal')
plt.plot(t[:1000], cos_add[:1000], label='cos(ω₁t + ω₂t)', color='goldenrod')
plt.title('Addition Formulas: sin(a+b), cos(a+b)')
plt.legend(), plt.grid()
plt.tight_layout()
plt.show()
# 🎧 音声再生(基本・加算・積・和積・積和・倍角・加法定理)
print("🎧 sin(ω₁t) [ド]")
display(Audio(normalize(sin1), rate=fs))
print("🎧 sin(ω₂t) [レ]")
display(Audio(normalize(sin2), rate=fs))
print("🎧 sin(ω₁t) + sin(ω₂t) [和音]")
display(Audio(normalize(sum_sin), rate=fs))
print("🎧 sin(ω₁t) × sin(ω₂t) [積]")
display(Audio(normalize(prod_sin), rate=fs))
print("🎧 和積公式 [sin + sin → sin × cos]")
display(Audio(normalize(sum_to_prod), rate=fs))
print("🎧 積和公式 [sin × sin → cos − cos]")
display(Audio(normalize(prod_to_sum), rate=fs))
print("🎧 sin(2ω₁t) [倍角]")
display(Audio(normalize(double_sin), rate=fs))
print("🎧 cos(2ω₁t) [倍角]")
display(Audio(normalize(double_cos), rate=fs))
print("🎧 sin(ω₁t + ω₂t) [加法定理: sin]")
display(Audio(normalize(sin_add), rate=fs))
print("🎧 cos(ω₁t + ω₂t) [加法定理: cos]")
display(Audio(normalize(cos_add), rate=fs))