Python PyAudio+;麦克风输入-特定频率滤波器?

Python PyAudio+;麦克风输入-特定频率滤波器?,python,audio,filtering,pyaudio,Python,Audio,Filtering,Pyaudio,我目前正在做一个射电天文学项目,在这个项目中我需要监控音频信号的振幅 我在这里使用了user1405612建议的简化Python代码,它接受麦克风输入并计算出RMS振幅,我还添加了一部分来简单地将值记录到CSV文件中。这是非常好的工作,并感谢必须得到USER1405612为它 然而,有一种方法我可以实现一个简单的频率滤波器的代码。例如,我对频率19.580khz的均方根振幅感兴趣(实际上我想看看19.4hkz到19.6hkz的范围) 有没有一种方法可以使用上面链接中的代码,例如通过查看原始流数据

我目前正在做一个射电天文学项目,在这个项目中我需要监控音频信号的振幅

我在这里使用了user1405612建议的简化Python代码,它接受麦克风输入并计算出RMS振幅,我还添加了一部分来简单地将值记录到CSV文件中。这是非常好的工作,并感谢必须得到USER1405612为它

然而,有一种方法我可以实现一个简单的频率滤波器的代码。例如,我对频率19.580khz的均方根振幅感兴趣(实际上我想看看19.4hkz到19.6hkz的范围)

有没有一种方法可以使用上面链接中的代码,例如通过查看原始流数据,或者其他任何方法来实现PyAudio?我不想要任何复杂的东西,如图形、频谱分析等,只需要一个简单的频率滤波器。不幸的是,在麦克风输入之前无法使用带通滤波器,因此需要在计算机上进行

提前谢谢

更新-2014年12月31日-她是我当前的代码:

# 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中实现同样的操作。