【Scipy】FFT、STFTとwavelet変換で遊んでみた♬～音声重畳合成アプリ

前回は、時間軸に向けての合成をやったが、今回は複数の音声（というか音）を重ね合わせする。Superimposeというやつだ。
###とりあえずの目標
以下のとおり、
※リンクされているものは記事にしたものであり、その記事を前提知識として書いて行くので、参照すると理解し易いと思います。
①[Scipy環境を作る](https://qiita.com/MuAuan/items/8850e037babcff991b8e)
　・環境の確認
②[不確定原理について](https://qiita.com/MuAuan/items/504160465e83e556dd3e)
・FFT変換・逆変換してみる；時間軸が消える
・STFT変換・逆変換してみる；窓関数について
・wavelet変換・逆変換してみる；スペクトログラムの解釈と不確定原理
③[音声や地震データや株価や、。。。とにかく一次元の実時系列データに応用する](https://qiita.com/MuAuan/items/858aab2879708668e2bb)
 [音声データ入力編](https://qiita.com/MuAuan/items/5f1a47bc6e5d842fa07d)
④[FFTからwavelet変換まで簡単にたどってみる（上記以外のちょっと理論）](https://qiita.com/MuAuan/items/70c87d42c3a258d0b6fd)
⑤二次元データに応用してみる
⑥天体観測データに応用してみる
⑦[リアルタイムにスペクトログラムしてみる](https://qiita.com/MuAuan/items/85b077640901dbb29514)
 [高速化（バグあり）](https://qiita.com/MuAuan/items/6c2ab8497409bac6304e)
 [高速化完成版](https://qiita.com/MuAuan/items/cffdf9bf9ed5dae21019)
 [音声分離アプリ](https://qiita.com/MuAuan/items/f4df0c8aa4c64415629c)
 [音声合成アプリ](https://qiita.com/MuAuan/items/1199a63797f50a6141a1)
###やったこと
・二つの音声を大きさを変えて重ね合わせする
・コード解説
###・二つの音声を大きさを変えて重ね合わせする
二つの音声を重ね合わせできれば、複数の音を重ね合わせに拡張するのは容易である。
ここでは、「おはよう」と「開けゴマ」を重ね合わせた。
以下は「おはよう」から徐々に「開けゴマ」に音声が変化する。
![out_ohayohirakegoma2.gif](https://qiita-image-store.s3.amazonaws.com/0/233744/96345f60-962b-1426-b57a-84f2d42cb0f9.gif)
以下は、「開けゴマ」から徐々に「おはよう」に音声が変化する。
![out_ohayohirakegoma.gif](https://qiita-image-store.s3.amazonaws.com/0/233744/00bb2de5-0c29-6bdf-fc0f-7330561dfbc8.gif)
###・コード解説
コードは、前回とほぼ同じなので、主な変更箇所を記載する。
※[全体はリンクを見てほしい。](https://github.com/MuAuan/Scipy-Swan/blob/master/add_wav_longitudinal.py)
最初に２つの音声ファイルを読み込む。

```py
if __name__ == '__main__':
    filename1=input('input original filename=')
    filename2=input('input original filename=')
```
だんだん二つのWavファイルの割合を変更してその変化を見たいので、while True:で連続することとした。
そして、加算する前に重畳する比率を入力することとした。


```py
    while True:
        wf1,stream1,fr1,fn1,fs1,width1,CHANNELS1 = fileOpen(filename1)
        wf2,stream2,fr2,fn2,fs2,width2,CHANNELS2 = fileOpen(filename2)
    
        fc1=int(input('input factor1='))
        fc2=int(input('input factor2='))
```
加算は同一のfor文内で以下のとおり実施する。

```py
        frames = []
        for i in range(0, int(fr1 / 1024 *fs1+0.5)):
            data1 = wf1.readframes(1024)
            data2 = wf2.readframes(1024)
            g1 = fc1*np.frombuffer(data1, dtype= "int16") #/32768.0    # -1～1に正規化 #g1は演算できる
            g2 = fc2*np.frombuffer(data2, dtype= "int16") #/32768.0    # -1～1に正規化 #g1は演算できる
            frames.append(g1+g2)
            stream1.write(g1+g2)
```
以下は、合成したwavファイルを出力する。ここでは加算因子をファイル名に記載することとした。

```py
        loff1 = wf1.getnframes()/1024 #215 #len(frames)
        loff2 = wf2.getnframes()/1024 #215 #len(frames)

        wr = wave.open('wav/'+str(fc1)+filename1+str(fc2)+filename2+'_out.wav', 'wb')
        wr.setnchannels(CHANNELS2)
        wr.setsampwidth(width2)  #width=2 ; 16bit
        wr.setframerate(fr2)
        s=int((loff1+loff2)*(fs1+fs2)/(fs1+fs2))
        wr.writeframes(b''.join(frames[0:s])) 
        #wr.close()
```
最後に、合成データ、STFT、そしてFFT画像を出力して、While文に戻る。

```py
        fn = wr.getnframes()
        fs = float(fn / wr.getframerate())
        print(fn,fs)
        plot_wav('wav/'+str(fc1)+filename1+str(fc2)+filename2+'_out',0,fs)
```
ということで、上記のような連続画像が得られた。
予想通り、音声が徐々に変化した。
例えば、このアプリを利用すると、ノイズの効果なども検証可能である。
###まとめ
・音声を重畳するアプリを作成した
・「おはよう」と「開けゴマ」を重畳した
・徐々に音声が変化する様子を観察できた

なお、重畳した音声のwavデータは以下に置いた
[Scipy-Swan/data/](https://github.com/MuAuan/Scipy-Swan/tree/master/data)
これはIEでは再生できると思う。また、ダウンロードすれば再生できると思う。
・いよいよ次回は音声認識に挑戦。。。