ひばりログ

Apple関連やプログラミングなど趣味を書き綴る。

Pythonでsin波を鳴らして遊ぶ

コード

import numpy as np
import wave
import struct
import pyaudio
import matplotlib.pyplot as plt

sample_num = 1024   # 1フレームあたりのサンプル数
channel = 1
rate = 16000        # サンプリング周波数
width = 2
format = pyaudio.paInt16

play_seconds = 1
frequency = 44{0}

total_sample_num = rate * play_seconds
t = np.arange(0, total_sample_num)
s = 32767.0 * np.sin(2*np.pi*frequency*t/rate)
s = s.astype(np.int16)

data = struct.pack("h" * total_sample_num , *s)

p = pyaudio.PyAudio()
stream = p.open(
    format=format,
    channels=channel,
    rate=rate,
    output=True
)

frame = data[0:sample_num]
for i in range(1, len(data)):
    stream.write(data)
    data = data[sample_num*i:sample_num*(i+1)]

stream.close()
p.terminate()

plt.plot(s[0:1000])
plt.show()

実行すると、作ったsin波の音が再生され、

sin波がグラフで表示されます。

f:id:hibari2978:20190709163018p:plain

sin波の作成

total_sample_num = rate * play_seconds
t = np.arange(0, total_sample_num)
s = 32767.0 * np.sin(2*np.pi*frequency*t/rate) * volume
s = s.astype(np.int16)

ここでsin波の作成をしています。

sin波に32767.0を乗算しているのは、

量子化ビットが16bit=(-32768~32768)だからです。 

量子化ビット

量子化ビットというのは、振幅をどれだけ細かくとるか、という単位です。

音をデジタルで表現するには、線ではなく点で表す必要があります。

f:id:hibari2978:20190709163916p:plain

上図が実際に440Hzのデジタル上の表現です。

縦軸は省略していますが、実際には

-32768、-32767、-32766…… 0、1、2…… 32766、32767、32768

というような細かさになっています。

これを量子化ビットという単位で決めています。

サンプリング周波数

横軸はサンプリング周波数で決めていて、

この場合は16000Hzと指定しているので

1秒間に16000個の点があります。

つまり、このグラフは横軸が1000まで表示されているので、

1 / 16000 * 1000 = 0.0625 なので

0.0625秒分となっています。

周波数を変える

このsin波をいじることで、様々な音を作れます。

一番簡単なのは周波数を変えることで、

音の高さが変わります。

440HzはA4(ラ)の音ですね。

(ピアノなどは442Hzなどにされていることが多いそうですが)

周波数を増やすと、音は高くなり、

減らすと低くなります。

sin派の振幅を制限する

他にもsin波の振幅を制限することで、

矩形波に変えて音色を変えることもできます。

upper_limit = 20000
downer_limit = -20000

total_sample_num = rate * play_seconds
t = np.arange(0, total_sample_num)
s = 32767.0 * np.sin(2*np.pi*frequency*t/rate)
s = s.astype(np.int16)

s = np.where(s > upper_limit, upper_limit, s)
s = np.where(s < downer_limit, downer_limit, s)

f:id:hibari2978:20190709165412p:plain

こちらは上限を20000、下限-20000にし、 それを超えた場合は上限下限に抑える

というようにして、波形をいじっています。

このように波形をいじることで、

色々と音を変えて遊ぶことができます。