音ファイル(.wav)の作成と再生
音の波をnumpy.ndarray上に作成して、wavファイルとしてscipy.io.wavfile.writeで保存した後、winsound.PlaySoundで音として再生するスクリプト(リスト1)を備忘録として作成した。
再生は別プロセスとして実行して、Enterキーの押下でプロセスを停止してプログラムの終了とした。
音はnumpy.ndarray型のw_valuesに、以下のコードで設定した。
w_values
= np.zeros(len(ts))
for t in range(len(ts)):
if t
< len(ts) / 4:
w_values[t] = Do.value()
elif t < 2 * len(ts) / 4:
w_values[t] = Mi.value()
elif t < 3 * len(ts) / 4:
w_values[t] = Sol.value()
else:
w_values[t] = (Do.value()
+ Mi.value() + Sol.value())
/ 3
Do、Mi、Solはド、ミ、ソの音を生成するオブジェクトでWave型である。Wave型は、次のコードで与えられるクラス型である。
class Wave():
"""
freq: 周波数, dt:
時間増分(1/sampling rate)
"""
def
__init__(self, freq, dt):
self.freq = freq
self.phase = 0.0
self.dt = dt
def
value(self):
v = np.sin(2*np.pi * self.phase)
self.phase += self.freq * self.dt
if self.phase > 1.0:
self.phase -= 1.0
return v
配列w_valuesに設定された音は、次のコードによってファイルexample.wavに保存される。
from scipy.io.wavfile
import write as write_wav
write_wav("example.wav", s_rate, w_values.astype(np.int16))
保存したファイルは、次の関数によって再生される。フラッグwinsound.SND_LOOPが指定されているので、ファイルは繰り返し実行される。
def mysound(v):
winsound.PlaySound(v,
winsound.SND_ASYNC |
winsound.SND_FILENAME | winsound.SND_LOOP)
この再生は、次のこーどにより別プロセスとして実行される。
with Pool() as pool:
print('Playing.')
pool.map(mysound,
["example.wav"])
print()
a = input('Press
Enter-key, to exit.')
pool.terminate()
input関数の次のterminate()が実行されると、この別プロセスは終了して、音の再生は終わる。
リスト1 音ファイルの作成と再生(ScriptFile.zip)
from scipy.io.wavfile
import write as write_wav
import numpy
as np
import copy
import winsound
from time import sleep
from multiprocessing import Pool
class Wave():
"""
freq: 周波数, dt:
時間増分(1/sampling rate)
"""
def
__init__(self, freq, dt):
self.freq = freq
self.phase = 0.0
self.dt = dt
def
value(self):
v = np.sin(2*np.pi * self.phase)
self.phase += self.freq * self.dt
if self.phase > 1.0:
self.phase -= 1.0
return v
#
#
winsound.SND_LOOP: 繰り返し再生
#
def mysound(v):
winsound.PlaySound(v,
winsound.SND_ASYNC |
winsound.SND_FILENAME | winsound.SND_LOOP)
if __name__ == '__main__':
# サンプリング周波数
s_rate
= 44100;
# 音データの長さ(2秒)
ts
= np.linspace(0, 2, s_rate
* 2 + 1)
# 時間増分
d_t
= 1.0 / s_rate
# ド(523.251ヘルツ)
Do = Wave(523.251, d_t)
# ミ(659.255ヘルツ)
Mi
= Wave(659.255, d_t)
# ソ(783.991ヘルツ)
Sol = Wave(783.991, d_t)
#
# ドー>ミー>ソー>(ド+ミ+ソ)
#
w_values
= np.zeros(len(ts))
for t in range(len(ts)):
if t
< len(ts) / 4:
w_values[t] = Do.value()
elif t < 2 * len(ts) / 4:
w_values[t] = Mi.value()
elif t < 3 * len(ts) / 4:
w_values[t] = Sol.value()
else:
w_values[t] = (Do.value()
+ Mi.value() + Sol.value())
/ 3
#
# 音データの強さの調整
#
amplitude = np.iinfo(np.int16).max * 0.5
max_wave
= np.abs(w_values).max()
w_values
= w_values * amplitude / max_wave
#
# numpy.ndarrayのデータをint16型でwavファイルに書き出す
#
write_wav("example.wav",
s_rate, w_values.astype(np.int16))
#
# Enterキーが押されるまで、繰り返し再生になるように
# 再生を別プロセスとして実行する。
#
with Pool() as pool:
print('Playing.')
pool.map(mysound,
["example.wav"])
print()
a = input('Press
Enter-key, to exit.')
pool.terminate()