きっかけ
超基礎的な音感トレーニングアプリを作ってみたかった。でも、ピアノ音のファイルが見つからなかった(1オクターブ分くらいはあったけど)。
困ったので自分で作りました。ピアノの音色ではなく「ピー」音ですが、音感トレーニング用なら悪くない?(素人なので分からない)
気づき
ピアノの鍵盤って、一つ隣の音との周波数の比はどこも同じらしいです。ということは 周波数だけ考えると鍵盤の白と黒って特に意味ない ってことですよ。レ(白)→レ#(黒)と、ミ(白)->ファ(白)の周波数比は同じなんですよ。黒はちょっとしか上がらないんだと思ってました。びっくりですよね。
サンプルコード
ラ(440Hz)から始まり、ラ#、シ、ド、ド#・・・ラ(1760Hz)と2オクターブ上まで1ファイル ずつ作ります
- もっと沢山作りたい場合は
np.arange
の25を増やせばok - 出力先のディレクトリ(
OUTPUT_DIRECTORY
)は先に作っておかないとエラーになります。もしくはOUTPUT_DIRECTORY = './'
に変えちゃえば動きます - importしてるものが無ければ
pip install
などで入れてくださいね
# Python 3.9.13
import numpy as np
from scipy.io.wavfile import write
from playsound import playsound
# 変更不要 >>>>>>>>>>>>>
SAMPLING_RATE = 44100 # 1秒あたりのデータ点数
FREQUENCY_RATIO = pow(2 , 1/12) # 隣合う音の周波数比。12回で2倍になることから計算
# <<<<<<<<<<<< 変更不要
# 適宜変更してね >>>>>>>>>>>>>>>
OUTPUT_DIRECTORY = './test_output/' # 出力先フォルダ。あらかじめ作ってないとエラーになるよ
AMPLITUDE = 16384 # 音の大きさ
START_FREQUENCY_HZ = 440 # 開始周波数(Hz)
DURATION_SEC = 2 # 音を何秒間鳴らすか
lamda = 2.5 # 音のフェードアウト具合。適当に調整する
# <<<<<<<<<<<<<< 適宜変更してね
# 時間軸データの生成
time_array = np.linspace(
0,
DURATION_SEC,
int(SAMPLING_RATE * DURATION_SEC)
)
# 周波数を変えてファイル生成するループ
for i in np.arange(0, 25, 1): # 0から24(2オクターブ上)まで1刻み
# 周波数
frequency_hz = START_FREQUENCY_HZ * pow(FREQUENCY_RATIO, i)
# 波形生成
amplitude_array = (
AMPLITUDE
* np.sin(2 * np.pi * frequency_hz * time_array) # SIN関数
* pow(np.e, -time_array * lamda) # 適当にフェードアウトさせる
)
# 出力先ファイルパス
fname = f'{i}'
path = f'{OUTPUT_DIRECTORY}{fname}.wav'
# 書き出し
write(path, SAMPLING_RATE, amplitude_array.astype(np.int16))
print(f"output: {i}, {frequency_hz}, {path}")