1. 聲波傳播和求和
下圖,一個簡化的麥克風陣列波束形成設置。 從揚聲器傳播來的聲波,將在不同的時刻到達麥克風,此屬性是陣列空間濾波功能的本質。 模擬陣列的空間濾波性能時,有必要計算麥克風信號如何針對不同的信號源位置或角度求和。
根據揚聲器和麥克風的位置,可以首先計算波束傳播的距離,然後對於給定的聲速,波束離開揚聲器併到達每個麥克風所花費的時間。
上圖顯示了一個100Hz的“源波”,代表信號離開揚聲器。 該圖還顯示了“麥克風1處的信號”和“麥克風2處的信號”。 可以清楚地看到源信號傳播到麥克風所引起的延遲。 最後顯示了陣列的“輸出”(兩個麥克風信號的總和)。 由於傳播時間的差異,輸出的幅度爲1.825,而不是幅度爲源波的兩倍(有兩個麥克風)。
注意:未考慮信號從揚聲器傳播到麥克風時的衰減。
2.用相量計算組合麥克風信號幅度
相量(Phasors )是一種簡單的計算組合的麥克風信號(陣列的輸出)幅度方法。 下圖顯示瞭如何計算兩個信號之間的相位差。 波的一個週期對應於360°,給定的週期爲10ms,2.305ms的延遲對應於82.975°的相移。
兩種麥克風信號的相位計算如下所示:
相量圖提供了一種表示正弦波的幅度和相位方法,還提供相加波形的圖形方法。 三個相量圖表示兩個麥克風信號和陣列的輸出。 相量長度對應于波的幅度,角度對應於相位,被繪製爲復軸上的向量。 通過將向量相加,可以很容易地實現相量求和,所得向量代表相加波。
對向量求和的最簡單方法是將其從極座標(振幅和相位)轉換爲笛卡爾座標(實數和虛數)。 然後,可以根據兩個麥克風矢量的總和輕鬆計算出輸出矢量。
最後,計算波幅總和,使用畢達哥拉斯定理計算總和向量的長度,如下所示
3.簡化形式
綜合上述階段,可以得出以下公式:
根據波的頻率,行間距離和聲速來計算波的複數表示。 要輸出一組波,只需計算併疊加每個波的實部和虛部,然後使用畢達哥拉斯定理計算最終振幅。
以下c代碼執行上述兩個麥克風設置的波加和計算:
File: waves.c
#include <stdio.h>
#include <math.h>
int main(void)
{
double phase, distance, delay;
double freq = 100.0; // Hz
double speedSound = 343.0; // m/s
// Microphone 1
distance = sqrt(0.25*0.25 + 0.75*0.75);
delay = distance / speedSound;
double re1 = cos(2.0 * M_PI * freq * delay);
double im1 = sin(2.0 * M_PI * freq * delay);
phase = 180 * atan2(im1, re1) / M_PI;
printf("Mic1 - Distance:%.4f, Delay:%.4f, Phase:%.3f, [%.3f %.3f]\n", distance, delay*1000, phase, re1, im1);
// Microphone 2
distance = sqrt(1.00*1.00 + 0.75*0.75);
delay = distance / speedSound;
double re2 = cos(2.0 * M_PI * freq * delay);
double im2 = sin(2.0 * M_PI * freq * delay);
phase = 180 * atan2(im2, re2) / M_PI;
printf("Mic2 - Distance:%.4f, Delay:%.4f, Phase:%.3f, [%.3f %.3f]\n", distance, delay*1000, phase, re2, im2);
// Output
double re = re1 + re2;
double im = im1 + im2;
double amp = sqrt(re*re + im*im);
phase = 180 * atan2(im, re) / M_PI;
printf("Output - Amplitude:%.3f, Phase:%.3f, [%.3f %.3f]\n", amp, phase, re, im);
return 0;
}
可以使用以下命令來編譯和執行代碼:
gcc -Wall -lm -o waves waves.c
./waves
輸出顯示麥克風的極性和笛卡爾形式以及輸出信號。
Mic1 - Distance:0.7906, Delay:2.3049, Phase:82.975, [0.122 0.992]
Mic2 - Distance:1.2500, Delay:3.6443, Phase:131.195, [-0.659 0.752]
Output - Amplitude:1.826, Phase:107.085, [-0.536 1.745]
4. 歐拉公式表示
可以使用歐拉公式表示波的複數。 下面的等式顯示了歐拉公式,以及如何調整它來表示頻率爲f的波動。
對於延遲爲d的波,方程式:
5. 線性陣列示例
以線性陣列爲例, 每個陣列麥克風之間的距離爲1米, 對於從角度θ以聲速c到達的頻率爲f的平面波,使用以下公式計算陣列的輸出。
下面代碼用相量和指數方法計算線性陣列的輸出幅度。
相量方法:
File: array1.c
#include <stdio.h>
#include <math.h>
int main(void)
{
int numElements = 4; // Number of array elements
double spacing = 0.75; // Element separation in metre
double angle = 30.0; // Degrees from broadside
double freq = 100.0; // Signal frequency in Hz
double speedSound = 343.0; // m/s
int i;
double realSum = 0;
double imagSum = 0;
// Iterate through array elements
for (i=0 ; i<numElements ; i++)
{
// Calculate element position and wavefront delay
double position = i * spacing;
double delay = position * sin(M_PI * angle / 180) / speedSound;
printf("%3d) Position: %f, Delay: %e\n", i, position, delay);
// Add Wave
realSum += cos(2.0 * M_PI * freq * delay);
imagSum += sin(2.0 * M_PI * freq * delay);
}
double output = sqrt(realSum * realSum + imagSum * imagSum);
printf("Output Amplitude: %.3f [%f, %f]\n", output, realSum, imagSum);
return 0;
}
指數方法
File: array2.c
#include <stdio.h>
#include <math.h>
#include <gsl/gsl_complex.h>
#include <gsl/gsl_complex_math.h>
int main(void)
{
int numElements = 4; // Number of array elements
double spacing = 0.75; // Element separation in metre
double angle = 30.0; // Degrees from broadside
double freq = 100.0; // Signal frequency in Hz
double speedSound = 343.0; // m/s
int i;
gsl_complex total;
GSL_SET_COMPLEX(&total, 0 ,0);
gsl_complex comp;
// Iterate through array elements
for (i=0 ; i<numElements ; i++)
{
// Calculate element position and wavefront delay
double position = i * spacing;
double delay = position * sin(M_PI * angle / 180) / speedSound;
printf("%3d) Position: %f, Delay: %e\n", i, position, delay);
// Calculate exponential form
comp.dat[0] = 0; // Real
comp.dat[1] = 2.0 * M_PI * freq * delay; // Imaginary
gsl_complex w = gsl_complex_exp(comp); // Exponential
// Add Wave
total = gsl_complex_add(total, w); // Accumulate
}
double output = gsl_complex_abs(total);
printf("Output Amplitude: %.3f [%f, %f]\n", output, total.dat[0], total.dat[1]);
return 0;
}
可以使用以下命令來編譯和執行代碼
> gcc -Wall -lm -o array1 array1.c
> ./array1
> gcc -Wall -lm -lgsl -o array2 array2.c
> ./array2
這兩個程序的輸出是相同的,因爲它們都計算相同的內容,儘管方式略有不同。 輸出以米爲單位顯示每個陣列元素的物理位置,以及相對於第一個麥克風的波前延遲。 求和信號的幅度也以其複雜的形式顯示。
0) Position: 0.000000, Delay: 0.000000e+00
1) Position: 0.750000, Delay: 1.093294e-03
2) Position: 1.500000, Delay: 2.186589e-03
3) Position: 2.250000, Delay: 3.279883e-03
Output Amplitude: 2.912 [1.498204, 2.497171]