【Audio入門】音を発生する♬


これまでなんとなく当然だと思っていたが、まず正しい音を正確に出力するところからやろうと思う。
技術的には、これまでも何度か書いているので、いきなりコードを出してちょっと説明したいと思う。

コード解説

import wave
import numpy as np
from matplotlib import pylab as plt
import struct
import pyaudio
import matplotlib

以下に発生する音の属性を示す。

a = 1     #振幅
fs = 44100 #サンプリング周波数
f0 = 400  #基準周波数
f1 = f0+10 #重畳する音の周波数
sec = 5   #秒;発生時間
CHUNK=1024 #一度にサンプリングするframe数
p=pyaudio.PyAudio()

stream=p.open(  format = pyaudio.paInt16,
        channels = 1,
        rate = fs,
        frames_per_buffer = CHUNK,
        input = True,
        output = True) # inputとoutputを同時にTrueにする

以下で実際に出力するサイン波を生成する。
※今回は二つの波を重畳する

swav=[]
for n in np.arange(fs * sec):
    #サイン波を生成
    s = (a * np.sin(2.0 * np.pi * f0 * n / fs)+ a * np.sin(2.0 * np.pi * f1 * n / fs))/2
    swav.append(s)

発生するサイン波を描画する。
0-0.1秒までのものとハウリングを見るために全体0-5秒の図を描画するが、
昨夜プロットの配置の仕方を学んだので、それを応用している。
※配置する図のデータは同一で範囲指定など変えて、描画できる

#サイン波を表示
matplotlib.rcParams.update({'font.size': 18, 'font.family': 'sans', 'text.usetex': False}) 
fig = plt.figure(figsize=(8,6))  #(width,height)
x_offset=np.round(0.05*4,decimals=2)
y_offset=np.round(0.05*10,decimals=2)
width=0.3
height=0.3
axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
axes2 = fig.add_axes([x_offset, y_offset, width, height]) # insert axes

x = np.linspace(0, sec, int(fs*sec)) #sec;サンプリング時間、fs*sec;サンプリング数
axes1.set_ylim(-1.2,1.2)
axes1.set_xlim(0,0.1) #0-0.1 sec
axes1.plot(x,swav)

axes2.set_ylim(-1.2,1.2)
axes2.set_xlim(0,5) #0-5 sec
axes2.plot(x,swav)
plt.pause(1)
plt.savefig('./fft/sound_'+str(f0)+'_'+str(f1)+'.jpg')

swavに格納された音データを以下によりwavファイルとして保存する。

#サイン波を-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("./fft/output"+str(f0)+"_"+str(f1)+".wav")
params = (1, 2, fs, len(binwave), 'NONE', 'not compressed')
w.setparams(params)
w.writeframes(binwave)
w.close()

最後に作成した音をスピーカーから出力する。
※inputに置き換える必要はないが、一応勘違い防止のために一度inputに代入してから出力している

input = binwave
output = stream.write(input)

いろいろな音を作成して聞き比べる

今回は、基準振動を400Hzとして、以下の音を重畳して作成して遊んでみた

f_list=[0.01,0.1,0.5,1,2,5,10,50,100,200,300,350,400.1,400.2,400.5,401,402,405,410,420,450,500,600,800,1000,1200,1400,1600]

結果は以下のような画像が得られる。

上記のパラメータでGifアニメーションにする。

対応する音は以下に置いた。
AudioAutoencoder/sound_generation/melody.wav

音の不思議

作成した音を聞いてみると、
1.400-402の重畳はいわゆるハウリングのようにウワ~ンウワ~ンと聞こえます
2.高周波例えば400-1000の重畳だと、この高調波側が周波数が高くなるにしたがって、大きな音で聞こえます
3.低周波の音との重畳400-1などでは、1Hzは可聴音ではないので関係なさそうです。しかし、音が大きくなったり小さくなったり、ハウリングのように聞こえることもあります
4.一番たぶん音声と関係するのはそれらの間の周波数例えば、400-600のような場合です。これは、まだまだですが音声の’う’と同じような音が出ます。これは先日のフォルマント合成の話と同じような現象です。

コードは以下に置きました

AudioAutoencoder/sin_sound.py

まとめ

・いろいろな音をサイン波で作成して遊んでみた
・発生した音は高々二音だが、「音の不思議」に記載したように多彩な音を発生する

・これらをFFT~STFT,そしてwavelet変換して分析する
・さらに男性声、女性声の分析及びそれらの音声合成を実施する