'20/06/13更新:音が多少ずれてたのを修正しました。
ライブラリpyaudioのインストールは下記のようにcondaで出来ます。
conda install pyaudio
音は波(三角関数sin)です。音階は周波数の違いで表現できます。そのため、楽譜に沿って、ドレミファソラシドの音符を順番に指定すれば、曲を演奏できます。4分音符や8分音符といった音の長さも指定します。ゲイン(音の強さ)は曲風が変わります。
下図は「ねこふんじゃった」の音(波)をプロットしたグラフです。正弦波でない波は、2つの正弦波を足した和音です。

■本プログラム
import sys
import pyaudio
import numpy as np
import wave
import struct
import glob
import re
import matplotlib.pyplot as plt
import datetime
now = datetime.datetime.now()
now = now.strftime("%y%m%d")
def tone(freq, length, gain):
slen = int(length * RATE)
if not isinstance(freq, list):
t = float(freq) * np.pi * 2 / RATE
sin_curve = np.sin(np.arange(slen) * t) * gain
else:
amp = float(gain) / len(freq)
sin_curve = 0
for f in freq:
t = float(f) * np.pi * 2 / RATE
sin_curve += np.sin(np.arange(slen) * t) * amp
plt.figure(num=1, figsize=(10,6))
plt.plot(sin_curve[0:500], label=freq)
plt.legend(bbox_to_anchor = (1.05, 1.0))
plt.tick_params(labelsize=16)
plt.tight_layout()
plt.grid()
plt.savefig(now + '_sin_curve.png')
return sin_curve
def play_wave(stream, sin_curve):
stream.write(sin_curve.astype(np.float32).tostring())
def create_music():
sample_list = []
sample_list.append([Dsharp4, L8, GAIN])
sample_list.append([Csharp4, L8, GAIN])
sample_list.append([Fsharp3, L2, GAIN])
sample_list.append([[Asharp3, Fsharp4], L4, GAIN])
sample_list.append([[Asharp3, Fsharp4], L4, GAIN])
sample_list.append([Dsharp4, L8, GAIN])
sample_list.append([Csharp4, L8, GAIN])
sample_list.append([Fsharp3, L2, GAIN])
sample_list.append([[Asharp3, Fsharp4], L4, GAIN])
sample_list.append([[Asharp3, Fsharp4], L4, GAIN])
sample_list.append([Dsharp4, L8, GAIN])
sample_list.append([Csharp4, L8, GAIN])
sample_list.append([Fsharp3, L2, GAIN])
sample_list.append([[Asharp3, Fsharp4], L4, GAIN])
sample_list.append([Dsharp3, L2, GAIN])
sample_list.append([[Asharp3, Fsharp4], L4, GAIN])
sample_list.append([Csharp3, L2, GAIN])
sample_list.append([[B3, F4], L4, GAIN])
sample_list.append([[B3, F4], L4, GAIN])
return sample_list
def read_wav(sample_list):
p=pyaudio.PyAudio()
stream = p.open(format = pyaudio.paInt16,
channels = 1,
rate = RATE,
frames_per_buffer = 1024,
input = True,
output = True)
wav_list = glob.glob('./*wav')
wav_list = sorted(wav_list, key=lambda x:int((re.search(r"[0-9]+", x)).group(0)))
for wavfile in wav_list:
print(wavfile)
wr = wave.open(wavfile, "rb")
input = wr.readframes(wr.getnframes())
output = stream.write(input)
stream.close()
def main():
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paFloat32,
channels=2,
rate=RATE,
frames_per_buffer=1024,
output=True)
sample_list = create_music()
binary_data_list = []
for i, sample in enumerate(sample_list):
print(i, sample)
sin_curve = tone(*sample)
np.savetxt(now + '_' + str(i) + '_sin_curve.csv',
sin_curve,
delimiter=',',
fmt='%.1f')
play_wave(stream, sin_curve)
sin_curve = [int(x * 32767.0) for x in sin_curve]
binary_data = struct.pack("h" * len(sin_curve), *sin_curve)
binary_data_list.append(binary_data)
binary_data_list = list(map(bytes, binary_data_list))
binary_data = b''.join(binary_data_list)
w = wave.Wave_write(now + "_sine.wav")
p = (1, 2, 44100, len(binary_data), 'NONE', 'not compressed')
w.setparams(p)
w.writeframes(binary_data)
w.close()
stream.close()
read_wav(sample_list)
if __name__ == '__main__':
RATE = 44100
GAIN = 1
BPM = 100
L1 = (60 / BPM * 4)
L2, L4, L8 = (L1/2, L1/4, L1/8)
C3, Csharp3, D3, Dsharp3, E3, F3, Fsharp3, G3, Gsharp3, A3, Asharp3, B3 \
= (130.813, 138.591, 146.832, 155.563, 164.814, 174.614, 184.997, 195.998, 207.652, 220.000, 233.082, 246.942)
C4, Csharp4, D4, Dsharp4, E4, F4, Fsharp4, G4, Gsharp4, A4, Asharp4, B4 \
= (261.626, 277.183, 293.665, 311.127, 329.628, 349.228, 369.994, 391.995, 415.305, 440.0, 466.164, 493.883)
C5, Csharp5, D5, Dsharp5, E5, F5, Fsharp5, G5, Gsharp5, A5, Asharp5, B5 \
= (523.251, 554.365, 587.330, 622.254, 659.255, 698.456, 739.989, 783.991, 830.609, 880.000, 932.328, 987.767)
main()
print('finished')
●参考リンク
https://people.csail.mit.edu/hubert/pyaudio/docs/
以上
<広告>
リンク