前提・実現したいこと
はてなブログ Webデータレポート 生活音を機械学習してみた
上記のリンクを参考にPython3を用いて、音声(wav)の機械学習をしたいと考えております。wavファイルのスペクトグラムや振幅の表示はできたのですが、MFCC(メル周波数ケプストラム係数)のあたりから上手くいかず、wavファイルからベクトルを生成することができません。
発生している問題・エラーメッセージ
Error: unknown format: 65534
該当のソースコード
Python3
1#coding:utf-8 2import wave 3import numpy as np 4import scipy.signal 5import scipy.fftpack 6import scipy.fftpack.realtransforms 7import scipy.io.wavfile 8 9def wavread(filename): 10 wf = wave.open(filename, "r") 11 fs = wf.getframerate() 12 x = wf.readframes(wf.getnframes()) 13 x = np.frombuffer(x, dtype="int16") / 32768.0 # (-1, 1)に正規化 14 wf.close() 15 return x, float(fs) 16 17def hz2mel(f): 18 """Hzをmelに変換""" 19 return 1127.01048 * np.log(f / 700.0 + 1.0) 20 21def mel2hz(m): 22 """melをhzに変換""" 23 return 700.0 * (np.exp(m / 1127.01048) - 1.0) 24 25def melFilterBank(fs, nfft, numChannels): 26 """メルフィルタバンクを作成""" 27 # ナイキスト周波数(Hz) 28 fmax = fs / 2 29 # ナイキスト周波数(mel) 30 melmax = hz2mel(fmax) 31 # 周波数インデックスの最大数 32 nmax = nfft / 2 33 # 周波数解像度(周波数インデックス1あたりのHz幅) 34 df = fs / nfft 35 # メル尺度における各フィルタの中心周波数を求める 36 dmel = melmax / (numChannels + 1) 37 melcenters = np.arange(1, numChannels + 1) * dmel 38 # 各フィルタの中心周波数をHzに変換 39 fcenters = mel2hz(melcenters) 40 # 各フィルタの中心周波数を周波数インデックスに変換 41 indexcenter = np.round(fcenters / df) 42 # 各フィルタの開始位置のインデックス 43 indexstart = np.hstack(([0], indexcenter[0:numChannels - 1])) 44 # 各フィルタの終了位置のインデックス 45 indexstop = np.hstack((indexcenter[1:numChannels], [nmax])) 46 47 filterbank = np.zeros((numChannels, nmax)) 48 for c in np.arange(0, numChannels): 49 # 三角フィルタの左の直線の傾きから点を求める 50 increment= 1.0 / (indexcenter[c] - indexstart[c]) 51 for i in np.arange(indexstart[c], indexcenter[c]): 52 i=int(i) 53 filterbank[c, i] = (i - indexstart[c]) * increment 54 # 三角フィルタの右の直線の傾きから点を求める 55 decrement = 1.0 / (indexstop[c] - indexcenter[c]) 56 for i in np.arange(indexcenter[c], indexstop[c]): 57 i=int(i) 58 filterbank[c, i] = 1.0 - ((i - indexcenter[c]) * decrement) 59 60 return filterbank, fcenters 61 62def preEmphasis(signal, p): 63 """プリエンファシスフィルタ""" 64 # 係数 (1.0, -p) のFIRフィルタを作成 65 return scipy.signal.lfilter([1.0, -p], 1, signal) 66 67def mfcc(signal, nfft, fs, nceps): 68 """信号のMFCCパラメータを求める 69 signal: 音声信号 70 nfft : FFTのサンプル数 71 nceps : MFCCの次元""" 72 # プリエンファシスフィルタをかける 73 p = 0.97 # プリエンファシス係数 74 signal = preEmphasis(signal, p) 75 76 # ハミング窓をかける 77 hammingWindow = np.hamming(len(signal)) 78 signal = signal * hammingWindow 79 80 # 振幅スペクトルを求める 81 spec = np.abs(np.fft.fft(signal, nfft))[:nfft/2] 82 fscale = np.fft.fftfreq(nfft, d = 1.0 / fs)[:nfft/2] 83 84 # メルフィルタバンクを作成 85 numChannels = 20 # メルフィルタバンクのチャネル数 86 df = fs / nfft # 周波数解像度(周波数インデックス1あたりのHz幅) 87 filterbank, fcenters = melFilterBank(fs, nfft, numChannels) 88 89 90 # 定義通りに書いた場合 91 # 振幅スペクトルに対してフィルタバンクの各フィルタをかけ、振幅の和の対数をとる 92 mspec = np.log10(np.dot(spec, filterbank.T)) 93 94 95 # 離散コサイン変換 96 ceps = scipy.fftpack.realtransforms.dct(mspec, type=2, norm="ortho", axis=-1) 97 98 # 低次成分からnceps個の係数を返す 99 return ceps[:nceps] 100 101#wavファイルと次元数を入れてMFCCを抽出 102# nfft:FFTのサンプル数 1024, 2048, 4096 103# nceps:MFCCの次元数 大体12次元が多い 104# ※ fs * cuttime >= nfft/2 を満たす値を与えなければいけない 105def get_feature(wavfile,nfft,nceps): 106 # 音声をロード 107 wav, fs = wavread(wavfile) 108 t = np.arange(0.0, len(wav) / fs, 1/fs) 109 110 # 音声波形の中心部分を切り出す 111 center = len(wav) / 2 # 中心のサンプル番号 112 cuttime = 0.8 # 切り出す長さ [s] 113 wavdata = wav[int(center - cuttime/2*fs) : int(center + cuttime/2*fs)] 114 115 ceps = mfcc(wavdata, nfft, fs, nceps) 116 return ceps.tolist() 117 118if __name__ == "__main__": 119 wavfile= "call01.wav" #1 120 nfft=2048 121 nceps=12 122 tmp = get_feature(wavfile,nfft,nceps) 123 print (tmp) #2 124 125
試したこと
前回の質問より、ほとんどリンク元のコードのまま実行してみました。変更点といたしましては、下から5行目(#1)と1行目(#2)のコードの
1.参照するファイル名の変更
2.printに()をつけたこと。(リンク元のコードがPython2.7のため)
を行いました。
少し調べてみたところ、
Why GitHub? wave.Error: unknown format: 65534 #129
上記でも似たようなエラーで困っている人を見つけ、色々とコードをいじってみてはいるのですが、上手くいきません。
補足情報(FW/ツールのバージョンなど)
Python3.6.5です
回答1件
あなたの回答
tips
プレビュー