当前位置: 首页 > 面试题库 >

使用来自现场麦克风的pyaudio检测点击

叶茂才
2023-03-14
问题内容

我将如何使用pyaudio来检测现场麦克风的突然敲击声?


问题答案:

我这样做的一种方式:

  • 一次读取一块样本,比如说值得0.05秒
  • 计算块的RMS幅度(各个样本的平方的平均值的平方根)
  • 如果块的RMS幅度大于阈值,则为“嘈杂的块”,否则为“安静的块”
  • 突然的敲击将是一个安静的区域,然后是少量的噪音区域,然后是一个安静的区域
  • 如果您从不安静,则门槛太低
  • 如果您从不听到嘈杂的声音,则您的门槛太高

我的应用程序正在录制无人看管的“有趣”噪音,因此只要有嘈杂的声音,它就会录制下来。如果有15秒的嘈杂时间(“遮住耳朵”),则将阈值乘以1.1;如果有15
分钟的 安静时间(“更难听”),则将阈值乘以0.9 。您的应用程序将有不同的需求。

此外,刚刚注意到我的代码中有关观察到的RMS值的一些注释。在Macbook Pro的内置麦克风上,标准化的音频数据范围为+/-
1.0,输入音量设置为max,一些数据点:

  • 0.003-0.006(-50dB至-44dB)我家的中央暖气风扇
  • 在同一台笔记本电脑上键入0.010-0.40(-40dB至-8dB)
  • 0.10(-20dB)在1’距离处轻柔地弹指
  • 0.60(-4.4dB)在1’处大声响动

更新:这是一个入门的示例。

#!/usr/bin/python

# open a microphone in pyAudio and listen for taps

import pyaudio
import struct
import math

INITIAL_TAP_THRESHOLD = 0.010
FORMAT = pyaudio.paInt16 
SHORT_NORMALIZE = (1.0/32768.0)
CHANNELS = 2
RATE = 44100  
INPUT_BLOCK_TIME = 0.05
INPUT_FRAMES_PER_BLOCK = int(RATE*INPUT_BLOCK_TIME)
# if we get this many noisy blocks in a row, increase the threshold
OVERSENSITIVE = 15.0/INPUT_BLOCK_TIME                    
# if we get this many quiet blocks in a row, decrease the threshold
UNDERSENSITIVE = 120.0/INPUT_BLOCK_TIME 
# if the noise was longer than this many blocks, it's not a 'tap'
MAX_TAP_BLOCKS = 0.15/INPUT_BLOCK_TIME

def get_rms( block ):
    # RMS amplitude is defined as the square root of the 
    # mean over time of the square of the amplitude.
    # so we need to convert this string of bytes into 
    # a string of 16-bit samples...

    # we will get one short out for each 
    # two chars in the string.
    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 )

class TapTester(object):
    def __init__(self):
        self.pa = pyaudio.PyAudio()
        self.stream = self.open_mic_stream()
        self.tap_threshold = INITIAL_TAP_THRESHOLD
        self.noisycount = MAX_TAP_BLOCKS+1 
        self.quietcount = 0 
        self.errorcount = 0

    def stop(self):
        self.stream.close()

    def find_input_device(self):
        device_index = None            
        for i in range( self.pa.get_device_count() ):     
            devinfo = self.pa.get_device_info_by_index(i)   
            print( "Device %d: %s"%(i,devinfo["name"]) )

            for keyword in ["mic","input"]:
                if keyword in devinfo["name"].lower():
                    print( "Found an input: device %d - %s"%(i,devinfo["name"]) )
                    device_index = i
                    return device_index

        if device_index == None:
            print( "No preferred input found; using default input device." )

        return device_index

    def open_mic_stream( self ):
        device_index = self.find_input_device()

        stream = self.pa.open(   format = FORMAT,
                                 channels = CHANNELS,
                                 rate = RATE,
                                 input = True,
                                 input_device_index = device_index,
                                 frames_per_buffer = INPUT_FRAMES_PER_BLOCK)

        return stream

    def tapDetected(self):
        print("Tap!")

    def listen(self):
        try:
            block = self.stream.read(INPUT_FRAMES_PER_BLOCK)
        except IOError as e:
            # dammit. 
            self.errorcount += 1
            print( "(%d) Error recording: %s"%(self.errorcount,e) )
            self.noisycount = 1
            return

        amplitude = get_rms( block )
        if amplitude > self.tap_threshold:
            # noisy block
            self.quietcount = 0
            self.noisycount += 1
            if self.noisycount > OVERSENSITIVE:
                # turn down the sensitivity
                self.tap_threshold *= 1.1
        else:            
            # quiet block.

            if 1 <= self.noisycount <= MAX_TAP_BLOCKS:
                self.tapDetected()
            self.noisycount = 0
            self.quietcount += 1
            if self.quietcount > UNDERSENSITIVE:
                # turn up the sensitivity
                self.tap_threshold *= 0.9

if __name__ == "__main__":
    tt = TapTester()

    for i in range(1000):
        tt.listen()


 类似资料:
  • 使用光环板制作一个音量检测计,通过光环板的麦克风检测音量大小,并通过可视化的形式呈现出来,音量越大,LED灯环亮起的灯就越多。 1. 从事件类积木拖取一个 当按钮被按下时 积木。 2. 从控制类积木拖取一个 重复执行 积木。 3. 从灯光类积木拖取一个 显示LED环形图()% 积木,再添加一个传感器类积木 麦克风 响度。 4. 试着拍下桌子,看光环板LED环形图的变化吧! 下载代码

  • 大家好,我正在使用Peer Js创建一个WebRtc,就像一个视频通话一样,我只想创建一个按钮,当用户点击它时,关掉麦克风,这段代码在script.Js中: 这是Html代码: 所以我创建了这个按钮: 那么我如何制作一个能够禁用麦克风的脚本呢?

  • 问题内容: 我正在尝试通过Java访问麦克风的级别。我不需要录制任何东西,我只想知道声音水平的相对范围。 这可以实时吗? 如果这是不可能的,那么这可能会起作用:当电平超过某个值时开始记录,当电平下降到一定水平以下一段时间后停止录制四分之一秒的位并读取它的音量,如果它在阈值以下停止录音。 提前致谢 问题答案: 您可以通过Sound API访问麦克风,但不会给您简单的响度级别。您只需要捕获数据并就其声

  • 问题内容: 我需要快速开发一个iOS应用程序,以检测用户的麦克风是否受到打击。这必须是一个挑战游戏,其中两个玩家必须一个接一个地吹入iPhone麦克风。分贝值应以米或公里为单位进行测量和换算,以便我确定获胜者。“进一步打击”的玩家(玩家1:50公里,玩家2:70公里)获胜。 这可能吗? 我很快就收到了这段代码,但我不知道如何进行: 谢谢你! 问题答案: 关。您有几个问题。您的选择器调用使该应用程序

  • 当我启动音频/屏幕录像机并打开我的录音机应用程序并启动用于录制音频的服务时,我遇到错误该应用程序崩溃。 我不知道为什么我会面临这个问题。 来自logcat的错误跟踪 录制服务.java 录音活动 这就是我尝试在应用程序中开始录制时发生的情况 链接如下。 显示我的应用程序崩溃

  • 我想直播Android麦克风,可以使用VLC播放器等听到。 Playstore主要提供IP摄像头应用,但这些应用是通过内部网络实现的。我想在互联网上播放流媒体。 可能吗? 我尝试了以下代码片段,但目前不起作用: 在VLC播放器前,我试着听(媒体)- 还有别的办法吗?