人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

波形を見る

Pythonで音声信号処理(2011/05/14)

サイン波

次は音の波をプロットして目に見えるようにしてみます。グラフの描画にはPythonのmatplotlibを使います。WAVEファイルには音をディジタル化(標本化 + 量子化)したデータがそのまま含まれているのでそれを読み出します。WAVEファイルの詳細なフォーマットはwavファイルフォーマットが参考になりました。自分でバイナリを分析してもよいですが、waveモジュールがやってくれます。

#coding:utf-8
import wave
from numpy import *
from pylab import *

def printWaveInfo(wf):
    """WAVEファイルの情報を取得"""
    print "チャンネル数:", wf.getnchannels()
    print "サンプル幅:", wf.getsampwidth()
    print "サンプリング周波数:", wf.getframerate()
    print "フレーム数:", wf.getnframes()
    print "パラメータ:", wf.getparams()
    print "長さ(秒):", float(wf.getnframes()) / wf.getframerate()

if __name__ == '__main__':
    wf = wave.open("sineWithNoise.wav", "r")
    printWaveInfo(wf)
    
    buffer = wf.readframes(wf.getnframes())
    print len(buffer)  # バイト数 = 1フレーム2バイト x フレーム数

    # bufferはバイナリなので2バイトずつ整数(-32768から32767)にまとめる
    data = frombuffer(buffer, dtype="int16")

    # プロット
    plot(data)
    show()

これを実行すると

f:id:aidiary:20110528094654p:plain

波形がつぶれてしまって見えません。そこで、サイン波の5周期分のみ描画します。そうなると1周期分が何サンプルにあたるかが問題です。

  • 波の基本周波数f0は、440Hzなので1秒間に440回振動
  • サンプリング周波数fsは、44100Hzなので1秒間に44100回サンプリング

ということは波の1周期の長さは1/440秒となり、これは44100 * (1/440) で100サンプル分に相当します。なので5周期分は500サンプルです。波の基本周波数とサンプリング周波数って同じHzだからちょっと混乱するけど。というわけで500サンプルだけ描画してみました。

    plot(data[0:500])

と書き直してグラフをプロットしてみると

f:id:aidiary:20110528094653p:plain

大成功!サイン波にノイズが乗っていることがわかりました。うーん、WAVEファイルってのはその名前の通り本当に波のデータがそのまま入ってるんですね〜。量子化ビット数は16bitなので-32768から32767(short型)で0を中心とした波であることもわかりました。次に、880Hzのノイズありサイン波を描画してみます。さっきは440Hzなので2倍高い音になります。結果は、

f:id:aidiary:20110528113516p:plain

同じ500サンプルの区間に波が10個なのでさっきより2倍多いことがわかりました。最後に、音の大きさを2倍にしてみます。

f:id:aidiary:20110528114530p:plain

先ほどと比べて波の振幅が大きいことがわかりました。short型の-32768〜32767の間に収まりきらず、上下が切れています(クリッピング)。

楽器の音

次に、楽器の音の波形を見てみます。今、勉強に使っている下の本のサンプルページにギターの音とリコーダーの音が含まれているのでそれで試してみます。chapter2.zipに入っています。

C言語ではじめる音のプログラミング―サウンドエフェクトの信号処理

C言語ではじめる音のプログラミング―サウンドエフェクトの信号処理

guitar_A4.wavとrecorder_A4.wavというファイルですが、サンプリング周波数は8000Hz、5秒間の音です。A4というのは、440Hzの「ラ」の音だそうです。

f:id:aidiary:20110528113517p:plain
f:id:aidiary:20110528113518p:plain

音の高さは同じなので含まれている波の数は同じだけど、ギターとリコーダーは波の形が違うことがわかりました。つまり、楽器による音色の違いは波形に現れるってことでした。

音楽の波

次にMP3の音楽の波を見てみました。ゲーム製作(2008/7/12)でもお世話になっていたTAM Music Factoryさんの「夏の恋」って曲で見てみます。私、ここの曲けっこう好きなのでこれをベースに類似楽曲検索やりたいんですよね。提供されている楽曲はMP3なので、まずWAVEに変換します。これには、ffmpegっていう超有名ツールを使います。無償のFFmpegでWavファイルの変換が参考になります。

ffmpeg -i tamsu02.mp3 -ac 1 -ar 44100 -acodec pcm_s16le tamsu02.wav

で44100Hz、16bit、モノラルに変換できます。さっそく、さっきのプログラムで波形を見てみます。まずは、全体波形

f:id:aidiary:20110528120502p:plain

つぶれてしまってよくわからないので、500000サンプルから510000サンプルまで拡大表示

f:id:aidiary:20110528120503p:plain

音楽ってのはすごい複雑な波なんですね。このような複雑な波を簡単なサイン波の合成で表すってのがフーリエ変換です。これは後で試してみます。

人の声の波

最後に人間の声の波を見てみました。Praatを使うと簡単に録音できますが、これについては後で書こうかな。母音の「あ」「い」「う」「え」「お」を8000Hz、16bit、モノラルで録音して描画してみました。左上からあいうえおの順です。WAVEファイルは恥ずかしいのでアップしない(笑)

f:id:aidiary:20110528124055p:plain
f:id:aidiary:20110528124056p:plain
f:id:aidiary:20110528124057p:plain
f:id:aidiary:20110528124058p:plain
f:id:aidiary:20110528124059p:plain

母音は周期的な波であることがわかります。波形は微妙に違いますね。これは人によって違うし、同じ人でも場合によって異なることもあるみたいです。この母音の波形から特徴量を抽出し、機械学習で識別することが音声認識の第一歩ですね!これについてはだいぶ後になりますがいずれ試してみたいと思います。

音の三要素

最後に、重要な音の三要素についてまとめ。音の三要素は、

  • 音の大きさ : 波の振幅に相当。大きい音ほど振幅が大きい。
  • 音の高さ : 波の周波数、周期に相当。高い音ほど周波数が高く、周期が短い。
  • 音色 : 波の形に相当。

音色だけまだ抽象的ですが、これからいろいろな特徴量で数値化できるようになるはずです。今回までは、すでにあるWAVEファイルを再生したり、波形を見るだけでしたが、次回は、自分でサイン波を合成していろんな音を出してみたいと思います。