Posted at

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

前回は、時間軸に向けての合成をやったが、今回は複数の音声(というか音)を重ね合わせする。Superimposeというやつだ。


とりあえずの目標

以下のとおり、

※リンクされているものは記事にしたものであり、その記事を前提知識として書いて行くので、参照すると理解し易いと思います。

Scipy環境を作る

 ・環境の確認

不確定原理について

・FFT変換・逆変換してみる;時間軸が消える

・STFT変換・逆変換してみる;窓関数について

・wavelet変換・逆変換してみる;スペクトログラムの解釈と不確定原理

音声や地震データや株価や、。。。とにかく一次元の実時系列データに応用する

音声データ入力編

FFTからwavelet変換まで簡単にたどってみる(上記以外のちょっと理論)

⑤二次元データに応用してみる

⑥天体観測データに応用してみる

リアルタイムにスペクトログラムしてみる

高速化(バグあり)

高速化完成版

音声分離アプリ

音声合成アプリ


やったこと

・二つの音声を大きさを変えて重ね合わせする

・コード解説


・二つの音声を大きさを変えて重ね合わせする

二つの音声を重ね合わせできれば、複数の音を重ね合わせに拡張するのは容易である。

ここでは、「おはよう」と「開けゴマ」を重ね合わせた。

以下は「おはよう」から徐々に「開けゴマ」に音声が変化する。

out_ohayohirakegoma2.gif

以下は、「開けゴマ」から徐々に「おはよう」に音声が変化する。

out_ohayohirakegoma.gif


・コード解説

コードは、前回とほぼ同じなので、主な変更箇所を記載する。

全体はリンクを見てほしい。

最初に2つの音声ファイルを読み込む。

if __name__ == '__main__':

filename1=input('input original filename=')
filename2=input('input original filename=')

だんだん二つのWavファイルの割合を変更してその変化を見たいので、while True:で連続することとした。

そして、加算する前に重畳する比率を入力することとした。

    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文内で以下のとおり実施する。

        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ファイルを出力する。ここでは加算因子をファイル名に記載することとした。

        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文に戻る。

        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/

これはIEでは再生できると思う。また、ダウンロードすれば再生できると思う。

・いよいよ次回は音声認識に挑戦。。。