Files
micarrsim/docs/acoustic-model.md
T

183 lines
7.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 음향 환경과 마이크 응답 모델
micarrsim의 음향 합성은 마이크 어레이 배치와 위치추정 알고리즘의 상대 성능을 빠르게 비교하기
위한 모델이다. ADC나 마이크 전자회로까지 재현하는 하드웨어 시뮬레이터가 아니며, 자유음장과
계산량이 제한된 실내 희소 경로 근사 중 하나를 선택한다.
## 신호 처리 범위
Snapshot 한 번의 처리 순서는 다음과 같다.
1. tone, noise 또는 audio asset으로 음원 신호를 만든다.
2. 음원과 각 마이크 사이의 직접음 또는 희소 multipath 전달함수를 만든다.
3. 마이크별 `sensitivityDb`, `phaseOffsetDeg`와 `frequencyResponse`를 수신 신호에 적용한다.
4. 합성된 동기식 다채널 신호를 STFT하고 conventional DAS map을 계산한다.
5. 설정에 따라 알려진 마이크 응답을 DAS에서 역보정하고 peak와 평가 지표를 구한다.
Scene의 `acoustics`를 생략하거나 `model: "free-field"`로 지정하면 기존 직접음 결과를
유지한다. `model: "shoebox"`는 직육면체 방 안에서 경로 수가 제한된 근사를 추가한다.
## 자유음장
음원과 마이크 사이 거리 `r`, 음속 `c`에 대해 직접음의 지연은 `r / c`, 진폭은
최소 거리 clamp를 적용한 `1 / r`이다. 분수 sample 지연은 zero-padded FFT의 주파수 영역
위상 이동으로 계산한다.
이 모델은 반사가 거의 없는 조건의 기준선과 배열 자체의 aperture·형상·대역 효과를 비교할 때
적합하다.
## Shoebox 희소 경로 근사
`shoebox` 모델은 source–microphone 쌍마다 다음 경로만 만든다.
- 직접음 1개. 축 정렬 occluder와 교차하면 `transmissionDb`만큼 감쇠한다.
- 방의 여섯 면마다 최대 1개의 1차 image-source 반사.
- 반사 에너지의 일부를 0.2–2 ms의 결정적 지연으로 나누는 scattering 경로.
- 직접음을 막는 occluder마다 여덟 corner 중 최단 우회 거리로 만든 회절 경로 1개.
- `tapCount`로 수를 제한하고 RT60에 걸쳐 -60 dB로 감쇠하는 결정적 diffuse tail.
같은 Scene seed와 source/microphone id에서는 scattering과 tail이 재현된다. 모든 희소 경로는
source–microphone 쌍의 주파수 전달함수 하나로 먼저 합쳐지고 IFFT는 한 번만 수행된다. 경로 위상은
recurrence로 갱신하고 1,024 bin마다 다시 고정해 bin마다 삼각함수를 반복하지 않는다.
Scene JSON의 사용자 설정 예는 다음과 같다.
```json
{
"acoustics": {
"model": "shoebox",
"room": {
"min": [-3.0, -2.5, -0.5],
"max": [3.0, 2.5, 4.0]
},
"reflections": {
"order": 1,
"wallGainDb": -8,
"perWallDb": {
"zMin": -14
},
"scattering": 0.25
},
"diffuseReverb": {
"enabled": true,
"rt60Seconds": 0.4,
"gainDb": -20,
"tapCount": 6
},
"occluders": [
{
"id": "screen",
"min": [-0.4, -0.1, 0.6],
"max": [0.4, 0.1, 1.8],
"transmissionDb": -18,
"diffractionGainDb": -12
}
]
}
}
```
`room`은 shoebox에서 필수다. 정적 source, trajectory keyframe과 occluder는 room 안에 있어야
하며 occluder id는 중복될 수 없다. 사용자 설정에서도 마이크 좌표가 room 안에 놓이도록 구성해야
1차 반사가 생성된다.
## Camera 환경 preset과 비용
Camera의 **고급 설정 → 음향 환경**은 현재 geometry 전체가 들어가도록 room을 자동 추론하고 다음
preset을 적용한다.
| 선택 | 벽 gain | scattering | RT60 / tail gain / taps | 수신점당 최대 경로 |
| --- | ---: | ---: | ---: | ---: |
| 자유음장 | — | — | — | 1 |
| 흡음된 실내 | -14 dB | 0.15 | 0.2 s / -26 dB / 4 | 17 |
| 일반 실내 | -8 dB | 0.25 | 0.4 s / -20 dB / 6 | 19 |
| 반사 강한 실내 | -4 dB | 0.40 | 0.8 s / -14 dB / 10 | 23 |
표의 상한은 직접음 1개, 반사 6개, scattering 6개와 tail tap 수를 합한 값이다. 사용자 occluder는
각 source–microphone 직접 경로를 실제로 막을 때 하나씩 추가된다. 대략적인 합성 경로 예산은
`음원 수 × 마이크 수 × 수신점당 최대 경로`다. Camera는 실행 전에 이 예산을 표시한다.
반사·tail을 늘리면 beamforming의 `O(scan points × microphones × selected bins × STFT frames)`
뿐 아니라 신호 합성의 전달함수 누산도 늘어난다. 처음에는 50×50 grid와 자유음장으로 기준선을
만들고, 같은 입력에서 preset을 하나씩 바꾸어 비교하는 것이 좋다.
## 마이크 주파수 응답
각 마이크에는 2–64개의 측정점을 지정할 수 있다. `frequencyHz`는 0–1,000,000 Hz에서
중복 없이 오름차순이어야 하며 `gainDb` 범위는 -120–120 dB, 선택적 `phaseDeg` 범위는
-180–180°다.
```json
{
"id": "mic-001",
"position": [-0.225, 0.225, 0],
"sensitivityDb": 0.6,
"phaseOffsetDeg": -1.5,
"frequencyResponse": [
{ "frequencyHz": 100, "gainDb": -8.0, "phaseDeg": -12 },
{ "frequencyHz": 1000, "gainDb": -0.7, "phaseDeg": -2 },
{ "frequencyHz": 8000, "gainDb": 2.1, "phaseDeg": 7 },
{ "frequencyHz": 20000, "gainDb": -5.0, "phaseDeg": 20 }
]
}
```
측정점 사이 gain dB와 phase는 선형 보간한다. phase는 ±180° 경계에서 가장 짧은 방향으로
보간하고 측정 범위 밖에서는 가장 가까운 끝점 값을 유지한다. 합성기는 이 curve를 실제 마이크
채널에 적용한다.
Experiment에서 `beamforming.compensateFrequencyResponse`를 생략하거나 `true`로 두면
CPU와 WebGPU DAS가 선택 FFT bin에서 알려진 curve의 역 gain/phase를 적용한다. 응답 notch의
무제한 역보정은 noise까지 크게 증폭할 수 있으므로 양의 보상 boost는
`beamforming.maxCompensationDb`로 제한하며 기본값은 24 dB다. 허용 범위는 0–120 dB이고
응답 peak를 줄이는 attenuation과 phase 보상은 이 boost 상한에 의해 잘리지 않는다.
```json
{
"beamforming": {
"algorithm": "das",
"backend": "auto",
"minimumDistance": 0.01,
"normalization": "peak",
"dynamicRangeDb": 45,
"compensateFrequencyResponse": true,
"maxCompensationDb": 24
}
}
```
Camera의 **마이크 주파수 응답 처리**에서 **측정 curve 적용 + 보정하지 않음**을 고르면 합성에는
curve가 남고 DAS 역보정만 꺼진다. 같은 배열에서 보정 유무의 robustness를 비교할 때 사용한다.
curve가 없는 마이크는 0 dB, 0°로 취급한다.
## 결과에서 확인할 값
Result `signalStats`에는 다음 선택 필드가 들어간다.
- `acousticModel`: `free-field` 또는 `shoebox`
- `acousticPathCount`: 실제 합성에 사용한 전체 경로 수
- `acousticPathCounts`: `direct`, `reflection`, `scattering`,
`diffraction`, `diffuse` 종류별 수
같은 입력과 seed에서 환경 preset만 바꿨다면 이 값과 위치 오차·precision/recall·PSR을 함께
비교할 수 있다.
## 정확도 범위와 제외 사항
이 구현은 FDTD/FEM/BEM이나 room impulse response 측정치를 대신하지 않는다. 다음 항목은
계산하지 않는다.
- 파동 방정식과 고차 반사
- 재질별 주파수 의존 흡음과 복잡한 mesh 산란
- edge 형상·파장에 따른 물리 회절
- 음원과 마이크 지향성, 바람, Doppler
- 절대 음압/SPL, 마이크 self-noise와 비선형 왜곡
- preamp, anti-alias filter, ADC quantization, channel clock jitter·drift
- 실제 장착 구조와 마이크 위치 공차
따라서 preset의 RT60이나 wall gain은 특정 방을 인증하는 값이 아니라 배열과 DAS가 multipath에
얼마나 민감한지 비교하는 조건이다. 실제 장치 성능을 평가할 때는 같은 Array/scan/band 설정으로
동기식 실측 채널을 [실시간 위치추정 코어](realtime-porting.md)에 입력하고 합성 결과와 나란히
비교해야 한다. 주파수 응답 curve만으로 noise floor, distortion, ADC와 clock 오차까지 모사되지는
않는다.