# 🎤 Теория: цифровой звук и MEMS-микрофон INMP441

## 1. Что такое звук физически

Звук — это волна давления воздуха, бегущая от источника. Когда что-то колеблется (голосовые
связки, динамик, ладони при хлопке), оно попеременно сжимает и разрежает воздух рядом с собой,
и эта область сжатия/разрежения распространяется дальше со скоростью ~343 м/с (при 20°C).

Волну описывают две главные величины:
- **Частота** (Гц) — сколько раз в секунду давление колеблется туда-обратно. Определяет
  *высоту* звука: низкий бас — десятки-сотни Гц, свист — килогерцы.
- **Амплитуда** — насколько сильно меняется давление относительно атмосферного. Определяет
  *громкость*.

Человеческое ухо слышит примерно 20 Гц — 20 000 Гц. INMP441 по даташиту рассчитан на
диапазон **60 Гц — 15 кГц** — уже, чем весь слышимый диапазон, но с запасом покрывает речь
(основная энергия голоса — 100 Гц — 4 кГц).

## 2. Микрофон INMP441 — как звук становится числом

Внутри INMP441 — MEMS-мембрана (микроскопическая кремниевая пластина), которая физически
прогибается под давлением звуковой волны. Это механическое смещение сразу же, прямо на
кристалле микрофона, оцифровывается встроенным 24-битным АЦП (аналого-цифровым
преобразователем) — в отличие от аналоговых электретных микрофонов, где сырой аналоговый сигнал
нужно было бы ещё передавать по проводу до АЦП на плате, рискуя подхватить наводки.

Результат — поток 24-битных чисел, выходящих по цифровому протоколу **I2S** (Inter-IC Sound):
никакого аналогового сигнала наружу микрофона вообще не выходит.

## 3. Протокол I2S: три провода, одна идея

I2S передаёт поток аудиосэмплов тремя линиями одновременно:

| Линия | Роль |
| :--- | :--- |
| **SCK** (BCLK) | Тактовый сигнал — один импульс на каждый бит данных |
| **WS** (LRCLK) | Word Select — high/low, показывает, какой сейчас слот: левый или правый |
| **SD** (DOUT) | Сами биты данных, синхронно с SCK |

Конфигурация этих трёх линий в коде — [`Inmp441::begin()`](src/Inmp441.cpp#L5-L37): драйвер
создаёт I2S-канал в режиме приёмника (`I2S_ROLE_MASTER` — ESP32 сам генерирует тактовый сигнал
для микрофона) и описывает распиновку в `i2s_std_config_t::gpio_cfg`
([Inmp441.cpp:16-24](src/Inmp441.cpp#L16-L24)).

INMP441 не имеет входа для звука — только выход, поэтому `dout` в конфигурации ESP32 не
используется ([I2S_GPIO_UNUSED](src/Inmp441.cpp#L20)), а данные идут только по `din`.

### Зачем нужен L/R и что такое "слот"

I2S исторически проектировался для *стерео*: в каждом кадре WS отводит время сначала левому
каналу, потом правому. INMP441 — моно-микрофон, но должен как-то вписаться в этот стереоформат,
поэтому пин L/R говорит ему, в какой из двух слотов класть свои данные (см. подробности и
таблицу — [WIRING.md](WIRING.md#lr-выбор-канала)). В коде это выбирает
[`slot_mask`](src/Inmp441.cpp#L26).

## 4. Частота дискретизации и теорема Найквиста

АЦП не пишет непрерывную кривую — он берёт мгновенные "снимки" давления через равные
промежутки времени. Число снимков в секунду — **частота дискретизации**
(`sample_rate` в [Inmp441.h:24](include/Inmp441.h#L24), по умолчанию 16000 Гц).

**Теорема Котельникова-Найквиста**: чтобы правильно восстановить волну частотой *f*, нужно
делать не меньше *2f* снимков в секунду. При 16000 Гц дискретизации корректно различимы частоты
до **8000 Гц** (частота Найквиста) — этого достаточно для речи (до ~4 кГц), но недостаточно,
например, для верхних гармоник тарелок ударной установки (может доходить до 15-20 кГц).
Если в звуке есть частоты выше половины частоты дискретизации, они не пропадают, а искажённо
"складываются" обратно в слышимый диапазон — это называется **алиасинг** (aliasing).

## 5. От 24 бит к 16: что делает `toSample16()`

INMP441 кладёт данные в 32-битное слово так: 24 значащих бита выровнены по старшим разрядам,
младшие 8 бит — нули (формат `I2S_DATA_BIT_WIDTH_32BIT` с MSB-выравниванием, настроено в
[Inmp441.cpp:15](src/Inmp441.cpp#L15)). Схематично 32-битное слово выглядит так:

```
[ 24 бита данных микрофона ][ 8 нулевых бит ]
 биты 31..8                  биты 7..0
```

[`Inmp441::toSample16()`](include/Inmp441.h#L38-L45) сдвигает слово на 16 бит вправо, оставляя
старшие 16 бит исходных данных:

```
raw_word >> 16  →  [ 16 старших бит из 24 ]
```

Младшие 8 бит из 24 при этом отбрасываются — компонент жертвует частью точности (16 бит вместо
24), чтобы формат сразу подходил для Serial Plotter Arduino IDE (который понимает `int16_t`) и
для стандартного 16-битного WAV/PCM, с которым работает большинство простых Python-библиотек.
16 бит дают 65536 уровней амплитуды — с большим запасом достаточно для учебной визуализации.

## 6. Почему нет абсолютных дБ SPL

В профессиональной акустике громкость измеряют в **дБ SPL** (Sound Pressure Level) —
абсолютной шкале относительно порога слышимости (20 мкПа). Даташит INMP441 приводит
чувствительность −26 дБFS при 94 дБ SPL (тон 1 кГц, эталонный источник) — то есть *у
конкретного откалиброванного экземпляра* эти два значения связаны.

Этот компонент **не выполняет такую калибровку** — ни один экземпляр модуля не проверялся
эталонным источником звука. Поэтому во всех графиках и в тестовом стенде используется только
**относительная шкала**:
- **LSB** (least significant bit) — то же самое "число из АЦП", 16-битное значение от −32768 до
  32767 после `toSample16()`.
- **дБFS** (dB Full Scale) — логарифмическая шкала относительно максимума этой 16-битной шкалы
  (32767 = 0 дБFS). Используется в [`main.cpp`](src/main.cpp#L80-L97) для метра громкости и
  показывает, насколько сигнал близок к клиппингу (переполнению), а не абсолютную громкость в
  паскалях.

Если понадобится настоящий дБ SPL — потребуется калибровка каждого физического экземпляра по
эталонному источнику известной громкости (например, калибратору 94 дБ SPL/1 кГц) и корректировка
формулы в коде под измеренное смещение.

## 7. Спектр и преобразование Фурье

Осциллограмма показывает звук *во времени* — как давление меняется мгновение за мгновением. Но
любой сложный звук на самом деле состоит из наложения нескольких простых синусоид разной
частоты и амплитуды (гармоник). **Преобразование Фурье** — математический инструмент,
раскладывающий сложную волну на эти составляющие: превращает график "амплитуда от времени" в
график "амплитуда от частоты" — **спектр**.

- Чистый тон (свист, камертон) даёт один острый пик в спектре.
- Голос даёт несколько пиков — **форманты**, определяемые резонансами голосового тракта; их
  расположение отличает гласные звуки друг от друга и делает голос каждого человека узнаваемым.
- Хлопок или стук — короткий импульс во времени превращается в широкий, размазанный по всем
  частотам спектр (чем короче импульс во времени, тем шире его спектр — фундаментальное
  свойство преобразования Фурье).

Python-визуализатор ([tools/visualizer.py](tools/visualizer.py)) считает спектр функцией
`numpy.fft.rfft` (быстрое преобразование Фурье для вещественного сигнала) и рисует три
синхронных графика: осциллограмму, спектр текущего окна и **спектрограмму** — как спектр
меняется кадр за кадром, то есть третье измерение (время) добавляется к паре
"частота-амплитуда" через цвет.

## 8. Почему за звуком не нужно "следить" постоянно: DMA

`i2s_channel_read()` в [`Inmp441::read()`](src/Inmp441.cpp#L41-L52) не "слушает" линию SD
напрямую в момент вызова — ESP32 непрерывно копирует поступающие биты в буфер памяти через
**DMA** (Direct Memory Access) в фоне, независимо от того, чем занят процессор в этот момент.
`read()` лишь забирает уже накопленные готовые сэмплы из этого буфера (и ждёт новых до
`timeout_ms`, если буфер пуст — поэтому вызов всё же блокирующий, просто недолго). Это значит,
что даже если `loop()` на десятки миллисекунд задержится на `Serial.print()`, звук не
потеряется — он подождёт в DMA-буфере, пока тот не переполнится.
