LoginSignup
13
15

More than 3 years have passed since last update.

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

Last updated at Posted at 2019-07-03

Audioの取り扱いは、何度かやってきましたが、いつも参考①のサイトを見てしまいます。
ということで、今回はAudioのWavファイルの取り扱い方を中心に音声を合成できるかどうかをまとめておこうと思います。

やったこと

・Audioの基本;入力、出力、信号処理(FFTなど)
・Sin波で基準音を出力し音楽を演奏する
・Sin波の合成で音声’う’を再現する

・Audioの基本;入力、出力、信号処理(FFTなど)

【参考】
・①PyAudioの基本メモ2 音声入出力
これをまとめてやるコードは、以下のとおりです。

# -*- 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形式で出力する
Pythonでサイン波(正弦波)をつくる
参考①と②から以下のコードで基準音の440Hzを作成できます。

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ファイルをつくることもできます。
とあるので、これをやってみました。
その他の音階は以下のとおりです。
【参考】
音階の周波数

音階 ファ
周波数 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ファイルを作成します。
上記の音階の周波数はピアノの音階が出ているので、ほぼどんな曲も再現できますね。。

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はお好きな曲にアレンジしてください。

# -*- 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/データ/

・Sin波の合成で音声'う'を再現する

まず、以下のコードで音声’う’を発生して、安定したところでFFT図を得ます。
AudioAutoencoder/audio_inout.py
IntensityvsFreq_real.jpg

そして、そのFFT図を再現すべく以下のコードで’う’の波形になるように探します。
AudioAutoencoder/make_wavUfile.py
実は、FFT図は割と近い絵になりますが、実際得られる音声波形は以下のようになかなか似たような絵になりません。
f_130_250_420_530.jpg
ということで、上のコードでそれぞれのサイン波の振幅と主要な周波数(290)を調整します。
ここで、周波数は動かすと大きく様相が変わりました。
ということで、1Hz単位で動かしてみましたがそれでも以下のように変わりました。
f_130_250_420_530__266.gif
最終的に得られた合成された’う’を以下に置きました
AudioAutoencoder/データ/

まとめ

・Audioの基本を振り返った
・Sin波でメロディを作成した
・Sin波で合成音声’う’を作成してみた

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

13
15
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
13
15