199 lines
12 KiB
Markdown
199 lines
12 KiB
Markdown
# 마이크 어레이 수신 빔 패턴
|
||
|
||
Array Builder의 **수신 빔 패턴**은 현재 마이크 좌표에 conventional delay-and-sum을 적용했을 때의
|
||
narrowband far-field array factor를 보여줍니다. XZ·YZ·XY의 세 360° polar 단면을 동시에 비교하거나
|
||
구면 방향 전체를 표본화한 3D 패턴으로 검사할 수 있습니다. 마이크는 송신원이 아니므로 엄밀히는
|
||
방사 패턴이 아니라 **수신 응답**입니다.
|
||
|
||
## 가장 짧은 사용법
|
||
|
||
1. Array Builder에서 마이크 배치를 만들거나 Array JSON을 엽니다.
|
||
2. 배열 canvas 아래의 **수신 빔 패턴**을 펼칩니다.
|
||
3. **로그 주파수 slider**를 움직여 실제 음향파의 아날로그 주파수를 live로 훑고 옆의 실제 값을
|
||
확인합니다.
|
||
4. 음속과 조향 방향을 정하고 XZ·YZ·XY 세 단면을 나란히 비교합니다.
|
||
5. 대각 방향을 포함한 전체 모양이 필요하면 3D 패턴으로 전환해 회전하며 검사합니다.
|
||
6. 기본 **자동 · 위상 간격 기준**을 사용하고, 계산량 비교가 필요할 때만 고정 표본 수를 고릅니다.
|
||
7. 각 보기의 raw 응답과 조건부 −3.0103 dB 폭, sampled local maxima 및 해상도 상태를 함께 읽습니다.
|
||
|
||
로그 slider에서 같은 화면 거리는 같은 Hz 차이가 아니라 같은 **주파수 비율**에 해당합니다. 따라서
|
||
넓은 범위를 저주파에 치우치지 않고 훑을 수 있습니다. 이 mapping은 UI 조작 방식일 뿐입니다. 계산에는
|
||
slider 위치가 아니라 현재의 선형 Hz 값 하나가 전달되며, 여러 주파수를 합치거나 보간해 하나의
|
||
패턴으로 만들지 않습니다. slider를 움직이면 그 순간의 한 주파수에서 현재 보기가 live로 갱신됩니다.
|
||
slider 위치 <code>p</code>는 0..6000의 정수이고
|
||
<code>f=10^(p/1000) Hz</code>로 바뀌므로 범위는 1 Hz..1 MHz, 한 칸의 비율은 약 1.002305입니다.
|
||
|
||
마이크를 드래그하는 동안에는 가벼운 preview를 표시하고, pointer를 놓으면 선택한 표본 설정으로 다시
|
||
계산합니다. 빔 패턴 설정과 2D/3D 보기 상태는 배열 좌표가 아니므로 undo history, 저장되지 않은 변경
|
||
상태와 Array JSON에는 들어가지 않습니다.
|
||
|
||
## 물리식과 좌표
|
||
|
||
마이크 위치 <code>r_m</code>, 배열 중심 <code>r_c</code>, array→source 방향 단위벡터
|
||
<code>u</code>, 조향 방향 <code>u0</code>, 아날로그 주파수 <code>f</code>, 음속
|
||
<code>c</code>에 대해 표시하는 complex receive array factor는 다음입니다.
|
||
|
||
<code>B(u) = (1/M) Σ_m exp[j (2πf/c) (u-u0)·(r_m-r_c)]</code>
|
||
|
||
각 마이크의 지수항은 조향 지연을 적용한 뒤 관찰 방향에 남는 복소 위상입니다. 관찰 방향과 조향
|
||
방향이 같아 <code>u=u0</code>이면 모든 지수항이 1이므로 <code>B(u0)=1</code>입니다.
|
||
<code>r_m-r_c</code>를 사용하므로 배열 전체를 평행 이동해도 패턴은 바뀌지 않고, 마이크 사이의 상대
|
||
배치만 영향을 줍니다.
|
||
|
||
<code>1/M</code>은 sampled maximum에 맞춘 사후 정규화가 아니라 고정 conventional
|
||
delay-and-sum weight입니다. 따라서 같은 0 dB 응답이 여러 방향에 있으면 모두 그대로 남습니다.
|
||
복소 응답의 실수부와 허수부를 <code>Re B</code>, <code>Im B</code>라 하면 raw power는
|
||
<code>P=|B|²=(Re B)²+(Im B)²</code>이고 raw dB는
|
||
<code>10 log10 P = 20 log10 |B|</code>입니다. 2D와 3D 보기의 표시 하한만 별도로 clamp하므로 표시
|
||
하한을 바꿔도 raw complex, power, peak 또는 HPBW 계산은 바뀌지 않습니다.
|
||
|
||
절단면 각도는 오른손 Array 좌표계에서 다음과 같습니다.
|
||
|
||
| 절단면 | 0° | +90° | 의미 |
|
||
| --- | --- | --- | --- |
|
||
| XZ | +Z | +X | 기본. XY 평면 배열의 broadside와 x축 단면 |
|
||
| YZ | +Z | +Y | XY 평면 배열의 broadside와 y축 단면 |
|
||
| XY | +X | +Y | 배열 평면 안의 edge 방향 단면 |
|
||
|
||
세 polar plot 모두 0°를 오른쪽, +90°를 위쪽에 그립니다. 하나의 각도 값은 각 단면의 위 규약에
|
||
따라 해석되므로 0°가 XZ·YZ에서는 +Z이고 XY에서는 +X입니다. 각 polar plot은 구면 전체가 아니라
|
||
하나의 great-circle 단면입니다. 세 개를 동시에 보더라도 대각 방향의 lobe를 놓칠 수 있으므로 전체
|
||
방향 검사는 3D 패턴을 사용합니다.
|
||
|
||
배열 편집 canvas는 XY 좌표를 정확히 배치하기 위한 2D 보기이고, 3D 배열 보기는 x/y/z 배치와 앞뒤를
|
||
회전해 검사하는 보기입니다. 좌표를 바꾸려면 2D canvas나 숫자 필드를 사용합니다. **+Z FRONT** 표시는
|
||
배열 좌표계에서 양의 z 쪽을 전면으로 읽으라는 기준이며, 마이크 element가 실제로 단방향이라는 뜻은
|
||
아닙니다. 3D 패턴은 같은 좌표계의 단위구면 방향 <code>u</code>들을 평가하므로 polar 세 단면에 없는
|
||
대각 방향 응답도 드러냅니다.
|
||
|
||
3D 표면은 구면 격자의 각 표시용 <code>displayDb</code> 표본을
|
||
<code>rho=clamp((displayDb-dbFloor)/(0-dbFloor),0,1)</code> 반지름으로 놓고 인접 격자점을 면으로
|
||
연결합니다. 이는 dB 동적 범위를 읽기 위한 표시 좌표이며 raw power를 바꾸지 않습니다. 격자 사이의
|
||
새 물리 응답을 보간하거나 surface를 평활화하지 않습니다.
|
||
|
||
## 모델에 들어가는 것과 빠지는 것
|
||
|
||
현재 array factor는 다음 조건을 명시적으로 고정합니다.
|
||
|
||
- 한 번에 아날로그 주파수 하나만 보는 monochromatic narrowband 가설
|
||
- 거리와 곡률이 없는 자유장의 far-field plane wave
|
||
- 위치만 가진, 이상적으로 보정된 무지향성 point microphone
|
||
- uniform conventional delay-and-sum weight
|
||
- meter 좌표와 사용자가 입력한 음속
|
||
|
||
slider를 움직여 여러 주파수의 모양을 연속해서 볼 수는 있지만, 각 frame은 서로 독립적인 단일
|
||
주파수 계산입니다. 광대역 신호의 spectrum을 적분하거나 서로 다른 주파수의 map을 융합하지 않습니다.
|
||
far-field 가정에는 source 거리 입력이 없으므로 거리 추정, 구면파 곡률, <code>1/r</code> 감쇠도 이
|
||
plot에서 평가할 수 없습니다.
|
||
|
||
따라서 방 반사·회절·산란, near-field 거리와 구면 감쇠, baffle·housing·상호결합, 마이크의 각도별
|
||
element directivity는 포함하지 않습니다. 이 패턴은 위치 확률분포나 실제 장면의 localization
|
||
정확도도 아닙니다. Array JSON의 <code>sensitivityDb</code>,
|
||
<code>phaseOffsetDeg</code>와 <code>frequencyResponse</code>도 이 geometry-only plot에는
|
||
섞지 않습니다. 이 보정들은 합성 및 위치추정 pipeline에서 별도로 적용됩니다. 주파수 응답은
|
||
주파수별 channel transfer이고, 그 자체가 각도별 element pattern은 아닙니다.
|
||
|
||
## Nyquist와 공간 alias
|
||
|
||
이 계산에는 ADC sample rate 입력이 없습니다. 파수는 항상 원래 아날로그 주파수로
|
||
<code>k=2πf/c</code>를 계산하며, 48 kHz ADC를 가정했을 때 Nyquist를 넘는 49,125 Hz 같은 값도
|
||
1,125 Hz로 접지 않습니다. 이는 배열 설계에서 실제 파장과 grating/ambiguity를 관찰하기 위한
|
||
의도된 동작입니다.
|
||
|
||
ADC의 temporal alias, anti-alias filter와 signed alias orientation은 sampling 단계의 문제입니다.
|
||
마이크 간격·파장·조향이 만드는 spatial alias와는 별개입니다. 이 plot은 sampled local maximum을
|
||
보여줄 수 있지만, 그것을 자동으로 grating lobe나 sidelobe로 분류하지 않습니다. planar 배열의
|
||
앞·뒤 0 dB 동률처럼 서로 다른 원인도 같은 단면 응답으로 나타날 수 있기 때문입니다.
|
||
|
||
## HPBW와 각도 해상도
|
||
|
||
HPBW는 조향 방향을 포함하는 연결 lobe에서 raw power가 정확히 0.5, 즉 −3.010299956… dB가 되는
|
||
양쪽 crossing을 찾았을 때만 표시합니다. 표본 두 점이 crossing을 bracket하면 raw analytic
|
||
evaluator로 각 경계를 48회 이분합니다.
|
||
|
||
고주파·큰 aperture에서는 고정 각도 grid가 매우 좁은 lobe나 dip을 건너뛸 수 있습니다. 이를 숨기지
|
||
않기 위해 투영된 최대 microphone baseline <code>D</code>, 각도 간격
|
||
<code>Δ=2π/N</code>에 대한 인접 방향 pair phase 변화 상한
|
||
<code>2 k D sin(Δ/2)</code>를 계산합니다. 현재 metric 해석 기준은 이 상한이
|
||
<code>π/8</code> 이하인 경우입니다.
|
||
|
||
이 기준은 공개된 수치 해상도 정책이지, 모든 연속 lobe와 half-power excursion을 검출한다는
|
||
수학적 증명이 아닙니다. 기준을 넘으면 raw polar 표본은 그대로 표시하되 HPBW와 peak 해석을
|
||
<code>resolution-unresolved</code>로 보류합니다. 기준을 만족해도 half-power crossing을 표본에서
|
||
찾지 못한 비상수 패턴은 360° HPBW라고 만들지 않고
|
||
<code>no-sampled-half-power-crossing</code>으로 남깁니다. 단일 또는 절단면 투영 좌표가 모두 같은
|
||
배열만 analytic constant로 판정하고 폭을 <code>null</code>로 반환합니다.
|
||
|
||
자동 표본은 최소 720개에서 시작해 이 phase-step 기준에 맞게 늘어나며 최대 14,400개와 전체 phasor
|
||
평가 상한을 지킵니다. 상한에서도 기준을 만족하지 못하면 계산을 예쁘게 보이도록 평활화하거나
|
||
peak를 제거하지 않고 미확정 상태를 표시합니다.
|
||
|
||
portable 함수의 호출별 상한과 별도로 Array Builder는 UI 정지를 줄이기 위해 live preview 전체를
|
||
240만 microphone-direction 평가로, pointer를 놓은 뒤의 전체 해상도 계산을 1,600만 평가로 제한합니다.
|
||
XZ·YZ·XY 동시 보기에서는 이 예산을 세 호출에 동일하게 분배합니다. 필요한 자동 표본이 예산을
|
||
넘으면 coarse 결과로 바꾸지 않고 계산을 거부하므로, 사용자가 고정 표본 수·주파수·채널 수의
|
||
trade-off를 직접 선택할 수 있습니다.
|
||
|
||
## portable API
|
||
|
||
<code>beam-pattern.js</code>는 DOM, Scene, ADC와 외부 package에 의존하지 않는 ES module입니다.
|
||
|
||
~~~js
|
||
import {
|
||
computeReceiveBeamPattern,
|
||
computeReceiveBeamPatternSphere,
|
||
} from "./packages/acoustics-core/beam-pattern.js";
|
||
|
||
const pattern = computeReceiveBeamPattern({
|
||
array,
|
||
frequencyHz: 49_125,
|
||
speedOfSound: 343,
|
||
cut: "xz",
|
||
steeringAngleDeg: 0,
|
||
sampleCount: "auto",
|
||
dbFloor: -60,
|
||
});
|
||
|
||
drawPolar(pattern.anglesDeg, pattern.displayDb);
|
||
|
||
if (!pattern.angularSampling.metricResolutionSatisfied) {
|
||
showUnresolved(pattern.angularSampling.maximumAdjacentPhaseStepRadBound);
|
||
}
|
||
|
||
const sphere = computeReceiveBeamPatternSphere({
|
||
array,
|
||
frequencyHz: 49_125,
|
||
speedOfSound: 343,
|
||
steeringAzimuthDeg: 0,
|
||
steeringElevationDeg: 90,
|
||
azimuthSampleCount: 120,
|
||
elevationSampleCount: 61,
|
||
dbFloor: -60,
|
||
});
|
||
|
||
// elevation-major: index = elevationIndex * azimuthSampleCount + azimuthIndex
|
||
drawSphere(
|
||
sphere.azimuthAxisDeg,
|
||
sphere.elevationAxisDeg,
|
||
sphere.displayDb,
|
||
sphere.grid.shape,
|
||
);
|
||
~~~
|
||
|
||
portable 함수는 명시한 절단면 하나를 계산합니다. Array Builder의 동시 polar 보기는 같은 주파수와
|
||
공통 설정으로 XZ·YZ·XY를 각각 계산해 나란히 표시하는 UI 구성입니다. 3D 보기 역시 같은 물리식의
|
||
관찰 방향 <code>u</code>를 구면 위에서 평가합니다. 세 단면을 평균하거나 maximum으로 합치는 새
|
||
beamforming 알고리즘이 아닙니다.
|
||
|
||
결과는 normalized raw <code>responseReal</code>, <code>responseImaginary</code>,
|
||
<code>responsePower</code>, <code>responseLinear</code>, unclamped <code>responseDb</code>와
|
||
표시용 <code>displayDb</code>를 각각 보존합니다. workload에는 baseline pair 비교, sampled phasor,
|
||
HPBW용 최대·실제 평가 수가 따로 기록됩니다. 1,024채널, 0–1 MHz, 각도·phasor·baseline 상한은
|
||
할당과 큰 반복 전에 검사합니다.
|
||
|
||
far-field steering vector와 beamformer response를 구현한 독립 참고 구현은
|
||
[Pyroomacoustics 공식 beamforming source](https://github.com/LCAV/pyroomacoustics/blob/master/pyroomacoustics/beamforming.py)에서
|
||
확인할 수 있습니다. array factor와 element pattern의 구분은
|
||
[MathWorks 공식 설명](https://www.mathworks.com/help/phased/ug/element-and-array-radiation-patterns-and-responses.html)을
|
||
함께 참고하세요.
|