Ho trovato quasi per caso su Internet che il Kinect 1 ha un array di 4 microfoni che permettono di determinare la direzione del suono (ed essendo tutto integrato non ha problemi di jitter)
Bus 001 Device 016: ID 045e:02b0 Microsoft Corp. Xbox NUI Motor
Bus 001 Device 018: ID 045e:02bb Microsoft Corp. Kinect Audio
Bus 001 Device 019: ID 045e:02ae Microsoft Corp. Xbox NUI Camera
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
L'array di 4 microfoni e' indicato da 0 (lato destro) a 3 (lato sinistro) con una distanza tra 0 e 3 di 22.6 cm. I microfoni 0,1,2 sono molto ravvicinati tra di loro, solo il 3 e' distanziato alla sinistra
Una delle limitazione di kinect e' che il campionamento massimo e' di 16k il che limita la precisione a 2.14 cm ed 24 bit (anche se sono trasmessi come 32 bit)
arecord -l
card 1: Audio [Kinect USB Audio], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
arecord -D hw:1,0 -c 4 -r 16000 -f S32_LE -t raw kinect_array.raw
ffmpeg -f s32le -ar 16000 -ac 4 -i kinect_array.raw kinect_output.wav
import numpy as np
import subprocess
import math
from scipy.signal import correlate
# --- CONFIGURAZIONE ---
CHANNELS = 4
RATE = 16000
CHUNK_SIZE = 1024 * 4 # Dimensione del blocco da analizzare (circa 0.25 secondi)
v = 343 # Velocità del suono m/s
d = 0.226 # Distanza Mic 0 - Mic 3 (metri)
# Comando per avviare arecord e inviare i dati RAW alla stdout
cmd = [
'arecord', '-D', 'hw:1,0', '-c', str(CHANNELS), '-r', str(RATE),
'-f', 'S32_LE', '-t', 'raw', '-q'
]
# Avvio del processo
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
print("Ascolto in corso... Muoviti davanti al Kinect o schiocca le dita!")
print("Premi Ctrl+C per fermare.\n")
try:
while True:
# Leggi un blocco di dati (4 canali * 4 byte per campione * CHUNK_SIZE)
raw_bytes = proc.stdout.read(CHUNK_SIZE * CHANNELS * 4)
if not raw_bytes:
break
# Converti byte in array numpy
data = np.frombuffer(raw_bytes, dtype=np.int32).reshape(-1, CHANNELS)
# Prendi Mic 0 e Mic 3
mic_0 = data[:, 0].astype(np.float32)
mic_3 = data[:, 3].astype(np.float32)
# Calcola correlazione
corr = correlate(mic_0, mic_3, mode='full')
lag = np.argmax(corr) - (len(mic_0) - 1)
# Calcolo tempo e angolo
dt = lag / RATE
# Limita l'argomento di arcsin tra -1 e 1 per evitare errori
sin_argument = (v * dt) / d
if abs(sin_argument) <= 1.0:
angle_rad = math.asin(sin_argument)
angle_deg = math.degrees(angle_rad)
# Visualizzazione a barre dinamica
bar_position = int(angle_deg / 10) + 9
display = ["-"] * 19
display[bar_position] = "O"
print(f"[{''.join(display)}] Angolo: {angle_deg:6.1f}°", end="\r")
except KeyboardInterrupt:
print("\nFermato dall'utente.")
finally:
proc.terminate()
Nessun commento:
Posta un commento