Я искал что-то похожее и написал здесь тупой ответ, который был удален. У меня были некоторые идеи, но я не написал их должным образом. Удаление дало мне эту интернет-гордость, поэтому я решил попробовать проблему, и я думаю, что это сработало!
На самом деле, попытка найти настоящую локализацию а-ля Адама Дэвиса очень сложна, но сделать локализацию в человеческом стиле (глядя на первый источник, игнорируя эхо или трактуя их как источники), я думаю, не так уж и плохо Я ни в коем случае не эксперт по обработке сигналов.
Я прочитал это и это . Это заставило меня понять, что проблема на самом деле заключается в нахождении временного сдвига (взаимной корреляции) между двумя сигналами. Оттуда вы будете рассчитывать угол, используя скорость звука. Обратите внимание, что вы получите два решения (спереди и сзади).
Ключевая информация, которую я прочитал, была в этом ответе и других на той же странице, которые рассказывают о том, как делать быстрые преобразования Фурье в scipy, чтобы найти кривую взаимной корреляции.
По сути, вам нужно импортировать волновой файл в python. Смотрите это .
Если ваш волновой файл (входной) является кортежем с двумя массивами (слева, справа), заполненными нулями, по крайней мере, до тех пор, пока он сам (очевидно, для остановки кругового выравнивания), код следует из ответа Густаво. Я думаю, вам нужно признать, что эти 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 . Я использовал автомобильный пример (стереофайл). Это произвело это .
Чтобы сделать это на лету, я думаю, вам понадобится входящий стереофонический источник, который вы могли бы «слушать» в течение короткого времени (я использовал 1000 кадров = 0,0208 с), а затем вычислить и повторить.
[править: найдено, что вы можете легко использовать функцию FFT Convolve, используя инвертированные временные ряды одного из двух для создания корреляции]