使用 python 与 pyaudio 包实时分析音频数据,通过 adapter eim 将数据发送给 Scratch,Scratch 收到数据后快速画图呈现。
Scratch 代码在此
import pyaudio
import numpy as np
import time
from codelab_adapter_client import AdapterNode
class MyNode(AdapterNode):
NODE_ID = "eim/list_data"
def __init__(self):
super().__init__()
def send_data(self, content):
message = self.message_template()
message["payload"]["content"] = content
self.publish(message)
node = MyNode()
node.receive_loop_as_thread()
time.sleep(0.1)
chunk = 1024 # 每次以 1024 个 sample 为 1 组(chunk)
num_of_bands = 10 # downsample 频率范围,合并分成 10 组呈现结果
fs = 44100 # 采样率
# 使用 pyaudio 从音频输入设备读取数据,每个 sample 以 16 bit 存储,单通道
pa = pyaudio.PyAudio()
def freq_index():
end_index = []
i = num_of_bands
while i >0:
end_index.append(int(chunk/2**i))
i = i - 1
start_index = end_index[:-1]
start_index.insert(0,0)
return start_index, end_index
start_index, end_index = freq_index()
def callback(in_data, frame_count, time_info, status):
data = np.fromstring(in_data, dtype=np.int16)
data_n = np.array(data)/(2**15)
data_w = data_n*np.hanning(len(data_n))
fft = np.abs(np.fft.fft(data_w))[0:int(chunk/2)]/chunk
fft[1:]=2*fft[1:]
out_li = [i for i in range(num_of_bands)]
for i in np.arange(num_of_bands):
fft_band = np.mean(fft[start_index[i]:end_index[i]])*10000
out_li[i]=float(fft_band)
i=i+1
node.send_data(out_li)
return(None, pyaudio.paContinue)
stream = pa.open(format=pyaudio.paInt16, channels=1, rate=fs, input=True, frames_per_buffer=int(chunk), stream_callback=callback)
stream.start_stream()
while stream.is_active():
time.sleep(1/fs*chunk)
stream.stop_stream()
stream.close()
p.terminate()