我一直对此感到好奇,所以我想也许可以在这里发帖,我可以得到一些好的答案。
到目前为止我所知道的:
人类可以用他们的双耳不仅能听到“听起来像”的声音 而且他们来自哪里。音高是我们听到的音符,而且 像人声这样的东西覆盖了各种音高(不是 纯音。)
我想知道的事情:
如何编写可以知道声音来自何处的程序?从理论的角度来看,我需要两个麦克风,然后我会记录进入麦克风的声音数据并存储音频数据,这样一秒钟的音频数据就可以放入像[streamA,streamB]这样的元组中。
我觉得可能有一种公式/数学方法可以根据声音的来源进行计算。我也觉得可以获取流数据并训练学习者(给它采样音频并告诉音频来自哪里)并让它以这种方式对输入音频进行分类。
这样做的最佳方式是什么?是否有良好的资源,我可以从中了解更多关于这个主题的信息?
编辑:
示例:
front
左(麦克风)x ======== x(麦克风)右
back x (sound source should return "back" or "right" or "back right")
我想编写一个程序,可以在听到的大部分声音中返回前/后左/右。根据我的理解,设置两个指向“前进”的麦克风应该很简单。基于此,我试图找出一种方法,我们可以对声音进行三角测量,并了解与麦克风相关的来源。
答案 0 :(得分:5)
如果你研究一下多相麦克风阵列的研究论文,特别是那些用于水下测向的研究论文(即冷战期间潜艇研究的大部分领域 - 电机声音来自何处,我们可以瞄准鱼雷? )然后你会发现在给定两个或更多麦克风输入的情况下找到声音位置所需的技术和数学。
这不是一件轻而易举的事情,也不是可以在这里广泛讨论的东西,所以你不会找到一个简单的代码片段和/或库来做你需要的。
主要问题是消除回声和阴影。一种简单的方法是从单音开始,滤除除该音之外的所有音调,然后测量该音调的两个麦克风之间的相位差。相位差将为您提供有关音调位置的大量信息。
然后,您可以选择是否要处理回声和多路径问题(其中许多问题可以通过删除除最强音之外的所有语音来消除)或者转移到由单个音调以外的其他内容组成的相关声音 - 一个人说话或者例如玻璃破碎。从小开始,从那里开始扩展。
答案 1 :(得分:3)
我正在寻找类似的东西,并在这里写了一个被删除的愚蠢答案。我有一些想法,但没有真正写出来。删除给了我互联网伤害自我的自豪,所以我决定尝试问题,我认为它的工作!
实际上,尝试做一个真正的定位,亚当戴维斯的回答是非常困难的,但是做一个人性化的位置(看第一个来源,忽略回声,或者将它们视为来源)并不是太糟糕,我想,我无论如何都不是信号处理专家。
我看了this和this。这让我意识到问题实际上是找到两个信号之间的时移(互相关)。从那里你可以用声速计算角度。请注意,您将获得两个解决方案(正面和背面)。
我读到的关键信息在this answer和同一页面上的其他信息,讨论如何在scipy中进行快速傅里叶变换,以找到互相关曲线。
基本上,您需要将wave文件导入python。见this。
如果你的wave文件(输入)是一个带有两个numpy数组(左,右)的元组,那么零填充至少和它本身一样长(为了使它明显地循环对齐),代码遵循Gustavo的答案。我认为你需要认识到fft假设时间不变性,这意味着如果你想获得任何类型的基于时间的信号跟踪,你需要“咬掉”小数据样本。
我从提到的来源中汇总了以下代码。它将生成一个图表,显示从左到右(负/正)的估计时间延迟(以帧为单位)。要转换为实际时间,请除以采样率。如果你想知道你需要的角度:
您还需要使用两个麦克风之间的距离,以确保您没有得到回声(时间延迟大于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找到的一些立体声音频尝试了这一点。我用过车的例子(立体声文件)。它产生了this。
要在运行中这样做,我想你需要有一个你可以'听'短时间的传入立体声源(我使用1000帧= 0.0208s),然后计算并重复。
[编辑:发现你可以轻松使用fft卷积函数,使用两者之一的倒置时间序列进行相关]
答案 2 :(得分:2)
这是一个有趣的问题。我不知道有任何参考资料,但我在音频软件和信号处理方面有一些经验,可以帮助您指明正确的方向。
确定声源方向(声音来自周围你的位置)非常简单。获得6个定向麦克风,并将它们向上,向下,向前,向后,向左和向右指向。通过查看响应声音的麦克风信号的相对振幅,您可以非常轻松地确定特定声音来自哪个方向。增加麦克风数量以提高分辨率。
2个麦克风只会告诉您声音来自右侧还是左侧。你的耳朵可以判断声音是来自你前面还是后面的原因是因为你的耳朵的外部结构会根据你的大脑解释然后纠正的方向修改声音。
答案 3 :(得分:2)
互相关是一种主要方法,但它有一些细节。有各种方法有助于有效地检测麦克风阵列的源。有些还可以在没有校准的情况下工作,有些需要校准以适应房间的几何形状。
您可以尝试使用现有的开源软件进行源本地化任务
Manyears机器人声源分离和定位 https://sourceforge.net/projects/manyears/
用于机器人应用的HARK工具包 http://www.ros.org/wiki/hark