PyAudioで音声を波形にしてみた

こんちには。TabiOです。
以前、音声認識技術についてという記事を書き、仕組みの部分を説明しました。
今回はPythonのPyAudioというライブラリーを使って、音声を波形にするところまでの実装をしてみました。


実行環境

MacBook Pro (13-inch, 2017)
macOS Sierra 10.12.6
プロセッサ 2.3 GHz Intel Core i5
メモリ 8GB
Python 3.5.4
Homebrew 1.6.6
pip 10.0.1
PyAudio 0.2.11

今回の流れ

  • ライブラリーをインストールして事前準備
  • 音声を可視化する
  • 実行結果についての解説

ライブラリーをインストール

PyAudioはPortAudioというツールに依存関係があるため、まずPortAudioをbrewコマンドを使ってダウンロードします。
macのメニューからターミナルを開き、下記内容を実行します。

brew install portaudio

成功すると下記のようなメッセージが表示されます。

==> Renamed Formulae
cdiff -> ydiff saltstack -> salt
crystal-lang -> crystal wpcli-completion -> wp-cli-completion
==> Deleted Formulae
aws-cloudsearch luciddb

==> Downloading https://homebrew.bintray.com/bottles/portaudio-19.6.0.high_sierr
######################################################################## 100.0%
==> Pouring portaudio-19.6.0.high_sierra.bottle.tar.gz
🍺 /usr/local/Cellar/portaudio/19.6.0: 33 files, 452KB

ここまでできたら、pipを使ってPyAudioをインストールしましょう。
ターミナルで下記を実行します。

pip install pyaudio

こんな感じのメッセージが表示されればOKです。

Successfully built pyaudio
Installing collected packages: pyaudio
Successfully installed pyaudio-0.2.11

これで準備完了です。

音声を可視化しよう!

ここからはPythonのプログラムになります。
音声の録音機能も利用するので、jupyter notebookで実行することをオススメします。

ターミナルで下記を実行するとブラウザでjupyter notebookが起動します。

jupyter notebook

下記のような画面が立ち上がります。(空のフォルダで作成しているため中身はありません)

画面右側の「New」ボタンを押すと、「python 3」というボタンがあるので押下します。
そうすると下記のような画像が立ち上がり、jupyter notebookでの実行準備ができました。

まずはプログラムの全体像を記載します。

# -*- coding: utf-8 -*-
import pyaudio
import sys
import time
import wave
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline


def recording(CHANNELS,RATE,CHUNK,RECORD_SECONDS,FORMAT,p):
    print("録音中")
    stream = p.open(format = FORMAT,
                        channels = CHANNELS,
                        rate = RATE,
                        input = True,
                        frames_per_buffer = CHUNK)

    all = []
    for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
        data = stream.read(CHUNK)
        all.append(data)
    stream.close()
    p.terminate()
    data = b''.join(all)
    print("終了")
    visualization(data)

def visualization(data):
    x = np.frombuffer(data, dtype="int16") / 10000

    plt.figure(figsize=(13,3))
    plt.plot(x)
    plt.show()

    x = np.fft.fft(np.frombuffer(data, dtype="int16"))

    plt.figure(figsize=(13,3))
    plt.plot(x.real[:int(len(x)/2)])
    plt.show()

if __name__ == '__main__':
    CHANNELS = 1
    RATE = 44100
    CHUNK = 2**11
    RECORD_SECONDS = 3
    FORMAT = pyaudio.paInt16
    p = pyaudio.PyAudio()
    recording(CHANNELS,RATE,CHUNK,RECORD_SECONDS,FORMAT,p)

・プログラムの解説

録音時間は3秒間のため、shift+enterボタンを押下して実行すると3秒間録音が始まります。

格納されたデータを波形として可視化します。
データの可視化のためmatplotlibというライブラリを使用しています。

実行した結果が下記です。

上が波形で、下がフーリエ変換した波形です。
周りがざわついていたせいであまり特徴が取れてないですね・・・
実行する際は静かな場所かつマイク等があるとより正確に波形が取れると思います。

実行結果についての解説

実行してみたけど、よくわからないと思った方に簡単に結果についてまとめました。

  • 波形(上の波形)
  • 音というのは空気の振動によって起こり、その振動は複数の周波数の振動が重なり合って構成されています。
    音の振動の中で、周波数が音の高さを決め、振幅の大きさ(上下の動き)が音の大きさ、そして、様々な周波数の振動が、音の音色を決めており、それを可視化したものが上の波形です。

  • フーリエ変換(下の波形)
  • 波形をフーリエ変換すると、その波形の中に何Hzの波がどのくらいの割合で含まれているかがわかります。
    つまりフーリエ変換とは、その波形がどんな波によりどれくらいの割合で構成されているかがわかる処理です。
    プログラムでいうと、下記箇所で実行しています。

x = np.fft.fft(np.frombuffer(data, dtype="int16"))

fftはFFT(高速離散フーリエ変換)をするためのnumpyの機能です。

まとめ

音声から波形に変換する処理を実行してみました。
今回はリアルタイムのマイクからの入力でしたが、mp3ファイル等の音声データの波形も見ることができます。
波形が大量に取得できると、ディープラーニングにも活用できますし、学習したデータをもとにどんな音なのかを認識させることができます。

最近ではRaspberry Piに実装されていたり様々なところで利用され始めています。
是非みなさんも試して見てください。

以上、TabiOでした。

参考資料