いろいろ方法がありますが、簡単でどこでも使えるのが print("\x07")
です。ASCII の 07 は音を鳴らすための文字です。いわゆるビープ音ですが、Mac はシステム設定の「サウンド」の「サウンドエフェクト」で音が選べます。
440Hzの正弦波を鳴らす方法はいろいろありますが、ここでは python-sounddevice というライブラリを使います。pip install sounddevice
または conda install -c conda-forge python-sounddevice
でインストールできます。音のデータは ±1 の範囲に収めます。
import numpy as np import sounddevice as sd x = 0.8 * np.sin(2 * np.pi * 440 * np.linspace(0, 1, 44101)) sd.play(x, 44100)
WAVファイルの読み書きは、Python標準ライブラリ wave や、次に説明する SciPy も使えますが、ここでは python-sounddevice と同じ開発者による soundfile ライブラリを使ってみます。pip install soundfile
でインストールして、次のようにします:
import soundfile as sf import sounddevice as sd data, fs = sf.read("filename.wav") sd.play(data, fs)
以下では SciPy を使ってみます。
880Hzの音と1320Hzの音を混ぜると、あるはずのない440Hzの音も聞こえるという話を聞いたので確かめてみましょう。NumPy と SciPy はインストールしておきます(pip install numpy scipy
)。
import numpy as np from scipy.io import wavfile samplerate = 44100 # 44100Hzサンプリング duration = 5 # 5秒 t = np.linspace(0, 2 * np.pi * duration, samplerate * duration + 1) data = 10000 * (np.sin(880 * t) + np.sin(1320 * t)) wavfile.write("test.wav", samplerate, np.round(data).astype("int16"))
こうしてできた test.wav を再生してみましょう。Macであればターミナルに afplay test.wav
と打ち込めば再生できます。
880Hzを左耳、1320Hzを右耳に出すには、data = ...
の行を次のようにします:
data = 10000 * np.c_[np.sin(880 * t), np.sin(1320 * t)]
1320Hzのほうを少し小さい音にして、1秒遅れて出します:
w = np.append(np.zeros(samplerate), np.ones(samplerate * (duration - 1) + 1)) data = 10000 * np.sin(880 * t) + 5000 * w * np.sin(1320 * t)
いろいろ試してください。聞こえるのは差 (1320-880)Hz だという説もありますが、それなら高い方を例えば 1374 にすれば (1374-880)Hz でほぼレの音が聞こえるはずですね。
ついでに聴力検査用の4000Hzの音を左に5秒、右に5秒出してみましょう。
data1 = 10000 * np.c_[np.sin(4000 * t), 0 * t] data2 = 10000 * np.c_[0 * t, np.sin(4000 * t)] data = np.vstack((data1, data2)) wavfile.write("4000.wav", samplerate, np.round(data).astype("int16"))
ボリュームを十分小さくして聞いてみてください。
音階にしてみましょう。中央のラ(A4)は440Hzで、半音上がるごとに周波数は 2**(1/12)
倍になりますので、上のド(C5)は 440 * 2**(3/12)
Hzです。ここから初めてドーレミファソラシドーレミファソラシドーレミファソラシドーレミファソラシドーレミファソラシドーと5オクターブ上げていって、どこまで聞こえるか試してください。
samplerate = 44100 # 44100Hzサンプリング t1 = np.linspace(0, np.pi, samplerate // 2 + 1) # 0.5sec t2 = np.linspace(0, 2 * np.pi, samplerate + 1) # 1sec onkai = [2**(3/12), 2**(5/12), 2**(7/12), 2**(8/12), 2**(10/12), 2**(12/12), 2**(14/12)] tempo = [t2, t1, t1, t1, t1, t1, t1] data = np.array([]) for k in [440, 880, 1760, 3520, 7040]: for o, t in zip(onkai, tempo): data = np.concatenate((data, np.sin(k * o * t))) data = np.concatenate((data, np.sin(14080 * 2**(3/12) * t2))) wavfile.write("mono.wav", samplerate, np.round(10000 * data).astype("int16")) left = 10000 * np.c_[data, np.zeros(data.shape[0])] right = 10000 * np.c_[np.zeros(data.shape[0]), data] wavfile.write("left.wav", samplerate, np.round(left).astype("int16")) wavfile.write("right.wav", samplerate, np.round(right).astype("int16"))
各音の周波数(Hz)は次の通りです。ピアノの最高音はC8です。
5 | 6 | 7 | 8 | 9 | 10 | |
---|---|---|---|---|---|---|
C | 523.3 | 1046.5 | 2093.0 | 4186.0 | 8372.0 | 16744.0 |
D | 587.3 | 1174.7 | 2349.3 | 4698.6 | 9397.3 | |
E | 659.3 | 1318.5 | 2637.0 | 5274.0 | 10548.1 | |
F | 698.5 | 1396.9 | 2793.8 | 5587.7 | 11175.3 | |
G | 784.0 | 1568.0 | 3136.0 | 6271.9 | 12543.9 | |
A | 880.0 | 1760.0 | 3520.0 | 7040.0 | 14080.0 | |
B | 987.8 | 1975.5 | 3951.1 | 7902.1 | 15804.3 |
私はE9くらいまでしか聞こえませんでした。昔はテレビのブラウン管(CRT)の水平同期周波数15750Hzが聞こえたのですが・・・。
C10を超える17000Hz以上の音(モスキート音)は若者にしか聞こえません。若者を寄せ付けないために大音量のモスキート音を使うことがあるようです。
musicpy が楽しそうです(そのうち書きます)。