diff --git a/README.md b/README.md
index 6cf257c..4116f2e 100644
--- a/README.md
+++ b/README.md
@@ -111,7 +111,9 @@ causal latency는 [전 대역 활동 검출 모델](docs/activity-detection.md)
seed로 같은 좌표를 재현하며, 최소 간격과 경계 여백도 지정할 수 있습니다.
4. **추가** 도구로 canvas에 마이크를 놓고, 선택한 점을 드래그하거나 x/y/z 입력으로 수정합니다.
목록에서는 삭제와 채널 순서 변경도 할 수 있습니다.
-5. 상태가 **Array JSON 저장 가능**이면 **Array JSON 저장**을 누릅니다.
+5. canvas 아래 **수신 빔 패턴**에서 아날로그 주파수·360° 절단면·조향각을 바꿔 polar 응답과
+ 조건부 −3.0103 dB 폭, sampled peak 동률을 확인합니다.
+6. 상태가 **Array JSON 저장 가능**이면 **Array JSON 저장**을 누릅니다.
불러온 Array의 `sensitivityDb`, `phaseOffsetDeg`, `frequencyResponse` 보정 정보는 마이크 위치·ID나
채널 순서를 편집해도 보존됩니다. 프리셋 생성은 마이크 목록 전체를 새로 만드는 작업이므로 기존
@@ -119,6 +121,7 @@ causal latency는 [전 대역 활동 검출 모델](docs/activity-detection.md)
생성 경계 형상, 프리셋 종류, random seed와 최소 간격은 편집을 돕는 설정이며 표준 Array JSON에
저장되지 않습니다. 저장되는 것은 aperture 너비·높이와 최종 마이크 좌표·순서 및 채널별 보정값입니다.
+빔 패턴 주파수·절단면·조향각도 preview 설정이므로 Array JSON과 undo/dirty 상태에 들어가지 않습니다.
자세한 사용법은 [`apps/array-builder/README.md`](apps/array-builder/README.md)를 참고하세요.
### 2. Dataset Builder에서 Scene 만들기
@@ -340,6 +343,9 @@ Camera의 **배열 선택**에서 8개 fixture를 바로 불러와 같은 Scene/
의도된 예제 특성입니다.
새 배치를 직접 만들려면 [Array Builder](apps/array-builder/README.md)를 사용하세요. 저장소 fixture의
상세한 생성법은 [`assets/array-geometries/README.md`](assets/array-geometries/README.md)를 참고하세요.
+Array Builder는 현재 배치의 geometry-only conventional receive array factor를 XZ·YZ·XY 360°
+polar 단면으로 즉시 표시합니다. 이 계산은 ADC sample rate 없이 원 아날로그 파장을 사용하므로
+Nyquist 초과 조건도 실행하며, 각도 해상도가 부족하면 raw 선을 남긴 채 HPBW·peak 해석을 보류합니다.
## 테스트와 benchmark
@@ -362,6 +368,7 @@ test.cmd
## 저장 형식과 개발 문서
- [전 대역 활동 검출 모델](docs/activity-detection.md): CA/OS-CFAR, spectral flux와 alias 가설 흐름
+- [수신 빔 패턴 모델](docs/beam-pattern.md): array factor 수식, polar 단면, HPBW와 해상도 기준
- [`docs/data-contracts.md`](docs/data-contracts.md): Array·Scene·Experiment·Result 계약
- [`docs/acoustic-model.md`](docs/acoustic-model.md): 마이크 응답과 자유음장·shoebox 희소 근사
- [`docs/realtime-porting.md`](docs/realtime-porting.md): 실측 다채널 위치추정 API 포팅
diff --git a/apps/array-builder/README.md b/apps/array-builder/README.md
index 4b76eaf..297e832 100644
--- a/apps/array-builder/README.md
+++ b/apps/array-builder/README.md
@@ -2,7 +2,8 @@
Array Builder는 `micarrsim.array` JSON을 브라우저에서 만드는 마이크 배열 편집기입니다. aperture
크기와 생성 경계를 정한 뒤 프리셋으로 시작하거나 마이크를 직접 추가·이동해 Acoustic Camera의
-배열 입력으로 사용할 수 있습니다.
+배열 입력으로 사용할 수 있습니다. 같은 화면에서 현재 좌표의 narrowband far-field 수신 빔 패턴도
+확인할 수 있습니다.
## 열기
@@ -15,8 +16,9 @@ Array Builder는 `micarrsim.array` JSON을 브라우저에서 만드는 마이
1. **크기와 형상**에서 aperture 너비·높이와 생성 경계를 정합니다.
2. 프리셋을 고르고 **현재 배열을 프리셋으로 교체**를 누릅니다.
3. canvas와 마이크 목록에서 좌표와 채널 순서를 다듬습니다.
-4. 상태가 **Array JSON 저장 가능**인지 확인하고 **Array JSON 저장**을 누릅니다.
-5. Acoustic Camera를 열어 **Array** 입력에서 저장한 `.array.json`을 선택합니다.
+4. canvas 아래 **수신 빔 패턴**에서 주파수·절단면·조향각에 따른 main lobe와 동률 응답을 확인합니다.
+5. 상태가 **Array JSON 저장 가능**인지 확인하고 **Array JSON 저장**을 누릅니다.
+6. Acoustic Camera를 열어 **Array** 입력에서 저장한 `.array.json`을 선택합니다.
## 크기와 생성 경계
@@ -65,6 +67,32 @@ Array JSON을 저장하세요.
`JSON 열기`로 다른 배열을 불러온 직후에도 한 번 실행 취소하면 불러오기 전 문서를 복구할 수
있습니다. 다시 실행하면 불러온 배열로 돌아갑니다.
+## 수신 빔 패턴
+
+배열 canvas 아래의 분석 카드는 ideal calibrated omnidirectional point microphone에 conventional
+delay-and-sum을 적용한 geometry-only receive array factor를 표시합니다.
+
+- **아날로그 주파수:** ADC bin이나 alias 주파수가 아닌 실제 음향 주파수입니다. 1 MHz까지
+ 입력할 수 있으며 sample rate가 없으므로 Nyquist를 넘어도 원래 파장을 사용합니다.
+- **절단면:** XZ는 0°=+Z·90°=+X, YZ는 0°=+Z·90°=+Y, XY는 0°=+X·90°=+Y입니다.
+- **조향각:** 선택한 360° great-circle 단면 안에서 conventional beamformer가 보는 방향입니다.
+- **각도 샘플:** 자동은 투영 aperture와 파장에 맞춰 최소 720개에서 늘립니다. 고정 sample은
+ 계산량 비교나 일부러 coarse한 설계 조건을 확인할 때 사용합니다.
+- **표시 하한:** polar dB radius에만 적용됩니다. raw complex·power와 HPBW는 바뀌지 않습니다.
+
+마이크를 드래그하는 동안 최대 720-angle preview를 갱신하고 놓으면 선택한 해상도로 다시 계산합니다.
+π/8 인접 pair phase-step 기준을 넘으면 raw polar 선은 유지하되 HPBW와 peak 해석을 **해상도
+부족**으로 보류합니다. 기준을 만족한다는 것은 공개된 sampling 정책을 통과했다는 뜻이며 모든 연속
+lobe 검출을 보장하지 않습니다.
+
+−3.0103 dB 폭은 조향 lobe의 sampled bracket을 찾은 경우에만 표시합니다. sampled local maximum은
+모두 나열하고 0 dB 동률을 임의로 하나 고르지 않지만, 이를 grating lobe나 sidelobe로 자동 분류하지
+않습니다. plot은 3D 전체가 아니라 선택한 단면이고 near-field, 방·하우징·element directivity와
+마이크 frequency response는 포함하지 않습니다.
+
+수식, raw 결과 필드, workload 상한과 상태 의미는
+[`../../docs/beam-pattern.md`](../../docs/beam-pattern.md)에 정리되어 있습니다.
+
## 보정값 보존
선택한 채널의 `sensitivityDb`와 `phaseOffsetDeg`는 보정값 펼침 영역에서 편집할 수 있습니다. 기존
@@ -84,8 +112,8 @@ frequency response도 함께 제거됩니다.
- 채널별 선택적 sensitivity, phase와 frequency-response curve
생성 경계의 사각형/타원 선택, 프리셋 종류, 행·열, random seed·최소 간격·경계 여백, snap과
-zoom은 편집기 설정입니다. 표준 Array JSON에는 저장되지 않으며 Camera는 최종 aperture와 실제
-마이크 좌표·순서를 사용합니다.
+zoom, 빔 패턴 주파수·절단면·조향각·표본 수는 편집기 설정입니다. 표준 Array JSON에는 저장되지
+않으며 Camera는 최종 aperture와 실제 마이크 좌표·순서를 사용합니다.
## Camera로 전달하기
@@ -94,8 +122,9 @@ zoom은 편집기 설정입니다. 표준 Array JSON에는 저장되지 않으
3. 입력 준비의 **Array**에서 저장한 파일을 선택합니다.
4. 채널 수와 aperture 요약을 확인한 뒤 Scene과 Experiment를 준비해 실행합니다.
-Experiment를 별도 파일로 가져올 때는 그 문서의 `arrayId`가 방금 불러온 Array ID와 같아야 합니다.
-Camera에서 배열 선택이 **불러온 Array JSON**으로 바뀌고 입력 검증이 통과했는지 확인하세요.
+Experiment의 `arrayId`는 provenance label이라 불러온 Array의 `id`와 달라도 실행을 막거나
+경고하지 않습니다. Camera에서 배열 선택이 **불러온 Array JSON**으로 바뀌고 채널 수·좌표가 의도한
+배열인지 직접 확인하세요.
## 검증과 제한
diff --git a/docs/beam-pattern.md b/docs/beam-pattern.md
new file mode 100644
index 0000000..c7a77d3
--- /dev/null
+++ b/docs/beam-pattern.md
@@ -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에는 들어가지 않습니다.
+
+## 물리식과 좌표
+
+마이크 위치 r_m, 배열 중심 r_c, array→source 방향 단위벡터
+u, 조향 방향 u0, 아날로그 주파수 f, 음속
+c에 대해 표시하는 complex receive array factor는 다음입니다.
+
+B(u) = (1/M) Σ_m exp[j (2πf/c) (u-u0)·(r_m-r_c)]
+
+1/M은 sampled maximum에 맞춘 사후 정규화가 아니라 고정 conventional
+delay-and-sum weight입니다. 따라서 조향 방향은 이상적 모델에서 1이고, 같은 0 dB 응답이 여러
+방향에 있으면 모두 그대로 남습니다. Array Builder는 |B|²와
+10 log10(|B|²)를 계산하며, 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의 sensitivityDb,
+phaseOffsetDeg와 frequencyResponse도 이 geometry-only plot에는
+섞지 않습니다. 이 보정들은 합성 및 위치추정 pipeline에서 별도로 적용됩니다. 주파수 응답은
+주파수별 channel transfer이고, 그 자체가 각도별 element pattern은 아닙니다.
+
+## Nyquist와 공간 alias
+
+이 계산에는 ADC sample rate 입력이 없습니다. 파수는 항상 원래 아날로그 주파수로
+k=2πf/c를 계산하며, 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 D, 각도 간격
+Δ=2π/N에 대한 인접 방향 pair phase 변화 상한
+2 k D sin(Δ/2)를 계산합니다. 현재 metric 해석 기준은 이 상한이
+π/8 이하인 경우입니다.
+
+이 기준은 공개된 수치 해상도 정책이지, 모든 연속 lobe와 half-power excursion을 검출한다는
+수학적 증명이 아닙니다. 기준을 넘으면 raw polar 표본은 그대로 표시하되 HPBW와 peak 해석을
+resolution-unresolved로 보류합니다. 기준을 만족해도 half-power crossing을 표본에서
+찾지 못한 비상수 패턴은 360° HPBW라고 만들지 않고
+no-sampled-half-power-crossing으로 남깁니다. 단일 또는 절단면 투영 좌표가 모두 같은
+배열만 analytic constant로 판정하고 폭을 null로 반환합니다.
+
+자동 표본은 최소 720개에서 시작해 이 phase-step 기준에 맞게 늘어나며 최대 14,400개와 전체 phasor
+평가 상한을 지킵니다. 상한에서도 기준을 만족하지 못하면 계산을 예쁘게 보이도록 평활화하거나
+peak를 제거하지 않고 미확정 상태를 표시합니다.
+
+## portable API
+
+beam-pattern.js는 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 responseReal, responseImaginary,
+responsePower, responseLinear, unclamped responseDb와
+표시용 displayDb를 각각 보존합니다. 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)을
+함께 참고하세요.
diff --git a/docs/data-contracts.md b/docs/data-contracts.md
index 8b97007..e5d4aa9 100644
--- a/docs/data-contracts.md
+++ b/docs/data-contracts.md
@@ -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의 기준으로 사용해야 한다.
diff --git a/docs/execution-plan.md b/docs/execution-plan.md
index 4281cc4..8623c54 100644
--- a/docs/execution-plan.md
+++ b/docs/execution-plan.md
@@ -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
diff --git a/docs/index.html b/docs/index.html
index 8ab8c55..2ac9862 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -102,6 +102,7 @@