環境
% 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

