・やっていること
現在Pythonを使用して音声解析をしています。
指定したヘルツ数で数値を抽出したいのですが、どのように抽出したら良いのかがわかりません。
使用しているコード
Python
1import struct 2import wave 3import math 4from matplotlib.colors import same_color 5import numpy as np 6import matplotlib.pyplot as plt 7def main(): 8 filename = "1_cut1.wav" 9 wf = wave.open(filename, "r" ) 10 # WAVファイルの情報を表示 11 print ("オーディオチャンネル数(モノラル: 1 ステレオ:2 ) : ", wf.getnchannels()) 12 print ("サンプルサイズ(バイト数) : ", wf.getsampwidth()) 13 print ("サンプリングレート : ", wf.getframerate()) 14 print ("オーディオフレーム数 : ", wf.getnframes()) 15 print ("圧縮形式 : ", wf.getcomptype()) 16 print ("(圧縮形式) : ", wf.getcompname()) 17 print ("パラメータ : ", wf.getparams()) 18 print ("記録時間(Sec) : ", float(wf.getnframes()) / wf.getframerate() ) 19 sw = wf.getsampwidth() #バイト数 20 fs = wf.getframerate() #サンプリング周波数 21 nf = wf.getnframes() #オーディオフレーム数 22 fc = 2000 #下限 # カットオフ周波数 23 fb = 5000 #上限 24 mado = float(wf.getnframes()) / wf.getframerate() 25 g = wf.readframes(wf.getnframes()) 26 g = np.frombuffer(g, dtype= "int16")/32768.0 # -1~1に正規化 27 #mado = math.floor(wf.getnframes() / wf.getframerate()) #全体 28 N = mado*fs # サンプル数=窓(1秒)×サンプリング周波数 29 wf.close() 30 # for ki in range(round(wf.getnframes()/fs)-1): 31 gz = g[::2] # サンプル数片方にわける 32 G = np.fft.fft(gz) # 高速フーリエ変換 33 #逆フーリエ変換 34 hpG = [(0.0+0.0j if xi < fc*mado else c.real+c.imag*1j )for xi,c in enumerate(G)] 35 hpG = [(0.0+0.0j if xi > len(G)-fc*mado else c.real+c.imag*1j )for xi,c in enumerate(hpG)] 36 hpG = [(0.0+0.0j if xi < fs/2 and xi > fb*mado else c.real+c.imag*1j )for xi,c in enumerate(hpG)] 37 hpG = [(0.0+0.0j if xi > fs/2 and xi < len(G)-fb*mado else c.real+c.imag*1j )for xi,c in enumerate(hpG)] 38 r = np.fft.ifft(hpG,n=N) 39 r = [x.real*32768 for x in r] 40 r = np.array(r,dtype=np.int16) 41 print(r) 42 print(r[2000:5000]) #配列0が0Hzの場合これかな? 43 print(r[0:3000]) #配列0が2000Hzの場合これかな? 44 fmt = '{}h'.format(len(r)) 45 r = struct.pack(fmt, *r) 46 #全部 47 # fOut = wave.open("C:\Users\hiro2\Desktop\sound\kara\"+str(ki)+"_"+str(ki+1)+"section.wav", "wb") 48 fOut = wave.open("2_cut5_bp.wav", "wb") 49 fOut.setparams((1,sw,fs,nf, "NONE", "not compressed")) 50 fOut.writeframes(r) 51 fOut.close() 52if __name__ == '__main__': 53 main()
上記のコードを使用していて、40行目の
Python
1r = np.array(r,dtype=np.int16)
の配列から2000Hz~5000Hzの間で数値を抽出して新たな配列に突っ込みたいのですが、どのように指定すればよいのか。
また、配列の0番目が何を表しているのかがわかりません。
・試してみたこと
Python
1print(r[2000:5000]) #配列0が0Hzの場合これかな? 2print(r[0:3000]) #配列0が2000Hzの場合これかな?
上記のように実験してみたもののよくわからなかったです。
使用しているコードはバンドパスフィルターをかけたものなのですが、この配列にバンドパスの影響が出ているのかもあまりわかっていません。
わかる方いらっしゃいましたら教えていただきたいです。
https://teratail.com/questions/368287
に記載のコードのように、
np.fft.fft(...
のところに
np.fft.fftfreq(...
を追加して周波数を計算して、その周波数で2000〜5000になる範囲の位置に相当する「np.fft.fft(...」を取り出せば、
> 2000Hz~5000Hzの間で数値を抽出
になります
import numpy as np
xxx=np.arange(20)
yyy=np.arange(20)+100
print(xxx)
print(yyy)
print(xxx[np.where((yyy>105)&(yyy<112))])
で、yyyが105よりも大きくて112よりも小さい範囲に相当するxxxの値を取り出せます
yyyが「np.fft.fftfreq(...」の結果の周波数で、xxxが「np.fft.fft(...」の結果なら、同じやり方で特定の周波数範囲の値だけ取り出せますよね
【追記】
print(xxx[np.where((yyy>105)&(yyy<112))])
↓ 変更
print(xxx[(yyy>105)&(yyy<112)])
でも、できます
なるほど!
ありがとうございます。
回答1件
あなたの回答
tips
プレビュー