Stavo cercando qualcosa di simile e ho scritto una risposta stupida qui che è stata cancellata. Ho avuto alcune idee ma non le ho scritte veramente bene. La cancellazione mi ha dato quell'orgoglio orgoglioso di Internet ferito, quindi ho deciso di provare il problema e penso che abbia funzionato!
In realtà, provare a fare una vera localizzazione a la risposta di Adam Davis è molto difficile, ma fare una location in stile umano (guardare la prima fonte, ignorare gli echi o trattarli come fonti) non è male, penso, anche se non sono un esperto di elaborazione del segnale con qualsiasi mezzo.
Ho letto this e this. Il che mi ha fatto capire che il problema è in realtà quello di trovare il time shift (cross-correlazione) tra due segnali. Da lì si calcola l'angolo usando la velocità del suono. Nota che avrai due soluzioni (anteriore e posteriore).
Le informazioni chiave che ho letto erano in this answer e altre sulla stessa pagina che parla di come eseguire trasformazioni di Fourier veloci in scipy, per trovare la curva di correlazione incrociata.
Fondamentalmente, è necessario importare il file wave in python. Vedi this.
Se il proprio file wave (input) è una tupla con due array numpy (a sinistra, a destra), riempito a zero almeno quanto se stesso (per fermarlo allineato in modo apparente) il codice segue la risposta di Gustavo. Penso che sia necessario riconoscere che i ffts fanno l'ipotesi dell'invarianza del tempo, il che significa che se si desidera ottenere un qualsiasi tipo di tracciamento dei segnali basato sul tempo, è necessario "mordere" piccoli campioni di dati.
Ho portato insieme il seguente codice dalle fonti menzionate.Produrrà un grafico che mostra il ritardo temporale stimato, in frame, da sinistra a destra (negativo/positivo). Per convertire in tempo reale, dividere per la frequenza di campionamento. Se volete sapere che cosa l'angolo è che dovete:
- assumere tutto ciò che si trova su un piano (senza fattore di altezza)
- dimenticare la differenza tra suono davanti e quelli dietro (non si può differenziare)
Si consiglia inoltre di utilizzare la distanza tra i due microfoni per assicurarsi che non si ottengano echi (ritardi superiori a quello per il ritardo di 90 gradi).
Mi rendo conto che ho preso molto in prestito qui, quindi grazie a tutti quelli che hanno contribuito inavvertitamente!
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()
ho provato questo utilizzando alcuni audio stereo ho trovato su equilogy. Ho usato l'esempio di auto (file stereo). Ha prodotto this.
Per fare questo on-the-fly, credo che avresti bisogno di avere una fonte stereo in ingresso che si potrebbe 'ascoltare' per un breve periodo (io ho usato 1000 fotogrammi = 0.0208s) e quindi calcolare e ripetere .
[edit: trovato si può facilmente utilizzare la funzione FFT convolve, utilizzando le serie storiche invertita di uno dei due per fare una correlazione]
Sto indovinando si vuole fare una discreta [correlazione incrociata] (http://en.wikipedia.org/wiki/Cross-correlation) tra i due canali. –
@HotLicks: Questo non ti dice molto. Conoscere il ritardo relativo tra microfono sinistro e destro limita solo la posizione fino alla superficie di un ellissoide. –
BBN fa milioni di dollari vendendo un sistema che fa questo. Non stanno dicendo come, o se lo hanno brevettato. – bmargulies