# Акустика помещений — `$.audio.room`

Реверберация по зонам: комната, улица, тоннель звучат по-разному. Подсистема
считает, в какой зоне слушатель и источник, и подбирает параметры реверба.

```js
$.audio.room.define('bunker', { size: 12, material: 'concrete', wet: 0.7 });
$.audio.room.zone({ x: 0, y: 0, w: 400, h: 300, room: 'bunker' });
const p = $.audio.room.at(hero.x, hero.y);      // параметры для точки
```

---

## 1. Методы и помощники

| Вызов | Смысл |
|---|---|
| `$.audio.room.define(name, spec)` | описать помещение (`size`, `material`, `wet`, …) |
| `$.audio.room.zone(rect)` | назначить помещение области мира |
| `$.audio.room.at(x, y)` | параметры реверба в точке |
| `$.audio.room.reset()` | сбросить зоны и описания |

Чистые функции (их проверяет юнит-тест): `roomVolume(spec)`, `rt60(spec)`,
`reverbForZone(...)`, `zoneAt(zones, x, y)`, `obstacleMuffle(...)`.

`MATERIALS` — таблица материалов с поглощением; `PX_PER_METER` — масштаб мира.

## 2. Как считается

* **объём** — из размера помещения, **RT60** — по объёму и поглощению
  материала (формула Сэбина);
* **препятствия** приглушают звук: `obstacleMuffle` учитывает стены между
  источником и слушателем (список отрезков);
* параметры применяются к каналам `$.sound`, а не к каждому файлу.

## 3. Ограничения

* **одна зона на точку**: пересекающиеся зоны выбираются по порядку, «смеси»
  двух помещений нет;
* **нет окклюзии по геометрии**: `obstacleMuffle` работает по отрезкам, которые
  вы ему дали, а не по всему миру;
* **порталов и проёмов нет**: звук не «течёт» через дверь отдельным путём;
* **реверб один на кадр**: все источники слышат одно помещение (то, где
  слушатель);
* **нет отражений и задержек**: только общий реверб, без ранних отражений.
