Python PyAudio+;麦克风输入-特定频率滤波器?
我目前正在做一个射电天文学项目,在这个项目中我需要监控音频信号的振幅 我在这里使用了user1405612建议的简化Python代码,它接受麦克风输入并计算出RMS振幅,我还添加了一部分来简单地将值记录到CSV文件中。这是非常好的工作,并感谢必须得到USER1405612为它 然而,有一种方法我可以实现一个简单的频率滤波器的代码。例如,我对频率19.580khz的均方根振幅感兴趣(实际上我想看看19.4hkz到19.6hkz的范围) 有没有一种方法可以使用上面链接中的代码,例如通过查看原始流数据,或者其他任何方法来实现PyAudio?我不想要任何复杂的东西,如图形、频谱分析等,只需要一个简单的频率滤波器。不幸的是,在麦克风输入之前无法使用带通滤波器,因此需要在计算机上进行 提前谢谢 更新-2014年12月31日-她是我当前的代码:Python PyAudio+;麦克风输入-特定频率滤波器?,python,audio,filtering,pyaudio,Python,Audio,Filtering,Pyaudio,我目前正在做一个射电天文学项目,在这个项目中我需要监控音频信号的振幅 我在这里使用了user1405612建议的简化Python代码,它接受麦克风输入并计算出RMS振幅,我还添加了一部分来简单地将值记录到CSV文件中。这是非常好的工作,并感谢必须得到USER1405612为它 然而,有一种方法我可以实现一个简单的频率滤波器的代码。例如,我对频率19.580khz的均方根振幅感兴趣(实际上我想看看19.4hkz到19.6hkz的范围) 有没有一种方法可以使用上面链接中的代码,例如通过查看原始流数据
# source https://stackoverflow.com/questions/4160175/detect-tap-with-pyaudio-from-live-mic
import pyaudio
import struct
import math
import datetime
FORMAT = pyaudio.paInt16
SHORT_NORMALIZE = (1.0/32768.0)
CHANNELS = 1
#RATE = 44100
RATE = 48000
INPUT_BLOCK_TIME = 1
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME)
filename = 'Data.CSV'
def get_rms(block):
count = len(block)/2
format = "%dh"%(count)
shorts = struct.unpack( format, block )
# iterate over the block.
sum_squares = 0.0
for sample in shorts:
# sample is a signed short in +/- 32768.
# normalize it to 1.0
n = sample * SHORT_NORMALIZE
sum_squares += n*n
return math.sqrt( sum_squares / count )
pa = pyaudio.PyAudio()
stream = pa.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
frames_per_buffer = INPUT_FRAMES_PER_BLOCK)
errorcount = 0
for i in range(1000):
try:
block = stream.read(INPUT_FRAMES_PER_BLOCK)
except IOError, e:
errorcount += 1
print( "(%d) Error recording: %s"%(errorcount,e) )
noisycount = 1
amplitude = get_rms(block)
print amplitude
#writeCSV
i = datetime.datetime.now()
f = open(filename,"a")
f.write("{},{}\n".format(i,amplitude))
f.close()
SciPy具有数字带通信号所需的所有功能 带通滤波器的设计 对于这个例子,我将使用
scipy.signal.butter
,设计一个三阶巴特沃斯带通滤波器:
def design_filter(lowcut, highcut, fs, order=3):
nyq = 0.5*fs
low = lowcut/nyq
high = highcut/nyq
b,a = butter(order, [low,high], btype='band')
return b,a
运行过滤器
函数的返回是一组滤波器系数,可由spick.signal.lfilter
函数使用。您将发现的大多数示例都是对批处理数据进行操作的,因此它们只调用函数一次。由于您处理的是实时流,因此您的流将有点棘手。该函数将以前的筛选器状态作为参数,并返回新状态。因此,您需要存储返回的状态,以便下次可以传递它。这大概就是它在现有代码中的工作方式。您需要从get_rms函数中重构数据规范化,这不是一个坏主意:
def normalize(block):
count = len(block)/2
format = "%dh"%(count)
shorts = struct.unpack( format, block )
doubles = [x * SHORT_NORMALIZE for x in shorts]
return doubles
def get_rms(samples):
sum_squares = 0.0
for sample in doubles:
sum_squares += n*n
return math.sqrt( sum_squares / count )
pa = pyaudio.PyAudio()
stream = pa.open(format = FORMAT,
channels = CHANNELS,
rate = RATE,
input = True,
frames_per_buffer = INPUT_FRAMES_PER_BLOCK)
errorcount = 0
# design the filter
b,a = design_filter(19400, 19600, 48000, 3)
# compute the initial conditions.
zi = lfilter_zi(b, a)
for i in range(1000):
try:
block = stream.read(INPUT_FRAMES_PER_BLOCK)
except IOError as e:
errorcount += 1
print( "(%d) Error recording: %s"%(errorcount,e) )
noisycount = 1
samples = normalize(block)
bandpass_samples,zi = lfilter(b, a, samples, zi)
amplitude = get_rms(samples)
bandpass_ampl = get_rms(bandpass_samples)
print(amplitude)
print(bandpass_ampl)
很抱歉,我无法运行此代码进行测试。尽管有可能,
样本
需要转换为np.数组。非常感谢。我看了一下scipy,认为它可以胜任这项工作。然而,我在代码中实现它时遇到了困难。我现在已经在我的原始问题中包含了我的代码。在我的例子中,我会怎么做,因为我在互联网上找到的大多数其他例子都没有将它与pyaudio结合使用?我试过使用你的向导,但可惜我没有任何运气。我还假设scypi.signal.butter中的scypi是一种类型,应该是scypy?非常感谢!在这段代码中,我在len(block)/2a处得到一个语法错误。是应该是2而不是2a,还是应该是2*a
(a
添加到参数列表中)?@DanielMarschall。编辑。我是说2。在C++中,它将是sieof(Stof),但我不确定如何在Python中实现同样的操作。