要pyqtgraph、numpy、pyaudio、pysas。
母音(あいうえお)で動作確認すると、スペクトル包絡の形状がリアルタイムに変化する様子が見られるので面白い。
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- # プロット関係のライブラリ import pyqtgraph as pg from pyqtgraph.Qt import QtCore, QtGui import numpy as np import sys # 音声関係のライブラリ import pyaudio from pysas import World sample_rate = 16000 frame_length = 1024 frame_shift = 80 class PlotWindow: def __init__(self): # プロット初期設定 self.win = pg.GraphicsWindow() self.win.setWindowTitle(u"スペクトル包絡") self.plt = self.win.addPlot() self.ymin = -100 self.ymax = 0 self.plt.setYRange(self.ymin, self.ymax) # y軸の上限、下限の設定 # Thanks to yukara 氏 self.plt.setXRange(0, frame_length / 2, padding=0) specAxis = self.plt.getAxis("bottom") specAxis.setLabel("Frequency [Hz]") specAxis.setScale(sample_rate / 2. / (frame_length / 2 + 1)) hz_interval = 500 newXAxis = ( np.arange(int(sample_rate / 2 / hz_interval)) + 1) * hz_interval oriXAxis = newXAxis / (sample_rate / 2. / (frame_length / 2 + 1)) specAxis.setTicks([zip(oriXAxis, newXAxis)]) self.curve = self.plt.plot() # プロットデータを入れる場所 self.epsiron = 0.0001 # マイク設定 self.CHUNK = frame_length # 1度に読み取る音声のデータ幅 self.RATE = sample_rate # サンプリング周波数 self.audio = pyaudio.PyAudio() self.stream = self.audio.open(format=pyaudio.paInt16, channels=1, rate=self.RATE, input=True, output=True, frames_per_buffer=self.CHUNK) # アップデート時間設定 self.timer = QtCore.QTimer() self.timer.timeout.connect(self.update) self.timer.start(10) # 10msごとにupdateを呼び出し # 音声データの格納場所(プロットデータ) self.data = np.zeros(self.CHUNK) def update(self): self.data = self.AudioInput() world = World(sample_rate) _, spec_env = world.spectral_envelope(self.data.astype(np.float64)) spec = np.mean(spec_env, axis=0) spec = 20 * np.log10(spec + self.epsiron) self.curve.setData(spec) # プロットデータを格納 def AudioInput(self): ret = self.stream.read(self.CHUNK) # 音声の読み取り(バイナリ) ret = np.frombuffer(ret, dtype="int16") / 32768 return ret if __name__ == "__main__": plotwin = PlotWindow() if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'): QtGui.QApplication.instance().exec_()
音声を取得する部分は以下の記事を参考にしました。ありがとうございました。
takeshid.hatenadiary.jp