2010-04-15 74 views
29

好吧即时尝试做的是一种音频处理软件,可以检测到流行的频率,如果频率播放足够长的时间(几毫秒),我知道我得到了积极的匹配。我知道我需要使用FFT或simiral的东西,但在这个数学领域我吮吸,我没有搜索互联网,但没有找到一个只能做到这一点的代码。Python频率检测

即时通讯的目标是让自己成为一种通过声音发送数据的自定义协议,每秒需要非常低的比特率(5-10bps),但即时通讯在发送端也非常有限,所以接收软件需要能够定制(不能使用实际的硬件/软件调制解调器)也我希望这只是软件(没有额外的硬件,除了声卡)

非常感谢帮助。

+1

这可能有帮助(请务必阅读回复):http://www.keyongtech.com/5003865-frequency-analysis-without-numpy – ChristopheD 2010-04-15 19:07:49

回答

37

aubio库已被SWIG封装,因此可以被Python使用。其众多功能包括音调检测/估计的几种方法,包括YIN算法和一些谐波梳理算法。然而,如果你想要简单些,我前段时间为音高估计编写了一些代码,你可以拿它或者离开它。它不会像在aubio中使用算法一样准确,但它可能足够满足您的需求。我基本上只是把数据的FFT乘以一个窗口(在这种情况下是一个Blackman窗口),FFT值的平方,找到具有最高值的bin,并且使用最大值的对数在峰值附近使用二次插值和它的两个相邻值来找到基频。我从我发现的一些论文中得到的二次插值。

它在测试音调上运行得很好,但它不会像上面提到的其他方法那样稳健或不精确。通过增加块大小(或通过减小块大小)可以提高精度。块大小应该是2的倍数以充分利用FFT。另外,我只确定每个块的基本音高,没有重叠。我用PyAudio在写出估计音高时播放声音。

源代码:

# Read in a WAV and find the freq's 
import pyaudio 
import wave 
import numpy as np 

chunk = 2048 

# open up a wave 
wf = wave.open('test-tones/440hz.wav', 'rb') 
swidth = wf.getsampwidth() 
RATE = wf.getframerate() 
# use a Blackman window 
window = np.blackman(chunk) 
# open stream 
p = pyaudio.PyAudio() 
stream = p.open(format = 
       p.get_format_from_width(wf.getsampwidth()), 
       channels = wf.getnchannels(), 
       rate = RATE, 
       output = True) 

# read some data 
data = wf.readframes(chunk) 
# play stream and find the frequency of each chunk 
while len(data) == chunk*swidth: 
    # write data out to the audio stream 
    stream.write(data) 
    # unpack the data and times by the hamming window 
    indata = np.array(wave.struct.unpack("%dh"%(len(data)/swidth),\ 
             data))*window 
    # Take the fft and square each value 
    fftData=abs(np.fft.rfft(indata))**2 
    # 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 "The freq is %f Hz." % (thefreq) 
    else: 
     thefreq = which*RATE/chunk 
     print "The freq is %f Hz." % (thefreq) 
    # read some more data 
    data = wf.readframes(chunk) 
if data: 
    stream.write(data) 
stream.close() 
p.terminate() 
+0

哇,非常感谢,这看起来像现在我会得到一个数字如何从音频实时读取音频输入(麦克风) – MatijaG 2010-04-15 23:56:37

+2

进入PyAudio站点http://people.csail.mit.edu/hubert/pyaudio/并向下滚动页面到示例,你会看到一些从麦克风输入的信息。 – 2010-04-16 00:13:35

+0

uhm can you help me figure为什么会发生此错误: “需要多于0个值才能在以下行上解压缩“ ” “y0,y1,y2 = np。log(fftData [which-1:which + 2:])“ – MatijaG 2010-04-16 14:51:49

0

虽然我之前还没有尝试过使用Python进行音频处理,但也许您可以根据SciPy(或其子项目NumPy)构建一个有效的科学/工程数值计算框架?您可以从查看scipy.fftpack开始查看FFT。

+1

好的,我发现这个http://www.swharden.com/博客/ 2010-03-05 - 实时-fft-graph-of-audio-wav-file-or-microphone-input-with-python-scipy-and -wckgraph/tho现在我想知道我将如何找到频率范围是在最高的(也是SciPy帮助了一下,谢谢 – MatijaG 2010-04-15 19:40:18

+0

所以你想怎么做? – 2017-12-05 18:10:20