我的目标是编写一个Python程序,该程序记录来自麦克风的声音并连续打印特定频率范围(使用带通滤波器)的音量。
下面是我当前拥有的代码。我花了几个小时搜索有关该主题或代码示例的更多信息,但没有找到任何有用的信息(我能理解)或没有合适的示例代码。不幸的是,我对FFT的了解非常有限。
当前,我有两个问题:
问题1:。带通滤波器不起作用。我将其设置为300Hz..500Hz,但实际上并没有过滤任何内容。作为示例,我添加了一个显示信号主要频率的代码,因此我可以查看滤波器是否正常工作(为了进行测试,我使用频率发生器应用播放声音)。频率检测效果很好,但是信号没有被滤波到300..500Hz。
问题2:如何确定音量?我的想法是使用noiselevel = np.average(fftData)
来找出fftData数组中所有频率上的平均音量。但这是行不通的:输出似乎不稳定,对麦克风中播放的大声声音也没有反应。
感谢您的帮助。非常感谢你!
#!/usr/bin/env python3
import pyaudio
import numpy as np
from scipy.signal import butter, sosfilt
def butter_bandpass(lowcut, highcut, fs, order=5):
nyq = 0.5 * fs
low = lowcut / nyq
high = highcut / nyq
sos = butter(order, [low, high], analog=False, btype='band', output='sos')
return sos
def butter_bandpass_filter(data, lowcut, highcut, fs, order=5):
sos = butter_bandpass(lowcut, highcut, fs, order=order)
y = sosfilt(sos, data)
return y
CHUNK = 2*4096 # number of data points to read at a time
RATE = 48000 # time resolution of the recording device (Hz)
DEVICE = 0 # default
p = pyaudio.PyAudio()
stream=p.open(format=pyaudio.paInt16,channels=1,rate=RATE,input=True, input_device_index=DEVICE,
frames_per_buffer=CHUNK)
while True:
indata = np.fromstring(stream.read(CHUNK),dtype=np.int16)
# Remove everything except 300Hz..500Hz
# TODO: does not work
#indata = butter_bandpass_filter(indata, 300, 500, RATE, order=5)
# Take the fft and square each value
fftData=abs(np.fft.rfft(indata))**2
# TODO: find out volume
noiselevel = np.average(fftData)
print("Volume of 300Hz..500Hz: %f" % (noiselevel))
# JUST FOR TESTING: Find out frequency (to see if band pass works correctly)
# find the maximum
which = fftData[1:].argmax() + 1
# use quadratic interpolation around the max
if which != len(fftData)-1:
y0,y1,y2 = np.log(fftData[which-1:which+2:])
x1 = (y2 - y0) * .5 / (2 * y1 - y2 - y0)
# find the frequency and output it
thefreq = (which+x1)*RATE/CHUNK
print("Frequency: %f Hz." % (thefreq))
else:
thefreq = which*RATE/CHUNK
print("Frequency: %f Hz." % (thefreq))
# END <JUST FOR TESTING>
stream.close()
p.terminate()
更新:这是我的第二次尝试,没有过滤器:
while True:
indata = np.fromstring(stream.read(CHUNK),dtype=np.int16)
# Get volume of 440 Hz
fftData=np.fft.rfft(indata)
freqs = np.fft.rfftfreq(fftData.size)
idx = (np.abs(freqs-440)).argmin()
volume = np.abs(fftData[idx]) # does not work
print(volume)