つまりなにしたの?
PyAudioでマイクから入ってきた音にScipyのフィルタをかけてそのまま再生してみた。
環境
% python Python 3.6.4 (default, Mar 2 2018, 00:45:54) [GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import pyaudio >>> pyaudio.__version__ '0.2.11' >>> import scipy >>> scipy.__version__
大まかな方針
前回Callback方式でデータをそのまま再生してみたので、
その再生する際のデータに途中でフィルタを掛けて見ることとする。
ここで適用したいフィルタは
Signal processing (scipy.signal) — SciPy v1.2.0 Reference Guide
ここのFilter designと書かれているもの。
コード
import pyaudio import numpy as np from scipy import signal import matplotlib.pyplot as plt import struct import time class AudioFilter(): def __init__(self): # オーディオに関する設定 self.p = pyaudio.PyAudio() self.channels = 1 # ステレオの場合は2 self.rate = 48000 self.dt = 1/self.rate self.format = pyaudio.paInt16 self.stream = self.p.open( format=self.format, channels=self.channels, rate=self.rate, output=True, input=True, stream_callback=self.callback) # フィルタの設計を行っているところ(1500Hzで4001次のローパスフィルタをかけてみている) self.filter1 = signal.firwin(numtaps=4000, cutoff=1500, fs=self.rate) # コールバック関数(再生が必要なときに呼び出される) def callback(self, in_data, frame_count, time_info, status): amp = np.fromstring(in_data, np.int16) amp[::2] = np.array(signal.lfilter(self.filter1, 1, amp[::2])) amp[1::2] = np.array(signal.lfilter(self.filter1, 1, amp[1::2])) amp = np.reshape(amp, (frame_count*self.channels, 1)) out_data = amp.astype(np.int16).tostring() return (out_data, pyaudio.paContinue) def close(self): self.p.terminate() if __name__ == "__main__": # AudioFilterのインスタンスを作る場所 af = AudioFilter() # ストリーミングを始める場所 af.stream.start_stream() # ノンブロッキングなので好きなことをしていていい場所 while af.stream.is_active(): time.sleep(0.1) # ストリーミングを止める場所 af.stream.stop_stream() af.stream.close() af.close()
FIRフィルタの使い方についてはここを参照
scipy.signal.firwin — SciPy v0.15.1 Reference Guide
実行方法
% python filter.py