6

我对此感到好奇已经有一段时间了,所以我想也许在这里发帖我可以得到一些好的答案。

到目前为止我所知道的:

人类不仅可以用两只耳朵听到“听起来像”的声音,还可以知道它们来自哪里。音高是我们听到的音符,像人声这样的东西有不同的音高叠加(不是纯音。)

我想知道的:

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

我觉得可能有一种公式/数学方法可以根据声音来自的音频进行计算。我也觉得可以获取流数据并训练学习者(给它样本音频并告诉它音频来自哪里)并让它以这种方式对传入的音频进行分类。

执行此操作的最佳方法是什么/是否有好的资源可以让我了解有关该主题的更多信息?

编辑:

例子:

          front

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

          back

                            x (sound source should return "back" or "right" or "back right")

我想编写一个程序,可以为它听到的大部分声音返回前/后左/右。据我了解,设置两个指向“向前”的麦克风应该很简单。基于此,我试图找出一种方法,我们可以对声音进行三角测量,并了解音源相对于麦克风的位置。

4

4 回答 4

5

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

不过,这很重要,也不能在这里广泛讨论,因此您不会找到一个简单的代码片段和/或库来做您需要的事情。

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

然后,您可以选择是否要处理回声和多路径问题(其中许多问题可以通过移除除最强音之外的所有声音来消除),还是转向包含非单音的相关声音 - 一个人说话,或一个例如,玻璃破碎。从小而轻松开始,然后从那里扩展。

于 2011-12-29T17:37:25.507 回答
3

我正在查找类似的内容,并在这里写了一个愚蠢的答案,但被删除了。我有一些想法,但并没有真正正确地写出来。删除给了我互联网挫伤的自我自豪感,所以我决定尝试这个问题,我认为它有效!

实际上,尝试按照亚当戴维斯的答案进行真正的定位是非常困难的,但是进行人性化的定位(查看第一个来源,忽略回声或将它们视为来源)并不算太糟糕,我认为,虽然我无论如何都不是信号处理专家。

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

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

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

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

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

  • 假设一切都在一个平面上(没有高度因素)
  • 忘记前面声音和后面声音的区别(你无法区分)

您还需要使用两个麦克风之间的距离来确保您没有收到回声(时间延迟大于 90 度延迟的时间延迟)。

我意识到我在这里借了很多东西,所以感谢所有不经意间做出贡献的人!

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()

我使用在equilogy找到的一些立体声音频对此进行了尝试。我使用了汽车示例(立体声文件)。它产生了这个

要即时执行此操作,我想您需要有一个传入的立体声源,您可以在短时间内“收听”(我使用 1000 帧 = 0.0208 秒),然后计算并重复。

[编辑:发现您可以轻松使用 fft convolve 函数,使用两者之一的倒置时间序列进行相关]

于 2013-11-20T06:36:21.890 回答
2

这是一个有趣的问题。我不知道这方面的任何参考资料,但我在音频软件和信号处理方面确实有一些经验,这可能有助于为您指明正确的方向。

确定声源方向(声音来自您周围的位置)相当简单。获取 6 个指向性麦克风并将它们指向上、下、前、后、左和右。通过查看麦克风信号响应声音的相对幅度,您可以很容易地确定特定声音来自哪个方向。增加麦克风数量以提高分辨率。

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

于 2011-12-29T01:47:30.810 回答
2

互相关是一种主要方法,但它有一些细节。有多种方法可以帮助有效地检测带有麦克风阵列的源。有些也无需校准即可工作,有些则需要校准以适应房间的几何形状。

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

万年机器人声源分离与定位 https://sourceforge.net/projects/manyears/

用于机器人应用程序的 HARK 工具包 http://www.ros.org/wiki/hark

于 2011-12-29T17:31:04.443 回答