使用GStreamer(或其他库)检测麦克风的吹气声
我可以用GStreamer(或者其他适合Linux的声音库)来检测麦克风前吹气的声音吗?
我可以通过这样做获取一些声音的信息:
import gtk, gst
def playerbinMessage(bus, message):
if message.type == gst.MESSAGE_ELEMENT:
struct = message.structure
if struct.get_name() == 'level':
# printing peak, decay, rms
print struct['peak'][0], struct['decay'][0], struct['rms'][0]
pipeline = gst.parse_launch('pulsesrc ! level ! filesink location=/dev/null')
bus = pipeline.get_bus()
bus.add_signal_watch()
bus.connect('message', playerbinMessage)
pipeline.set_state(gst.STATE_PLAYING)
gtk.main()
我用这个来检测拍手的声音,但我不知道能不能用这些信息来检测吹气的声音,而不让我的电脑把吹气和说话搞混。此外,我也不清楚有没有其他方法可以用GStreamer或其他Linux兼容的声音库来分析声音。
3 个回答
0
CMU Sphinx项目是一个语音识别工具包,你可以在这里找到它:http://cmusphinx.sourceforge.net/。这个工具包可以利用gstreamer来提供麦克风的音频流。你可以去看看。
0
这只是一个答案和操作代码的混合(示例管道)
#!/usr/bin/env python
import pygtk
pygtk.require('2.0')
import gtk, gst, time
class HelloWorld:
def delete_event(self, widget, event, data=None):
print "delete event occurred"
return False
def destroy(self, widget, data=None):
print "destroy signal occurred"
gtk.main_quit()
def __init__(self):
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
self.window.connect("delete_event", self.delete_event)
self.window.connect("destroy", self.destroy)
self.window.set_border_width(2)
#self.window.set_size_request(600, 483)
""" Play """
self.vbox = gtk.VBox(False, 2)
self.vbox.set_border_width(0)
self.hbox = gtk.HBox()
self.hlpass = gtk.Entry()
self.hlpass.set_text("low-pass")
self.hbox.pack_start( gtk.Label("High/Low-pass: "), False, False, 0 )
self.hbox.pack_start( self.hlpass, False, False, 0 )
self.vbox.add(self.hbox)
self.hbox = gtk.HBox()
self.cutoff = gtk.Entry()
self.cutoff.set_text("40")
self.hbox.pack_start( gtk.Label("Cutoff: "), False, False, 0 )
self.hbox.pack_start( self.cutoff, False, False, 0 )
self.vbox.add(self.hbox)
self.hbox = gtk.HBox()
self.poles = gtk.Entry()
self.poles.set_text("4")
self.hbox.pack_start( gtk.Label("Poles: "), False, False, 0 )
self.hbox.pack_start( self.poles, False, False, 0 )
self.vbox.add(self.hbox)
self.hbox = gtk.HBox()
self.button = gtk.Button("High-Pass")
self.button.connect("clicked", self.change, None)
self.hbox.pack_start(self.button, False, False, 0 )
self.vbox.add(self.hbox)
self.window.add(self.vbox)
self.window.show_all()
def main(self):
self.gst()
gtk.main()
def gst(self):
test = """
alsasrc device=hw:0 ! audioconvert ! audioresample ! audiocheblimit mode=low-pass cutoff=40 poles=4 name=tuneit ! level ! autoaudiosink
"""
self.pipeline = gst.parse_launch(test)
self.bus = self.pipeline.get_bus()
self.bus.add_signal_watch()
self.bus.connect('message', self.playerbinMessage)
self.pipeline.set_state(gst.STATE_PLAYING)
def playerbinMessage(self,bus, message):
if message.type == gst.MESSAGE_ELEMENT:
struct = message.structure
if struct.get_name() == 'level':
print struct['peak'][0], struct['decay'][0], struct['rms'][0]
#time.sleep(1)
def change(self, widget, data=None):
data = [self.hlpass.get_text(), self.cutoff.get_text(), self.poles.get_text()]
print data[0], data[1], data[2]
self.audiocheblimit = self.pipeline.get_by_name('tuneit')
self.audiocheblimit.props.mode = data[0]
self.audiocheblimit.props.cutoff = int( data[1] )
self.audiocheblimit.props.poles = int ( data[2] )
if __name__ == "__main__":
hello = HelloWorld()
hello.main()
低通输出:
-20.9227157774 -20.9227157774 -20.953279177
-20.9366239523 -20.9227157774 -20.9591815321
-20.9290995367 -20.9227157774 -20.9601319723
高通输出:
-51.2328030138 -42.8335117509 -62.2730163502
-51.3932079772 -43.3559607159 -62.2080540769
-52.1412276733 -43.8784096809 -62.9151309943
编辑:
high-pass = speech and taking all audio
low-pass = some audio like when you are talking near the microphone
3
要区分吹气声和说话声,光看音量是不够的。首先要知道,大多数说话的声音频率都在80Hz以上,而对着麦克风吹气会产生很多低频的隆隆声。
所以,如果你想继续使用gstreamer,可以试试用“audiocheblimit”这个滤镜,先把声音的低频部分过滤掉,然后再测量音量。(可以用类似 audiocheblimit mode=low-pass cutoff=40 poles=4
的命令)
我个人的做法会更简单一些:
- 用像python-alsaaudio这样的工具录制原始音频
- 使用numpy计算声音片段的傅里叶变换
- 把低频(比如20-40Hz)的幅度加起来,如果这个值足够大,就触发相应的操作。
如果这样还不行,我就会寻找更聪明的检测算法。这种alsa+numpy的方法非常灵活,但比gstreamer的方法稍微复杂一点。
补充:我刚注意到gstreamer还有一个“spectrum”元素,可以返回傅里叶变换的结果。