docs: explain receive beam pattern workflow

This commit is contained in:
2026-08-29 14:54:09 +09:00
parent b68cd87e3c
commit 6804eca6ed
9 changed files with 231 additions and 12 deletions
+130
View File
@@ -0,0 +1,130 @@
# 마이크 어레이 수신 빔 패턴
Array Builder의 **수신 빔 패턴**은 현재 마이크 좌표에 conventional delay-and-sum을 적용했을 때의
narrowband far-field array factor를 360° polar 단면으로 보여줍니다. 마이크는 송신원이 아니므로
엄밀히는 방사 패턴이 아니라 **수신 응답**입니다.
## 가장 짧은 사용법
1. Array Builder에서 마이크 배치를 만들거나 Array JSON을 엽니다.
2. 배열 canvas 아래의 **수신 빔 패턴**을 펼칩니다.
3. 실제 음향파의 **아날로그 주파수**와 음속을 입력합니다.
4. XZ, YZ 또는 XY 360° 절단면과 조향각을 고릅니다.
5. 기본 **자동 · 위상 간격 기준**을 사용하고, 계산량 비교가 필요할 때만 고정 표본 수를 고릅니다.
6. polar 선, 조향 응답, 조건부 −3.0103 dB 폭과 sampled local maxima를 함께 읽습니다.
마이크를 드래그하는 동안에는 최대 720개 각도의 가벼운 preview를 표시합니다. 마우스나 pointer를
놓으면 선택한 표본 설정으로 다시 계산합니다. 빔 패턴 설정은 배열 좌표가 아니므로 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>1/M</code>은 sampled maximum에 맞춘 사후 정규화가 아니라 고정 conventional
delay-and-sum weight입니다. 따라서 조향 방향은 이상적 모델에서 1이고, 같은 0 dB 응답이 여러
방향에 있으면 모두 그대로 남습니다. Array Builder는 <code>|B|²</code>와
<code>10 log10(|B|²)</code>를 계산하며, polar 표시 하한만 별도 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°를 위쪽에 그립니다. 각 plot은 구면 전체가 아니라 하나의
great-circle 단면입니다. 임의 3D 배열을 세 단면만으로 완전히 평가할 수는 없습니다.
## 모델에 들어가는 것과 빠지는 것
현재 array factor는 다음 조건을 명시적으로 고정합니다.
- analog monochromatic narrowband 가설
- 자유장의 far-field plane wave
- 위치만 가진, 이상적으로 보정된 무지향성 point microphone
- uniform conventional delay-and-sum weight
- meter 좌표와 사용자가 입력한 음속
따라서 방 반사·회절·산란, near-field 거리와 구면 감쇠, baffle·housing·상호결합, 마이크의 각도별
element directivity는 포함하지 않습니다. 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 API
<code>beam-pattern.js</code>는 DOM, Scene, ADC와 외부 package에 의존하지 않는 ES module입니다.
~~~js
import { computeReceiveBeamPattern } 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);
}
~~~
결과는 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)을
함께 참고하세요.
+2 -1
View File
@@ -28,7 +28,8 @@ array의 `sensitivityDb`와 `phaseOffsetDeg`는 각 마이크 수신 channel에
측정 범위 밖에서는 가까운 끝점을 사용한다.
Array Builder의 사각형/타원 생성 경계, 프리셋 종류, 행·열, random seed·최소 간격·경계 여백,
snap과 zoom은 편집기 상태이며 `micarrsim.array` 계약에 포함되지 않는다. 저장 파일에는
snap·zoom과 수신 빔 패턴의 주파수·음속·절단면·조향각·angular sample·display floor는 편집기
preview 상태이며 `micarrsim.array` 계약에 포함되지 않는다. 저장 파일에는
`aperture.width/height`와 최종 `microphones` 좌표·순서만 들어간다. 따라서 다른 도구는
형상 이름을 추론하지 않고 실제 좌표를 배열 geometry의 기준으로 사용해야 한다.
+7 -2
View File
@@ -41,13 +41,15 @@ CPU 기준 구현과 GPU 결과의 수치 오차가 합의된 허용 범위 안
세 앱의 책임은 다음과 같이 분리한다.
- `array-builder`: aperture 크기와 사각/타원 생성 경계, 격자·선형·둘레·Fermat·seed random
프리셋, 마이크 직접 편집·채널 순서·보정 보존과 표준 Array JSON 내보내기
프리셋, 마이크 직접 편집·채널 순서·보정 보존, receive array-factor polar 분석과 표준 Array
JSON 내보내기
- `dataset-builder`: 음원 배치, gain/시간 구간/반복 설정, ambient mix, 이미지상의 위치 지정,
seed 고정, 합성 오디오와 ground truth manifest 내보내기
- `acoustic-camera`: manifest와 배열 JSON 읽기, 마이크 신호 전파 합성, steering vector 생성,
DAS 실행, overlay·수치 평가·실험 결과 내보내기
- `acoustics-core`: 앱들이 공유하는 좌표계, 단위, 구면 감쇠·희소 multipath·마이크 응답,
STFT, 정답 rasterization, 지표, CPU reference와 실측 channel용 streaming localizer
STFT, far-field receive array factor, 정답 rasterization, 지표, CPU reference와 실측
channel용 streaming localizer
- `webgpu-kernels`: steering/DAS 커널, buffer layout, 장치 한도 검사와 benchmark
## 3. 데이터 계약
@@ -179,6 +181,8 @@ flattening이 모델 타당성을 훼손하는지 청취 및 spectrum 통계로
- canvas 추가·선택·drag, 정밀 좌표·ID·채널 순서 편집과 undo/redo
- 가져온 sensitivity·phase·frequency response 보존과 표준 Array JSON 왕복
- 좌표 중복 오류, 경계 초과 경고, clamp·중앙 정렬·aperture 맞춤
- analog frequency·XZ/YZ/XY 조향의 360° conventional receive array-factor polar plot
- raw complex/power 보존, 조건부 HPBW·sampled peak tie와 phase-step 해상도 미확정 상태
완료 조건: 만든 Array가 계약 검증을 통과하고 Acoustic Camera에서 그대로 불러와진다.
@@ -242,6 +246,7 @@ hardware deadline과 정확도는 장치 adapter가 정해진 뒤 별도 측정
- [x] 설치 없는 ES module workspace와 세 앱 shell
- [x] Array Builder 프리셋·직접 편집·검증·Camera 전달
- [x] Array Builder receive array-factor polar 단면·HPBW·Nyquist 초과 설계 조건
- [x] array/scene/experiment/result schema와 synthetic fixture
- [x] 좌표·거리·구면 감쇠·분수 지연·STFT 단위 테스트
- [x] CPU DAS golden implementation
+8
View File
@@ -102,6 +102,7 @@
<li><a href="/apps/array-builder/">Array Builder</a>에서 aperture 너비·높이와 사각형 또는 타원 생성 경계를 정합니다.</li>
<li>격자·선형·원형·Fermat 나선·균일 랜덤 중 하나를 고릅니다. 랜덤은 seed와 최소 간격으로 재현성과 채널 간 거리를 제어합니다.</li>
<li>canvas의 <strong>추가</strong> 도구로 마이크를 놓고, 점을 드래그하거나 x/y/z 필드로 좌표를 수정합니다.</li>
<li>canvas 아래 <strong>수신 빔 패턴</strong>에서 아날로그 주파수·XZ/YZ/XY 절단면·조향각에 따른 polar 응답을 확인합니다.</li>
<li>목록에서 마이크를 삭제하거나 채널 순서를 바꾸고, 상태가 <strong>Array JSON 저장 가능</strong>이면 저장합니다.</li>
<li><a href="/apps/acoustic-camera/">Acoustic Camera</a>의 <strong>Array</strong> 입력에서 저장한 파일을 선택합니다.</li>
</ol>
@@ -113,6 +114,12 @@
생성 경계 형상, 프리셋 종류, seed와 최소 간격은 편집기 설정이라 표준 Array JSON에
저장되지 않습니다. Camera가 사용하는 것은 저장된 aperture와 최종 마이크 좌표·순서입니다.
</aside>
<aside class="callout">
빔 패턴은 이상적으로 보정된 무지향성 point microphone의 narrowband far-field
geometry-only 수신 단면입니다. Nyquist 초과 주파수도 원 파장으로 계산하며, angular
phase-step 기준이 부족하면 raw polar 선만 남기고 HPBW·peak 해석을 보류합니다.
<a href="/docs/beam-pattern.md">수식과 제한 보기</a>
</aside>
</div>
</section>
@@ -343,6 +350,7 @@
<a href="/apps/dataset-builder/README.md"><strong>Dataset Builder 설명서</strong><span>source·ambient·Preview WAV</span></a>
<a href="/apps/acoustic-camera/README.md"><strong>Camera 설명서</strong><span>backend·결과·비교</span></a>
<a href="/docs/activity-detection.md"><strong>전 대역 활동 검출</strong><span>CFAR·spectral flux·alias 가설</span></a>
<a href="/docs/beam-pattern.md"><strong>수신 빔 패턴</strong><span>array factor·HPBW·해상도</span></a>
<a href="/docs/acoustic-model.md"><strong>음향 모델</strong><span>마이크 응답·반사·산란·회절</span></a>
<a href="/docs/realtime-porting.md"><strong>실측 포팅</strong><span>block·streaming 위치추정 API</span></a>
<a href="/docs/data-contracts.md"><strong>데이터 계약</strong><span>JSON Schema와 재현성</span></a>