【Audio入門】Sin波の合成でメロディや音声を再現・再生してみる♬

Audioの取り扱いは、何度かやってきましたが、いつも参考①のサイトを見てしまいます。
ということで、今回はAudioのWavファイルの取り扱い方を中心に音声を合成できるかどうかをまとめておこうと思います。
###やったこと
・Audioの基本；入力、出力、信号処理（FFTなど）
・Sin波で基準音を出力し音楽を演奏する
・Sin波の合成で音声’う’を再現する
###・Audioの基本；入力、出力、信号処理（FFTなど）
【参考】
・①[PyAudioの基本メモ2 音声入出力](http://takeshid.hatenadiary.jp/entry/2016/01/10/153503)
これをまとめてやるコードは、以下のとおりです。

```py
# -*- coding:utf-8 -*-
import pyaudio
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal

CHUNK=1024
RATE=44100
p=pyaudio.PyAudio()
N=10
CHUNK=1024*N
p=pyaudio.PyAudio()
fr = RATE
fn=51200*N/50
fs=fn/fr

stream=p.open(	format = pyaudio.paInt16,
		channels = 1,
		rate = RATE,
		frames_per_buffer = CHUNK,
		input = True,
		output = True) # inputとoutputを同時にTrueにする
# Figureの初期化
fig = plt.figure(figsize=(16, 8)) #...1
# Figure内にAxesを追加()
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
while stream.is_active():
    input = stream.read(CHUNK)
    output = stream.write(input)
    sig =[]
    sig = np.frombuffer(input, dtype="int16")  /32768.0

    nperseg = 1024*N
    
    f, t, Zxx = signal.stft(sig, fs=fn, nperseg=nperseg)
    ax2.pcolormesh(fs*t, f/fs, np.abs(Zxx), cmap='hsv')
    ax2.set_xlim(0,fs)
    ax2.set_ylim(2,20000)
    ax2.set_yscale('log')
    ax2.set_axis_off()
    x = np.linspace(0, 100, nperseg)
    ax1.plot(x,sig)
    ax1.set_ylim(-0.5,0.5)
    plt.pause(0.01)
    plt.clf()
    ax1 = fig.add_subplot(211)
    ax2 = fig.add_subplot(212)
	
stream.stop_stream()
stream.close()
print( "Stop Streaming")
```
###・Sin波で基準音を出力し音楽を演奏する
【参考】
②[[python]　sin波の音をWAV形式で出力する](https://qiita.com/kinaonao/items/c3f2ef224878fbd232f5)
③[Pythonでサイン波(正弦波)をつくる](http://www.non-fiction.jp/2015/08/17/sin_wave/)
参考①と②から以下のコードで基準音の440Hzを作成できます。

```py
import wave
import numpy as np
from matplotlib import pylab as plt
import struct
 
a = 1     #振幅
fs = 8000 #サンプリング周波数
f0 = 440  #周波数
sec = 5   #秒
swav=[]
for n in np.arange(fs * sec):
    #サイン波を生成
    s = a * np.sin(2.0 * np.pi * f0 * n / fs)
    swav.append(s)
#サイン波を表示
plt.plot(swav[0:100])
plt.show()
#サイン波を-32768から32767の整数値に変換(signed 16bit pcmへ)
swav = [int(x * 32767.0) for x in swav]
#バイナリ化
binwave = struct.pack("h" * len(swav), *swav)
#サイン波をwavファイルとして書き出し
w = wave.Wave_write("output.wav")
p = (1, 2, 8000, len(binwave), 'NONE', 'not compressed')
w.setparams(p)
w.writeframes(binwave)
w.close()
```
そして、参考②に**今回は440Hzの音(ラ・A4)で試しましたが、ド(C4)は261.63Hz、レ(D4)は293.66Hzというように音階（十二平均律音階）は周波数が決まっています。なのでスクリプトを改造して簡単な音楽のwavファイルをつくることもできます。**
とあるので、これをやってみました。
その他の音階は以下のとおりです。
【参考】
・[音階の周波数](https://tomari.org/main/java/oto.html)

|音階| ド | レ | ミ | ファ | ソ | ラ | シ |ド|
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
|周波数|261.626|293.665|329.628|349.228|391.995|440.000|493.883|523.251|
|音階|C4|D4|E4|F|G4|A4|B4|C5|
この音階周波数を利用すると、いわゆるmusicが作成できます。
ここでは、基本ということで、以下のようなコードでドレミファソラシド．．．を奏でてみました。
まず、ドレミファソラシドのwavファイルを作成します。
**上記の音階の周波数はピアノの音階が出ているので、ほぼどんな曲も再現できますね。。**

```py
import numpy as np
import wave
import struct

A=1
fs = 44100
sec = 0.5 #秒
f0=261.626 #ド	C4	
f1=293.665 #レ	D4	
f2=329.628 #ミ	E4	
f3=349.228 #ファ	F	
f4=391.995 #ソ	G4	
f5=440.000 #ラ	A4	
f6=493.883 #シ	B4	
f7=523.251 #ド	C5
f_list=(f0,f1,f2,f3,f4,f5,f6,f7)
def create_wave(A,f0,fs,t):
    point = np.arange(0,fs*t)
    sin_wave =A* np.sin(2*np.pi*f0*point/fs)
    sin_wave = [int(x * 32767.0) for x in sin_wave]
    binwave = struct.pack("h" * len(sin_wave), *sin_wave)
    w = wave.Wave_write("./doremi/Doremi{}.wav".format(f0))
    p = (1, 2, fs, len(binwave), 'NONE', 'not compressed')
    w.setparams(p)
    w.writeframes(binwave)
    w.close()
for i in f_list:
    f=i
    create_wave(A, f, fs, sec)
```
そして、上記で作成されたwavファイルを以下のコードで演奏します。
もちろん、f_listはお好きな曲にアレンジしてください。

```py
# -*- coding:utf-8 -*-
import pyaudio
import numpy as np
import wave
import wave
import struct

RATE=44100
CHUNK = 22050
p=pyaudio.PyAudio()
f0=261.626 #ド	C4	
f1=293.665 #レ	D4	
f2=329.628 #ミ	E4	
f3=349.228 #ファ F	
f4=391.995 #ソ	G4	
f5=440.000 #ラ	A4	
f6=493.883 #シ	B4	
f7=523.251 #ド	C5
f_list=(f0,f1,f2,f3,f4,f5,f6,f7,f6,f5,f4,f3,f2,f1,f0,f0)
stream=p.open(format = pyaudio.paInt16,
        channels = 1,
        rate = RATE,
        frames_per_buffer = CHUNK,
        input = True,
        output = True) # inputとoutputを同時にTrueにする
for i in f_list:
    wavfile = './doremi/Doremi{}.wav'.format(i)
    print(wavfile)
    wr = wave.open(wavfile, "rb")
    input = wr.readframes(wr.getnframes())
    output = stream.write(input)
```
作成したメロディ等は以下の置きました。
・[AudioAutoencoder/データ/](https://github.com/MuAuan/AudioAutoencoder/tree/master/%E3%83%87%E3%83%BC%E3%82%BF)
###・Sin波の合成で音声'う'を再現する
まず、以下のコードで音声’う’を発生して、安定したところでFFT図を得ます。
・[AudioAutoencoder/audio_inout.py](https://github.com/MuAuan/AudioAutoencoder/blob/master/audio_inout.py)
![IntensityvsFreq_real.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/64866f47-e55e-1310-e867-a65c8135725c.jpeg)

そして、そのFFT図を再現すべく以下のコードで’う’の波形になるように探します。
・[AudioAutoencoder/make_wavUfile.py](https://github.com/MuAuan/AudioAutoencoder/blob/master/make_wavUfile.py)
実は、FFT図は割と近い絵になりますが、実際得られる音声波形は以下のようになかなか似たような絵になりません。
![f_130_250_420_530.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/a6cf3d1d-c60d-391c-ae8b-15d67dc7b597.jpeg)
ということで、上のコードでそれぞれのサイン波の振幅と主要な周波数（290）を調整します。
ここで、周波数は動かすと大きく様相が変わりました。
ということで、１Hz単位で動かしてみましたがそれでも以下のように変わりました。
![f_130_250_420_530__266.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233744/493b1ce1-64fa-d790-c6ad-5f76807397ab.gif)
最終的に得られた合成された’う’を以下に置きました
・[AudioAutoencoder/データ/](https://github.com/MuAuan/AudioAutoencoder/tree/master/%E3%83%87%E3%83%BC%E3%82%BF)
###まとめ
・Audioの基本を振り返った
・Sin波でメロディを作成した
・Sin波で合成音声’う’を作成してみた

・これを利用して音声Autoencoderの学習データを作成しようと思う