您的麥克風陣列為4x4佈局,共16個麥克風,每個麥克風在水平與垂直方向上的間隔均為42mm。這樣的配置允許在多個方向上精確地捕捉音訊信號,為後續的波束形成奠定基礎。麥克風的位置對於波束形成算法的準確性至關重要,因此必須正確設定每個麥克風的坐標。
使用Python進行音訊數據的實時採集,可以利用
pyaudio
sounddevice
import pyaudio
import numpy as np
# 音訊參數設定
CHUNK = 1024 # 每次讀取的樣本數
RATE = 44100 # 採樣率 (Hz)
CHANNELS = 16 # 麥克風通道數
# 初始化pyaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
定義麥克風的位置對於計算延遲至關重要。以下是麥克風陣列的幾何結構設定:
mic_positions = np.array([
[0, 0], [0, 0.042], [0, 0.084], [0, 0.126],
[0.042, 0], [0.042, 0.042], [0.042, 0.084], [0.042, 0.126],
[0.084, 0], [0.084, 0.042], [0.084, 0.084], [0.084, 0.126],
[0.126, 0], [0.126, 0.042], [0.126, 0.084], [0.126, 0.126]
]) # 單位:米
為了確保波束形成的準確性,所有麥克風必須經過校準。校準過程包括檢查每個麥克風的靈敏度、頻率響應和相位一致性。任何麥克風的不一致性都可能導致波束形成結果的偏差。
在進行波束形成之前,需要對音訊數據進行前處理,包括去除直流分量、應用高通或低通濾波器以消除不需要的頻率成分,以及對多通道信號進行標準化處理,以確保各通道信號的均衡。
波束形成(Beamforming)是一種信號處理技術,用於通過麥克風陣列中的多個麥克風信號,通過調整各個信號的相位與幅度,來增強特定方向的聲音信號,同時抑制其他方向的噪聲。這樣可以精確地定位聲源方向並提升信噪比。
延遲與總和是一種基本的波束形成方法。其步驟如下:
實現二維波束形成需要在水平方向(Azimuth)和垂直方向(Elevation)上對每個目標角度進行計算。以下程式碼展示了如何計算延遲並進行波束形成:
def beamforming(audio_data, mic_positions, angle_h, angle_v, speed_of_sound=343):
"""
執行二維波束形成
:param audio_data: (通道數, 樣本數) 的音訊數據
:param mic_positions: (通道數, 2) 的麥克風位置數組
:param angle_h: 水平角度 (度)
:param angle_v: 垂直角度 (度)
:param speed_of_sound: 聲速 (默認343 m/s)
:return: 波束形成後的信號
"""
delays = np.zeros(len(mic_positions))
for i, pos in enumerate(mic_positions):
# 計算每個麥克風的延遲時間
delay = (pos[0] * np.sin(np.radians(angle_h)) + pos[1] * np.sin(np.radians(angle_v))) / speed_of_sound
delays[i] = delay
# 對音訊數據進行延遲補償
delayed_data = np.zeros_like(audio_data)
for i in range(len(mic_positions)):
sample_shift = int(delays[i] * RATE)
delayed_data[i] = np.roll(audio_data[i], sample_shift)
# 合併延遲後的音訊數據
beamformed_signal = np.sum(delayed_data, axis=0)
return beamformed_signal
為了提升波束形成的效果,可以在前處理階段進行噪聲抑制,例如使用濾波器來去除背景噪聲,或者應用自適應波束形成算法來動態調整波束以應對不同的噪聲環境。下方程式碼展示了如何應用高通濾波器去除低頻噪聲:
from scipy.signal import butter, lfilter
def highpass_filter(data, cutoff=1000, fs=RATE, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
# 設計高通濾波器
b, a = butter(order, normal_cutoff, btype='high', analog=False)
y = lfilter(b, a, data)
return y
# 應用高通濾波器
filtered_data = highpass_filter(audio_data)
以下流程圖展示了二維波束形成的整體流程:
步驟 | 描述 |
---|---|
1 | 音訊數據採集 |
2 | 數據前處理(如濾波、降噪) |
3 | 計算延遲時間 |
4 | 延遲補償並叠加信號 |
5 | 生成波束形成後的信號 |
Heatmap(熱圖)是一種可視化工具,用於表示多維數據的強度或頻率。在波束形成中,Heatmap可用於展示聲源在不同方向上的強度分佈,幫助直觀理解聲源定位結果。熱圖中,每個像素點代表一個特定的方向,顏色深淺則表示該方向上的信號強度。
Matplotlib是一個強大的Python圖形庫,適合用來生成和更新Heatmap。以下程式碼展示如何初始化並實時更新Heatmap:
import matplotlib.pyplot as plt
# 初始化Heatmap
fig, ax = plt.subplots()
heatmap = ax.imshow(np.zeros((180, 180)), cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
plt.colorbar(heatmap)
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.title('波束形成熱圖')
# 實時更新Heatmap
while True:
# 讀取音訊數據
audio_data = np.frombuffer(stream.read(CHUNK), dtype=np.int16).reshape(-1, CHANNELS).T
# 初始化Heatmap數據
heatmap_data = np.zeros((180, 180))
# 計算每個角度的訊號強度
for angle_h in range(-90, 90):
for angle_v in range(-90, 90):
beamformed_signal = beamforming(audio_data, mic_positions, angle_h, angle_v)
heatmap_data[angle_v + 90, angle_h + 90] = np.sum(np.abs(beamformed_signal))
# 更新Heatmap
heatmap.set_data(heatmap_data)
plt.pause(0.1) # 更新間隔為0.1秒
ax.cla()
heatmap = ax.imshow(heatmap_data, cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
plt.colorbar(heatmap)
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.title('波束形成熱圖')
由於波束形成計算量龐大,實時生成Heatmap時可能會出現延遲。以下是一些優化建議:
multiprocessing
threading
為了讓Heatmap更加清晰易讀,可以進行以下美化處理:
以下是一個結合所有部分的完整Python程式碼示例,展示如何從麥克風陣列的信號採集到實時生成Heatmap:
import numpy as np
import pyaudio
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter
import threading
# 音訊參數設定
CHUNK = 1024
RATE = 44100
CHANNELS = 16
# 麥克風陣列位置設定(單位:米)
mic_positions = np.array([
[0, 0], [0, 0.042], [0, 0.084], [0, 0.126],
[0.042, 0], [0.042, 0.042], [0.042, 0.084], [0.042, 0.126],
[0.084, 0], [0.084, 0.042], [0.084, 0.084], [0.084, 0.126],
[0.126, 0], [0.126, 0.042], [0.126, 0.084], [0.126, 0.126]
])
# 初始化pyaudio
p = pyaudio.PyAudio()
stream = p.open(format=pyaudio.paInt16,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
# 高通濾波器
def highpass_filter(data, cutoff=1000, fs=RATE, order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b, a = butter(order, normal_cutoff, btype='high', analog=False)
y = lfilter(b, a, data)
return y
# 波束形成函數
def beamforming(audio_data, mic_positions, angle_h, angle_v, speed_of_sound=343):
delays = np.zeros(len(mic_positions))
for i, pos in enumerate(mic_positions):
delays[i] = (pos[0] * np.sin(np.radians(angle_h)) + pos[1] * np.sin(np.radians(angle_v))) / speed_of_sound
delayed_data = np.zeros_like(audio_data)
for i in range(len(mic_positions)):
sample_shift = int(delays[i] * RATE)
delayed_data[i] = np.roll(audio_data[i], sample_shift)
beamformed_signal = np.sum(delayed_data, axis=0)
return beamformed_signal
# Heatmap更新函數
def update_heatmap():
while not stop_event.is_set():
# 讀取音訊數據
audio_data = np.frombuffer(stream.read(CHUNK), dtype=np.int16).reshape(-1, CHANNELS).T
# 應用高通濾波器
audio_data = highpass_filter(audio_data)
# 初始化Heatmap數據
heatmap_data = np.zeros((180, 180))
# 計算每個角度的訊號強度
for angle_h in range(-90, 90):
for angle_v in range(-90, 90):
beamformed_signal = beamforming(audio_data, mic_positions, angle_h, angle_v)
heatmap_data[angle_v + 90, angle_h + 90] = np.sum(np.abs(beamformed_signal))
# 更新Heatmap
ax.clear()
im = ax.imshow(heatmap_data, cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
plt.colorbar(im, ax=ax)
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.title('波束形成熱圖')
plt.pause(0.001) # 短暫暫停以更新圖形
# 初始化Heatmap
fig, ax = plt.subplots()
heatmap = ax.imshow(np.zeros((180, 180)), cmap='hot', origin='lower', extent=[-90, 90, -90, 90])
plt.colorbar(heatmap, ax=ax)
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.title('波束形成熱圖')
# 啟動Heatmap更新執行緒
stop_event = threading.Event()
heatmap_thread = threading.Thread(target=update_heatmap)
heatmap_thread.start()
try:
plt.show(block=True)
except KeyboardInterrupt:
pass
finally:
stop_event.set()
heatmap_thread.join()
stream.stop_stream()
stream.close()
p.terminate()
pyaudio
在執行此程式前,請確保所有麥克風均已正確連接並能夠穩定運行。運行程式後,應能實時看到波束形成的Heatmap呈現聲源方向及強度分佈。在測試過程中,您可以移動聲源的位置,觀察Heatmap的變化,以驗證系統的準確性。
為了提升實時運行的效率,建議對程式碼進行以下優化:
multiprocessing
threading
為了提升實時運行的效率,可以考慮以下方法:
可以進一步提升波束形成的準確性和對噪聲的抑制能力:
除了Heatmap外,還可以考慮以下擴展功能:
本文詳細介紹了如何使用Python實現4x4麥克風陣列的二維波束形成,並將結果以實時Heatmap呈現。通過步驟化的指導與範例程式碼,您可以有效地設置麥克風陣列、進行信號處理及可視化,進而實現精確的聲源定位。進一步的優化與擴展將使系統在更複雜的環境中表現更佳,滿足不同應用需求。