Speech recognition 编写软件告知声音来自何处(定向聆听)

Speech recognition 编写软件告知声音来自何处(定向聆听),speech-recognition,wav,audio,waveform,Speech Recognition,Wav,Audio,Waveform,我对这件事好奇了一段时间,所以我想也许在这里我可以得到一些好的答案 到目前为止我所知道的: 人类不仅可以用两只耳朵听到“听起来像”的声音 但他们来自哪里。音高是我们听到的音符 类似人声的东西有不同的音调叠加(不是一个 纯音。) 我想知道的是: 我如何编写一个程序来知道声音从哪里来?从理论上讲,我需要两个麦克风,然后我会记录到麦克风的声音数据,并存储音频数据,这样一瞬间的音频数据就可以放入元组中,如[streamA,streamB] 我觉得可能有一种公式化的/数学的方法可以根据声音的来源进行计算。

我对这件事好奇了一段时间,所以我想也许在这里我可以得到一些好的答案

到目前为止我所知道的:

人类不仅可以用两只耳朵听到“听起来像”的声音 但他们来自哪里。音高是我们听到的音符 类似人声的东西有不同的音调叠加(不是一个 纯音。)

我想知道的是:

我如何编写一个程序来知道声音从哪里来?从理论上讲,我需要两个麦克风,然后我会记录到麦克风的声音数据,并存储音频数据,这样一瞬间的音频数据就可以放入元组中,如[streamA,streamB]

我觉得可能有一种公式化的/数学的方法可以根据声音的来源进行计算。我也觉得有可能获取流数据并训练学习者(为其提供音频样本并告诉其音频来自何处),并让其以这种方式对传入音频进行分类

做这件事的最佳方式是什么/是否有好的资源可以让我更多地了解这个主题

编辑:

例如:

          front
左(麦克风)x========x(麦克风)右


我想写一个程序,可以返回前/后左/右的大部分声音是听到的。据我所知,设置两个指向“前方”的话筒应该很简单。基于此,我试图找出一种方法,我们可以对声音进行三角测量,并知道与话筒相关的音源在哪里。

这是一个有趣的问题。我不知道这方面有什么参考资料,但我在音频软件和信号处理方面有一些经验,这可能会帮助你找到正确的方向

确定声源方向(声音来自你周围的地方)相当简单。准备6个定向话筒,分别指向上、下、前、后、左、右。通过观察话筒信号对声音的相对振幅,您可以很容易地确定特定声音来自哪个方向。增加麦克风数量以提高分辨率


2个麦克风只能告诉您声音是从右侧传来还是从左侧传来。你的两只耳朵之所以能分辨出声音是来自你的前方还是后方,是因为你耳朵的外部结构会根据你的大脑解释然后纠正的方向来改变声音。

互相关是一种主要方法,但它有一些细节。有多种方法可以帮助使用麦克风阵列有效地检测声源。有些在没有校准的情况下也可以工作,有些需要校准以适应房间的几何结构

您可以为源代码本地化任务尝试现有的开源软件

多年机器人声源分离与定位

HARK机器人应用工具包

如果你查阅关于多相麦克风阵列的研究论文,特别是那些用于水下测向的麦克风阵列(即,冷战期间潜艇研究的一个大领域-发动机声音来自哪里,以便我们可以瞄准鱼雷?)然后,您将找到在给定两个或多个麦克风输入的情况下查找声音位置所需的技术和数学

这不是一个简单的问题,也不是这里可以广泛讨论的问题,所以您不会找到一个简单的代码片段和/或库来完成您需要的工作

主要问题是消除回声和阴影。一个简单的方法是从单一音调开始,过滤掉除该音调以外的所有音调,然后测量该音调的两个麦克风之间的相位差。相位差会给你很多关于音调位置的信息


然后,您可以选择是要处理回声和多路径问题(其中许多问题可以通过去除除最强音调以外的所有音调来消除),还是要处理由单音以外的其他声音组成的相关声音,例如,一个人说话,或者一个玻璃破碎。从小而简单开始,然后从那里扩展。

我正在查找类似的内容,并在这里写了一个被删除的愚蠢答案。我有一些想法,但写得不好。删除给了我网络挫伤了我的自尊心,所以我决定尝试这个问题,我认为它奏效了

实际上,尝试真正定位la Adam Davis的答案是非常困难的,但做一个人类风格的定位(看第一个来源,忽略回声,或将其视为来源)并不太糟糕,我认为,尽管我无论如何都不是信号处理专家

我阅读和阅读。这让我意识到问题其实是找到两个信号之间的时间偏移(互相关)。从那里你可以用声速计算角度。注意,您将得到两种解决方案(正面和背面)

我读到的关键信息是在和同一页上的其他人讨论了如何在scipy中进行快速傅立叶变换,以找到互相关曲线

基本上,您需要将wave文件导入python。看

如果您的wave文件(输入)是一个具有两个numpy数组(左、右)的元组,则零填充的长度至少与它自身的长度相同(以阻止其循环对齐),代码遵循Gustavo的答案。我认为你需要认识到FFT假设了时间不变性,这意味着如果你想得到任何一种基于时间的信号跟踪,你需要“咬掉”小样本数据

我从上述来源收集了以下代码。它将生成一个图形,显示从左到右(负/正)的估计时间延迟(以帧为单位)。要转换为实际时间,请除以采样率。如果你想知道角度是多少,你需要:

  • 假设一切都在计划中
              back
    
                                x (sound source should return "back" or "right" or "back right")
    
    import wave
    import struct
    from numpy import array, concatenate, argmax
    from numpy import abs as nabs
    from scipy.signal import fftconvolve
    from matplotlib.pyplot import plot, show
    from math import log
    
    def crossco(wav):
        """Returns cross correlation function of the left and right audio. It
        uses a convolution of left with the right reversed which is the
        equivalent of a cross-correlation.
        """
        cor = nabs(fftconvolve(wav[0],wav[1][::-1]))
        return cor
    
    def trackTD(fname, width, chunksize=5000):
        track = []
        #opens the wave file using pythons built-in wave library
        wav = wave.open(fname, 'r')
        #get the info from the file, this is kind of ugly and non-PEPish
        (nchannels, sampwidth, framerate, nframes, comptype, compname) = wav.getparams ()
    
        #only loop while you have enough whole chunks left in the wave
        while wav.tell() < int(nframes/nchannels)-chunksize:
    
            #read the audio frames as asequence of bytes
            frames = wav.readframes(int(chunksize)*nchannels)
    
            #construct a list out of that sequence
            out = struct.unpack_from("%dh" % (chunksize * nchannels), frames)
    
            # Convert 2 channels to numpy arrays
            if nchannels == 2:
                #the left channel is the 0th and even numbered elements
                left = array (list (out[0::2]))
                #the right is all the odd elements
                right = array (list  (out[1::2]))
            else:
                left = array (out)
                right = left
    
            #zero pad each channel with zeroes as long as the source
            left = concatenate((left,[0]*chunksize))
            right = concatenate((right,[0]*chunksize))
    
            chunk = (left, right)
    
            #if the volume is very low (800 or less), assume 0 degrees
            if abs(max(left)) < 800 :
                a = 0.0
            else:
                #otherwise computing how many frames delay there are in this chunk
                cor = argmax(crossco(chunk)) - chunksize*2
                #calculate the time
                t = cor/framerate
                #get the distance assuming v = 340m/s sina=(t*v)/width
                sina = t*340/width
                a = asin(sina) * 180/(3.14159)
    
    
    
            #add the last angle delay value to a list
            track.append(a)
    
    
        #plot the list
        plot(track)
        show()