20 KiB
Acoustic Camera
Scene과 마이크 배열로 자유음장 또는 저비용 shoebox microphone signal을 합성하고, 표준 CA/OS-CFAR·Dixon spectral flux로 ADC 대역 후보를 보거나 STFT와 DAS·DAS-PHAT·GCC-PHAT·MUSIC 위치추정으로 주파수 대역별 acoustic map과 ground-truth 평가 지표를 만드는 브라우저 앱입니다. 정지 장면은 Snapshot, trajectory 장면은 Moving 흐름으로 분리되어 있습니다.
열기와 Snapshot
저장소의 start.cmd를 실행한 뒤 시작 화면에서 Acoustic Camera를 선택하거나
http://127.0.0.1:4173/apps/acoustic-camera/을 엽니다. index.html을 직접 열지 마세요.
데스크톱에서는 왼쪽 설정 패널과 결과 작업 영역 사이의 선을 드래그해 폭을 조절할 수 있습니다.
방향키도 지원하며 Enter 또는 더블클릭으로 기본 폭을 복원합니다. 앱별 폭은 브라우저에
저장되고, 980px 이하에서는 설정과 결과가 위아래로 자동 배치됩니다. 패널을 최소 폭으로 줄이면
파일·분석 설정과 주파수 대역 입력도 실제 패널 폭에 맞춰 한 열 또는 두 행으로 재배치됩니다.
가장 빠른 확인 방법은 다음과 같습니다.
- 기본 fixture가 준비될 때까지 기다립니다.
- 192채널 rectangular 배열, single-tone scene과 50×50 grid를 그대로 둡니다.
- 상단 작업 순서에서 입력·설정 상태를 확인한 뒤 Snapshot 카드의 ▶ Snapshot 실행을 누릅니다.
- 완료 후 overlay, 위치 오차와 timing을 확인하고 Result JSON을 저장합니다.
MUSIC은 현재 장면 제목 옆 MUSIC 빠른 예제 → ▶ Snapshot 실행 두 단계로 확인할 수 있습니다. 12채널 배열, 1.125 kHz 단일 FFT-grid 가설과 Fixed K=1 Experiment가 함께 열립니다.
이동 장면을 바로 보려면 Moving 카드에서 이동 예제 열기 → Map 준비 → 재생 순서로 누릅니다. 이동 예제는 24×18 grid와 2 Hz map rate를 사용해 CPU fallback에서도 준비량을 줄였습니다.
사용자 입력 불러오기
문서는 다음 순서로 불러오면 asset 연결까지 한 번에 확인하기 쉽습니다.
- Scene:
.scene.json - Array: 선택 사항인
.array.json; 또는 비교 배열 preset 사용 - Experiment: 선택 사항인
.experiment.json - Assets: Scene이 참조하는 원본 이미지와 오디오
Scene을 불러오면 scan plane/bounds를 새 Scene에 맞추고 기존 asset 연결을 해제하지만
Experiment의 sceneId provenance label과 분석 대역은 보존합니다. Array를 불러와도
arrayId label을 덮어쓰지 않습니다. 별도 Experiment는 어느 시점에 불러와도 문서 자체를
먼저 검증하며 원래 sceneId/arrayId와 모든 분석 대역을 보존합니다. ID가 달라도 실행이
막히지 않고 현재 열린 Scene·Array가 실제 입력이 되며, Result에 그 실제 ID와 hash가 기록됩니다.
Nyquist 위 tone·band는 ideal ADC
alias로 실행되고, 잘못된 scan 범위 같은 실제 관계 오류는 그대로 거부됩니다.
Scene JSON에는 원본 파일 byte가 없습니다. Assets에서 Builder에 사용한 파일을 다시 선택하면 Camera가 SHA-256을 계산해 manifest에 연결합니다. 같은 이름이라도 내용이 바뀌면 거절됩니다. 브라우저를 다시 열거나 Scene을 바꿀 때도 재선택해야 합니다.
- asset 한 파일: 최대 128 MiB
- 연결된 asset 합계: 최대 512 MiB
- decode되어 메모리에 유지되는 오디오 합계: 최대 192 MiB
파일은 외부로 업로드되지 않고 브라우저 메모리에서만 처리됩니다.
전 대역 활동 후보 찾기
분석 주파수를 미리 모를 때는 분석 대역 아래의 전 대역 활동 검사를 펼칩니다. 이 흐름은 위치추정 map과 별도이며 다음 순서로 사용합니다.
- 실제로 관찰할 물리 마이크 한 채널을 고릅니다.
- 좁은 spectral outlier에는 OS-CFAR 또는 CA-CFAR, 갑작스러운 onset에는 Dixon spectral flux를 고릅니다.
- 전 대역 검사를 누르고 frame별 원시 결과를 확인합니다.
- CFAR가 표시한 ADC bin에 대응한다고 가정할 아날로그 center를 직접 입력합니다.
- 이 가설을 대역으로 추가한 뒤 DAS·PHAT·GCC-PHAT·MUSIC으로 배열 위치응답을 비교합니다.
- 모든 complete frame과 모든 tested/untested bin은 Activity JSON으로 저장합니다.
Activity worker는 Scene과 선택한 마이크의 위치·응답으로 물리 수신 신호를 합성하지만, 음원 위치·주파수·개수 정답은 detector 함수에 전달하지 않습니다. 선택하지 않은 마이크는 합성하거나 평균·투표하지 않습니다. 위치추정 band, algorithm, backend 또는 배경 image 연결이 잘못돼 Snapshot을 실행할 수 없어도, Scene·선택 마이크·STFT·합성 최소 거리와 필요한 audio asset이 유효하면 Activity는 실행할 수 있습니다.
CFAR는 Hann STFT의 각 complete frame을 독립 검사합니다. DC, Nyquist와 좌우 full reference window가 없는 edge bin은 reference 수를 줄이거나 wrap하지 않고 untested로 남깁니다. Pfa는 IID exponential square-law 배경을 가정한 tested CUT 하나당 명목 오경보율이며 위치 확률, confidence, frame 전체 오경보율 또는 실측 보정값이 아닙니다. 화면에는 CUT, reference, threshold와 ratio를 그대로 표시합니다.
Dixon spectral flux는 Hamming STFT의 연속 frame 사이에서 증가한 linear magnitude의 full-DFT L1 합입니다. 지속 activity가 아니라 onset novelty입니다. Böck–Krebs–Schedl causal peak picker는 기본으로 꺼져 있고, 켤 때도 delta는 확률이 아닌 사용자 보정값입니다. Frame start는 설명용 시각이며 available 시각이 실제 causal 판정 가능 시각입니다.
Scene의 peak normalization을 선택했다면 선택한 한 채널의 전체 render peak가 detector 전에 적용됩니다. 이 경우 detector 자체는 입력 이후 causal이어도 spectral-flux 절대값과 delta event를 포함한 end-to-end 전처리는 미래 sample에 의존하며, UI와 JSON에 이를 표시합니다. 물리 scale을 그대로 비교하려면 Scene normalization을 none으로 두세요.
검출기가 관찰하는 주파수는 ADC의 0…Fs/2뿐입니다. 예를 들어 Fs=48 kHz에서 ADC 1,125 Hz로 보인 성분은 1,125 Hz, 46,875 Hz, 49,125 Hz 등 여러 아날로그 carrier와 양립합니다. Nyquist 초과 가설도 0–1 MHz 검증 범위에서 허용하지만 alias order와 spectral inversion은 자동 선택하지 않습니다. 각 가설을 FFT-grid center의 별도 band로 추가합니다. CFAR와 flux, 서로 다른 band 또는 위치 map을 합의·평균·maximum으로 자동 결합하지 않습니다.
수식, 통계 가정, 문헌과 raw output 계약은 전 대역 활동 검출 모델을 참고하세요.
위치 추정 알고리즘과 Backend
분석 설정 → 위치 추정 알고리즘에서 다음 네 구현을 선택합니다.
- DAS: 채널 진폭과 위상을 유지해 coherent sum power를 계산하는 기준선입니다. CPU와 WebGPU를
지원하고
rawMap.scale은power입니다. - DAS-PHAT: 각 STFT 성분의 크기를 정규화하고 위상을 합산합니다. 채널 gain 차이에 덜
민감한 비교용이며 CPU와 WebGPU를 지원합니다. 결과는 무차원
score입니다. - GCC-PHAT: 기준 마이크와 나머지 마이크의 PHAT 상관에서 기하학적 TDOA를 평가합니다. 현재 CPU 전용이므로 Auto는 CPU를 선택하고 WebGPU 강제는 선택할 수 없습니다. 각 band가 8개 미만의 FFT bin을 포함하면 협대역 상관이 불안정할 수 있다는 경고가 표시됩니다.
- MUSIC: CPU에서 표준 Schmidt narrowband MUSIC의 근거리 구면파 direct-path manifold를 계산합니다. Fixed K 또는 Wax–Kailath AIC/MDL을 선택하며, band마다 아날로그 FFT-grid 가설 하나만 허용합니다.
PHAT score는 위치 확률이나 음향 power가 아닙니다. 네 알고리즘 모두 같은 scan grid에 응답 map을 만들지만, 진폭 보존 여부와 실패 양상이 다르므로 같은 Scene·Array·band로 비교하세요. GCC-PHAT raw score는 pair·band coefficient·IFFT 크기를 정규화한 0–1 양의 상관 응답이라 scan 범위나 마이크 수에 따른 단순 scale 변화는 피하지만, 확률이나 다른 알고리즘과 공통인 confidence는 아닙니다.
MUSIC raw q는 noise-subspace projection이고 작은 값이 좋은 가설입니다. 화면 heatmap과 peak
threshold는 reciprocal P=1/q의 scan 내 표시값 P/Pmax를 사용합니다. 둘 다 확률·confidence
또는 신뢰구간이 아닙니다. flat q는 위치를 임의 선택하지 않고 식별 불가로 표시합니다.
- Auto (GPU→CPU): 권장. WebGPU를 먼저 시도하고 adapter/device 부재나 지원되는 장치 한계가 있으면 CPU로 계속합니다. 라이브 준비에서는 첫 fallback 뒤 남은 frame이 같은 CPU analysis plan을 재사용하므로 GPU 실패를 매 frame 반복하지 않습니다. GCC-PHAT에서는 **Auto (CPU)**로 표시됩니다.
- WebGPU 강제: DAS와 DAS-PHAT를 GPU에서만 실행하며 운용 오류가 나도 CPU로 fallback하지 않습니다.
- CPU 강제: 선택한 알고리즘의 CPU 수치 기준이나 WebGPU가 없는 환경에서 사용합니다.
WebGPU가 감지돼도 실제 장치는 실행 시 확인합니다. 계산 중 계산 취소를 누르면 Worker를 종료하며, 이미 완료된 이전 결과가 있으면 그대로 남습니다.
음향 환경과 마이크 주파수 응답
고급 설정 → 음향 환경에서 다음 preset을 선택합니다.
- 자유음장 · 직접음만: 거리 지연과
1/r감쇠의 기준선 - 흡음된 실내 · 짧은 잔향: 수신점당 최대 17개 sparse path
- 일반 실내 · 균형: 수신점당 최대 19개 sparse path
- 반사 강한 실내: 수신점당 최대 23개 sparse path
실내 preset은 현재 마이크, 정적·trajectory source와 scan corner를 포함하도록 직육면체 room을
자동 추론합니다. 직접음에 여섯 면의 1차 image-source 반사, 결정적 scattering과 tap 수가 제한된
RT60 diffuse tail을 추가합니다. Scene JSON에 사용자 shoebox와 축 정렬
occluders를 넣으면 직접음 감쇠와 최단 corner 우회 회절도 계산합니다. 사용자 설정은
dropdown에 Scene 사용자 설정으로 표시되고 preset 값으로 덮어쓰기 전까지 유지됩니다.
Array의 각 microphone에는 선택적 frequencyResponse를 넣을 수 있습니다.
{
"id": "mic-001",
"position": [-0.225, 0.225, 0],
"frequencyResponse": [
{ "frequencyHz": 100, "gainDb": -8, "phaseDeg": -12 },
{ "frequencyHz": 1000, "gainDb": -0.7, "phaseDeg": -2 },
{ "frequencyHz": 10000, "gainDb": 1.2, "phaseDeg": 8 }
]
}
curve는 합성 microphone channel에 항상 적용됩니다. 마이크 주파수 응답 처리의 기본
측정 curve 적용 + 위치추정에서 역보정은 선택한 CPU 위치추정과 DAS/DAS-PHAT WebGPU
경로에서 알려진 gain/phase를 역보정합니다. 측정 curve 적용 + 보정하지 않음은 합성 응답은
유지하고 역보정만 꺼서 영향을 비교합니다. curve가 없는 마이크는 기존 결과를 유지합니다. 응답 notch를
과도하게 증폭하지
않도록 역보정의 양의 gain boost는 기본 24 dB로 제한하며, 사용자 Experiment JSON의
beamforming.maxCompensationDb에서 0–120 dB로 지정할 수 있습니다.
모델 수식, preset 값, Scene/Array/Experiment 예와 제외 범위는 음향 환경과 마이크 응답 모델을 참고하세요.
Grid, STFT와 대역
50×50은 2,500 points입니다. 이를 1로 보면 100×100은 4배, 200×200은 16배 points를 계산합니다. 처음에는 50×50을 권장합니다. 연산량 줄에는 공통 STFT transform 수와 signal path, distance cache를 표시하고 알고리즘별 위치추정 비용을 다음처럼 분리합니다.
- DAS/DAS-PHAT: scan point × microphone × STFT frame × 선택 bin의 complex MAC
- GCC-PHAT: 기준 마이크 pair별 two-pass cross-spectrum, pair × band inverse FFT와 scan point × pair × band correlation lookup
- MUSIC: hypothesis별 Float64 covariance, Hermitian Jacobi EVD와 scan point × microphone × noise-subspace projection
이는 구현 연산 횟수이지 실행 시간 예측값은 아닙니다. scene 길이, microphone 수, FFT/hop, band 수와 폭, grid 및 CPU/GPU에 따라 실제 시간이 달라집니다.
각 band는 id, 최소/최대 Hz와 overlay 색을 가집니다. Nyquist 위 band도 허용되며 legend에 실제로
접힌 ADC FFT range가 표시됩니다. 중복 id나 잘못된 범위 같은 계약 오류는 실행 전에 표시됩니다.
DAMAS와 CLEAN-SC 후처리는 아직 구현하지 않았으며, 실행할 수 없는 비활성
항목은 Camera UI에서 제거했습니다. Result의 processedMaps 계약만 향후 확장을 위해 남아 있습니다.
MUSIC에서는 band가 사용자가 지정한 아날로그 FFT-grid center 하나만 포함해야 합니다. 같은 ADC bin으로 접히는 서로 다른 Nyquist-zone 가설은 별도 band로 만드세요. spectral inversion이면 analog carrier 크기의 공간 위상을 유지하면서 positive-bin coefficient와 calibration/manifold 전체를 켤레 방향으로 계산합니다. signed ADC alias는 orientation만 정합니다. Scene의 tone truth로 alias order를 자동 선택하지 않으며 DC/Nyquist edge는 거부합니다.
**Peak 검출 임계값 (%)**은 최강 local peak의 map 값에 대한 상대 임계값이며 Experiment JSON에 저장됩니다. 기본 25%에서 약한 두 번째 음원이 빠지면 10–20%로 낮추세요. 낮은 값은 더 약한 후보를 살리는 대신 sidelobe를 음원으로 잘못 고를 가능성도 높입니다. 같은 대역의 두 음원이 알고리즘의 main lobe 폭보다 가깝다면 grid만 키우거나 threshold를 낮춰도 하나로 합쳐질 수 있습니다.
Peak 묶기는 raw map을 바꾸지 않고 threshold 위 후보를 표현하는 방식을 고릅니다.
local-max는 각 8-neighbor local maximum, connected-components는 threshold mask의
8-connected component별 weighted centroid, watershed는 local maximum marker 기반 watershed
basin을 사용합니다. 선택한 표준 방식과 threshold는 Experiment와 Result에 기록됩니다.
화면과 배열·알고리즘 비교
- acoustic overlay의 투명도와 표시할 band를 선택할 수 있습니다.
- Ground truth를 켜면 source 위치와 검출 peak를 비교할 수 있습니다.
- 빔 분포는 DAS power의 half-power 또는 PHAT score의 half-maximum 연결 성분을 해당 map 값으로 가중한 공분산으로 계산해 1× RMS 점선과 2× RMS 영역으로 표시합니다. 위치 확률, Gaussian 신뢰구간 또는 측정 불확실성 보정값은 아닙니다.
- 배열 선택에는 채널 수(4·12·48·192·384), aperture 크기(0.12·0.45·1.20 m), rectangular와 Fermat spiral 배치를 분리 비교하는 8개 preset이 있습니다. 같은 scene·scan·STFT에서 연속 실행하면 비교 기록에 배열, 알고리즘, 실제 backend, 위치추정/전체 timing과 평가 요약이 함께 남습니다.
- 입력을 바꾼 뒤 화면에 남은 결과는 이전 실행 snapshot이며 UI가 이전 설정 결과임을 표시합니다.
- Camera에서 거리·음속·seed를 바꾼 Scene과 scan·STFT·band를 바꾼 Experiment는 우측의 각
JSON 저장 버튼으로 보존할 수 있습니다. Experiment의
sceneId/arrayId는 provenance label이며, 현재 입력에 다시 연결한 뒤 실제 실행 ID와 hash가 Result에 기록됩니다. - 전체 기록 JSON은 세션에 남은 배열·알고리즘·backend 비교 요약을
micarrsim.comparison-history문서로 저장합니다.
미저장 Scene·Experiment·Result·비교 기록은 우측 저장 상태에 표시됩니다. 직전 Result를 저장하지 않고 새 실행을 시작하면 교체 여부를 확인하며, 미저장 항목이나 실행 중 계산이 있는 상태에서 페이지를 닫으면 브라우저가 한 번 더 확인합니다.
이동 음원 라이브
Scene source에 두 개 이상의 trajectory keyframe이 있으면 Map 준비가 활성화됩니다.
Builder에서는 시간에 따라 음원 이동과 경로 미리보기 slider로 이 데이터를 만들 수 있습니다.
- 알고리즘, Map rate와 backend를 선택합니다. 처음에는 DAS, 2 Hz와 Auto를 권장합니다.
- Map 준비를 누릅니다. 현재 입력 snapshot을 최대 48개, map당 최대 2,500 points의 짧은 분석창으로 계산합니다.
- 재생 또는 시간 slider로 이동합니다. Heatmap은 이웃한 acoustic map 사이를 보간하고 source 위치는 keyframe 사이를 연속 보간합니다.
각 시간창은 sample 경계에 맞추며 tone 위상, 결정적 noise index와 audio asset의 재생 위치를 원래 Scene 시간에 이어 붙입니다. 한 창 안에서는 중앙 시각의 위치를 고정하는 준정적 근사이므로 Doppler, 창 내부 연속 경로 변화와 실제 마이크 스트림은 지원하지 않습니다. 실제 192채널 장치를 연결하려면 장치의 channel 순서, sample 형식, clock와 전송 API에 맞춘 capture adapter가 별도로 필요합니다.
Result JSON
Result JSON은 검증을 통과한 micarrsim.result 1.1 문서만 저장합니다.
experimentId,arrayId,sceneId,createdAt, 실제algorithm과backend- 실행 입력 전체의 canonical SHA-256인
inputHash signalStats: 정규화 전 peak, 적용 scale, clipped sample 수, 실제 음향 모델과 sparse path 전체·종류별 수와 필수 ideal-ADC sampling provenancetimingMs: 전체, signal generation과localization; 기존 소비자 호환용beamforming은 같은 위치추정 시간을 담는 alias- band별
rawMap: DAS는 선형power, PHAT 계열은 무차원score; 화면용displayMap과 검출peaks - 각 peak의 비보정 half-power/half-maximum 공분산과 RMS ellipse인
beamSpread - 평가 설정과
peakToSidelobeDb,energyInsideTruthRatio,precision,recall,mainLobeWidthM - band별 연속 fold segment, FFT bin-center 선택, DAS/GCC 실제 localization model, 원 carrier 미사용 여부와 alias-equivalent band ID
Tone source는 요청 analog interval 또는 접힌 ADC 주파수의 nearest selected bin을 기준으로 해당 band의 ground truth가 됩니다. Audio asset과 noise source는 임의 spectrum detector를 만들지 않고 모든 band의 ground truth로 평가합니다. Source z가 scan z와 다르면 평면에 투영한 x/y를 사용하므로 UI 경고와 위치 오차를 함께 해석하세요.
해석 한계
신호 모델은 직접 경로의 자유음장과 선택적인 shoebox 희소 근사입니다. shoebox는 1차 반사, deterministic scattering, 축 정렬 occluder의 직접음 감쇠·최단 corner 우회 회절과 제한된 RT60 tail을 포함합니다. 파동 방정식, 고차 반사, 재질별 주파수 의존 흡음, 복잡한 mesh, 바람, Doppler, 센서 self-noise·비선형, ADC·clock과 장착 구조는 포함하지 않습니다. 배열 JSON의 sensitivity/phase/frequency-response calibration은 적용하지만 결과는 상대 배열 비교와 알고리즘 검증용이며 실측 인증을 대신하지 않습니다.
실제 동기식 microphone Float32Array를 Scene 합성 없이 위치추정하려면
실시간 위치추정 코어 포팅의
createLocalizationPlan, localizeMultichannel 또는
createStreamingLocalizer를 사용하세요. portable config의 algorithm으로 같은 네 위치추정을
선택할 수 있습니다. MUSIC은 CPU 전용이며 fixed K 또는 엄격한 가정 아래 AIC/MDL을 사용합니다.
실시간성은 장치에서
processingTimeMs <= deadlineMs와 deadlineMisses·droppedSamples를
측정해 판정해야 합니다.
WebGPU 성능을 별도로 측정하려면 서버 실행 후 http://127.0.0.1:4173/benchmarks/webgpu-scaling.html을 여세요.