LoginSignup
1
1

More than 3 years have passed since last update.

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

Posted at

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

コード解説

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]

結果は以下のような画像が得られる。
sound_400_401.jpg
上記のパラメータでGifアニメーションにする。
sound_modulation.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変換して分析する
・さらに男性声、女性声の分析及びそれらの音声合成を実施する

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1