建立一個4x4的麥克風陣列,總計16個麥克風。每個麥克風在水平與垂直方向上相隔42毫米,這樣的配置有助於提升聲源定位的精度。麥克風的座標可以使用NumPy陣列進行儲存和管理,確保後續的信號處理準確無誤。
使用以下Python程式碼範例來設定麥克風的座標:
import numpy as np
# 麥克風間距 (42mm)
mic_spacing = 0.042 # 單位:米
num_mics_per_side = 4 # 每邊4個麥克風
# 建立4x4麥克風座標矩陣
mic_positions = np.array([[(i * mic_spacing, j * mic_spacing, 0)
for j in range(num_mics_per_side)]
for i in range(num_mics_per_side)])
mic_positions = mic_positions.reshape(-1, 3) # 重塑為(16, 3)矩陣
在開始編寫程式之前,確保已安裝以下Python庫:
pip install numpy scipy matplotlib seaborn sounddevice
這些庫分別用於數值運算、信號處理、資料視覺化以及即時音訊擷取。
使用sounddevice庫來即時擷取16通道音訊。設定取樣率為48kHz,並設置時間窗格為0.1秒,以便實現實時處理。
import sounddevice as sd
# 音訊參數設定
sample_rate = 48000 # 取樣率:48kHz
frame_size = int(0.1 * sample_rate) # 時間窗格:0.1秒
num_channels = 16 # 麥克風通道數
以下函數用於即時擷取音訊資料:
def audio_callback(indata, frames, time, status):
if status:
print(status)
# 傳遞數據至隊列或處理函數
process_audio(indata.copy())
啟動音訊流:
import queue
audio_queue = queue.Queue()
def process_audio(data):
audio_queue.put(data)
stream = sd.InputStream(samplerate=sample_rate, channels=num_channels, callback=audio_callback)
stream.start()
延遲與加總是最基本的Beamforming技術。透過計算每個麥克風接收到聲波的相位差,對信號進行延遲補償後加總,從而增強特定方向的聲源信號。
根據聲源方向(θ,φ),計算每個麥克風的理論延遲時間:
公式如下:
$$ \tau_{i,j} = \frac{d_{i,j} \cdot \cos(\theta) + d_{k,l} \cdot \sin(\phi)}{c} $$其中,
d_{i,j} 是第(i,j)個麥克風與參考點的距離。θ 和 φ 分別是水平和垂直角度。c 是聲速(約343 m/s)。對所有麥克風信號進行延遲補償,並加總以形成Beamforming輸出:
def delay_and_sum(audio_data, mic_positions, angles, sample_rate=48000, speed_of_sound=343):
num_angles = len(angles)
beamformed_output = np.zeros(num_angles)
for i, angle in enumerate(angles):
theta_rad = np.deg2rad(angle[0])
phi_rad = np.deg2rad(angle[1])
delays = (mic_positions[:,0] * np.cos(theta_rad) + mic_positions[:,1] * np.sin(phi_rad)) / speed_of_sound
delay_samples = (delays * sample_rate).astype(int)
delayed_signals = np.array([np.roll(audio_data[j], int(delay_samples[j])) for j in range(len(mic_positions))])
beamformed_output[i] = np.sum(np.abs(np.sum(delayed_signals, axis=0)))
return beamformed_output
為了在水平與垂直方向上各自掃描180度,將聲場劃分為一個網格,每個網格點代表一個可能的聲源方向。
def generate_grid(resolution=5, max_angle=90, distance=1):
angles_theta = np.arange(-max_angle, max_angle + resolution, resolution)
angles_phi = np.arange(-max_angle, max_angle + resolution, resolution)
grid_points = []
for theta in angles_theta:
for phi in angles_phi:
grid_points.append((theta, phi))
return grid_points
結合延遲與加總方法,對每個網格點進行Beamforming計算,並將結果儲存以供後續熱力圖生成。
grid_angles = generate_grid(resolution=5) # 5度解析度
def compute_beamforming(audio_data, mic_positions, grid_angles):
beam_results = delay_and_sum(audio_data, mic_positions, grid_angles)
heatmap = beam_results.reshape((len(np.arange(-90, 95, 5)), len(np.arange(-90, 95, 5))))
return heatmap
利用Matplotlib和Seaborn庫來生成和更新熱力圖,實時顯示聲源方向的強度。
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.animation import FuncAnimation
def update_heatmap(frame):
if not audio_queue.empty():
audio_data = audio_queue.get()
heatmap_data = compute_beamforming(audio_data, mic_positions, grid_angles)
sns.heatmap(heatmap_data, cmap='hot', cbar=True, ax=ax, vmin=0, vmax=np.max(heatmap_data))
plt.title('實時聲場熱力圖')
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
plt.pause(0.1)
fig, ax = plt.subplots()
anim = FuncAnimation(fig, update_heatmap, interval=100)
plt.show()
為確保實時顯示的流暢性,需優化Python程式的運算效率。可以採用以下方法:
以下是一個完整的Python實作範例,將上述各部分整合起來,實現基於4x4麥克風陣列的二維Beamforming與實時熱力圖顯示:
import numpy as np
import sounddevice as sd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.animation import FuncAnimation
import queue
# 麥克風陣列配置
mic_spacing = 0.042 # 42mm
num_mics_per_side = 4
mic_positions = np.array([[(i * mic_spacing, j * mic_spacing, 0)
for j in range(num_mics_per_side)]
for i in range(num_mics_per_side)])
mic_positions = mic_positions.reshape(-1, 3)
# 音訊參數設定
sample_rate = 48000 # 48kHz
frame_size = int(0.1 * sample_rate) # 0.1秒
num_channels = 16
# 音訊擷取設定
audio_queue = queue.Queue()
def audio_callback(indata, frames, time, status):
if status:
print(status)
audio_queue.put(indata.copy())
stream = sd.InputStream(samplerate=sample_rate, channels=num_channels, callback=audio_callback)
stream.start()
# Beamforming函數
def delay_and_sum(audio_data, mic_positions, angles, sample_rate=48000, speed_of_sound=343):
num_angles = len(angles)
beamformed_output = np.zeros(num_angles)
for i, angle in enumerate(angles):
theta_rad = np.deg2rad(angle[0])
phi_rad = np.deg2rad(angle[1])
delays = (mic_positions[:,0] * np.cos(theta_rad) + mic_positions[:,1] * np.sin(phi_rad)) / speed_of_sound
delay_samples = (delays * sample_rate).astype(int)
delayed_signals = np.array([np.roll(audio_data[j], int(delay_samples[j])) for j in range(len(mic_positions))])
beamformed_output[i] = np.sum(np.abs(np.sum(delayed_signals, axis=0)))
return beamformed_output
# 聲場網格生成
def generate_grid(resolution=5, max_angle=90, distance=1):
angles_theta = np.arange(-max_angle, max_angle + resolution, resolution)
angles_phi = np.arange(-max_angle, max_angle + resolution, resolution)
grid_points = []
for theta in angles_theta:
for phi in angles_phi:
grid_points.append((theta, phi))
return grid_points
grid_angles = generate_grid(resolution=5) # 5度解析度
# 計算Beamforming結果
def compute_beamforming(audio_data, mic_positions, grid_angles):
beam_results = delay_and_sum(audio_data, mic_positions, grid_angles)
heatmap = beam_results.reshape((len(np.arange(-90, 95, 5)), len(np.arange(-90, 95, 5))))
return heatmap
# 初始化熱力圖顯示
fig, ax = plt.subplots(figsize=(10, 8))
heatmap = sns.heatmap(np.zeros((len(np.arange(-90, 95, 5)), len(np.arange(-90, 95, 5)))),
cmap='hot', cbar=True, ax=ax, vmin=0, vmax=1)
plt.title('實時聲場熱力圖')
plt.xlabel('水平角度 (度)')
plt.ylabel('垂直角度 (度)')
# 更新熱力圖函數
def update_heatmap(frame):
if not audio_queue.empty():
audio_data = audio_queue.get()
audio_data = audio_data.flatten()
if len(audio_data) < num_channels:
return
audio_data = audio_data[:num_channels]
heatmap_data = compute_beamforming(audio_data, mic_positions, grid_angles)
ax.cla()
sns.heatmap(heatmap_data, cmap='hot', cbar=True, ax=ax, vmin=0, vmax=np.max(heatmap_data) if np.max(heatmap_data) > 0 else 1)
ax.set_title('實時聲場熱力圖')
ax.set_xlabel('水平角度 (度)')
ax.set_ylabel('垂直角度 (度)')
plt.tight_layout()
# 啟動動畫
anim = FuncAnimation(fig, update_heatmap, interval=100)
plt.show()
# 關閉音訊流
stream.stop()
stream.close()
本指南詳細介紹了如何利用Python實現基於4x4麥克風陣列的二維Beamforming演算法,並將處理後的音訊資料以實時熱力圖形式呈現。從麥克風陣列的配置、音訊擷取與處理、Beamforming演算法的實作,再到實時視覺化展示,每個步驟均提供了具體的程式碼範例與實作建議。通過優化演算法性能與合理配置硬體資源,可以達到高效且準確的聲源定位效果。