Reduce Linux voice capture latency and verify device timing
This commit is contained in:
1 parent
3276204196
commit
7477da42a5
11 files changed
+342
-38
No files matched your search
@@ -382,7 +382,7 @@ LeakSanitizer; LeakSanitizer запускается вне песочницы. M
|
||||
ThreadSanitizer. Изолированный интеграционный запуск:
|
||||
|
||||
```sh
|
||||
python3 tools/chatgui/tests/run_pulse_recovery.py
|
||||
dbus-run-session -- python3 tools/chatgui/tests/run_pulse_recovery.py
|
||||
```
|
||||
|
||||
Итоговый прогон 2026-10-02: сборка `vibechat` успешна, CTest — 11/11,
|
||||
@@ -407,6 +407,101 @@ async-тесты исключены из дальнейших запусков.
|
||||
AEC в длительном реальном звонке этими проверками не подтверждены. Reference
|
||||
охватывает звук этого приложения на том же выходе, согласно выбранному контракту.
|
||||
|
||||
## Период Linux/PulseAudio и сравнительный замер
|
||||
|
||||
`AudioDevice::requestLowLatency()` задаёт запрос 10 мс для capture звонка/рации.
|
||||
Он применяется при каждом открытии, включая recovery и fallback.
|
||||
Остальные backends сохраняют прежние параметры.
|
||||
Общий и отдельный voice output сохраняют прежний период: запрос 10 мс
|
||||
на проверенной системе не снизил измеренную задержку воспроизведения.
|
||||
Кадры AEC/кодека остаются 20 мс; `noFixedSizedCallback` позволяет обслуживать
|
||||
фактические порции backend без дополнительного накопления в miniaudio.
|
||||
|
||||
Это запрос задержки, а не гарантия размера callback. PulseAudio согласует
|
||||
`tlength`, `fragsize`, `minreq`, `maxlength`, `prebuf`; PipeWire также ограничивает
|
||||
quantum и минимальные порции. `AudioDiag` при init выводит внутренний PCM-формат
|
||||
и согласованные параметры в миллисекундах (`-1` — значение по умолчанию).
|
||||
Пересчёт использует внутренние rate/channels/format, а не формат приложения.
|
||||
|
||||
Секундные clock-отчёты содержат `latency_us`/`backend_us` и `block_us` в виде
|
||||
`min/avg/max`. В задержку включены только измеренные timing snapshots;
|
||||
`estimated_blocks`/`measured` позволяют отличить их отсутствие от нулевой задержки.
|
||||
Для времени исполнения callback включать `call=trace`, для состояния AEC —
|
||||
`aec=debug`. Логи агрегируются вне аппаратного callback.
|
||||
|
||||
Ручной режим существующего стенда использует настоящие устройства и голосовые
|
||||
workers, не сохраняет микрофонный PCM и не отправляет его по сети. Выход звонка
|
||||
без удалённого собеседника обслуживается тишиной; акустическое подавление эха
|
||||
этот режим не измеряет. Аргументы: capture frames, playback frames, секунды,
|
||||
необязательный режим `call` (по умолчанию), `radio` или `output`, затем путь лога.
|
||||
Ноль frames оставляет стандартный период backend; override применяется только
|
||||
в тестовом executable, до настоящего `ma_device_init`.
|
||||
|
||||
```sh
|
||||
cmake --build tools/chatgui/build --target test_audio_recovery -j4
|
||||
tools/chatgui/build/test_audio_recovery --latency 960 0 60 > /tmp/audio-baseline.log 2>&1
|
||||
tools/chatgui/build/test_audio_recovery --latency 480 0 60 > /tmp/audio-capture10.log 2>&1
|
||||
tools/chatgui/build/test_audio_recovery --latency 960 480 60 > /tmp/audio-playback10.log 2>&1
|
||||
tools/chatgui/build/test_audio_recovery --latency 480 480 60 > /tmp/audio-both10.log 2>&1
|
||||
```
|
||||
|
||||
Запуски последовательные: несколько потоков могут менять общий quantum сервера.
|
||||
Сравнивать одинаковые маршруты и нагрузку, отдельно от старта/остановки и после
|
||||
стабилизации адаптивного PCM-резерва. Проверять backend latency, возраст первого
|
||||
сэмпла перед готовым TX-кадром, очередь после mix, starvation, holes, потери PCM,
|
||||
AEC reference и событий диагностики. Затем повторить baseline и проверить
|
||||
выбранный вариант под нагрузкой. Меньший возраст PCM в capture callback сам по
|
||||
себе не доказывает такой же выигрыш до кодирования: worker собирает кадры 20 мс.
|
||||
|
||||
`test_voice_audio_io` дополнительно проверяет порции по 256 samples: порядок PCM,
|
||||
временные метки, границы mute/PTT и позицию частичного playback. AEC проверяется
|
||||
при разных порциях capture/reference (256/480 и 480/256) с противофазным stereo
|
||||
reference. Очереди по-прежнему ограничены числом событий; уменьшение периода
|
||||
не увеличивает их ёмкость в миллисекундах.
|
||||
|
||||
Сравнение 2026-10-15 на встроенном HDA, PipeWire 1.6.2, 48 кГц. Каждый вариант
|
||||
работал 60 секунд; таблица содержит средние по callback/кадрам после 45 секунд
|
||||
прогрева (PCM-резерв к этому моменту уменьшился до одного блока).
|
||||
|
||||
| Запрос capture / playback | Capture backend, мс | Первый сэмпл готового TX-кадра, мс | Playback backend, мс | PCM после mix, мс |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| 20 мс / default 25 мс | 30,69 | 34,53 | 16,32 | 18,67 |
|
||||
| 10 мс / default 25 мс | 16,02 | 29,79 | 16,15 | 18,67 |
|
||||
| 20 мс / 10 мс | 31,51 | 34,97 | 18,09 | 24,00 |
|
||||
| 10 мс / 10 мс | 16,13 | 29,66 | 18,46 | 24,00 |
|
||||
|
||||
Изменение capture даёт около 14,7 мс на границе backend и около 4,7 мс перед
|
||||
передачей полного кадра в голосовой стек. Для playback сервер согласовал
|
||||
`tlength=16ms`, `minreq=5.333ms` при запросе 10 мс; callback уменьшился с 512
|
||||
до 256 samples, но выигрыша по задержке не получилось. Поэтому в рабочем коде
|
||||
изменён только capture. Значения в столбцах не следует складывать как независимые
|
||||
участки общей задержки: capture backend входит в возраст TX-кадра, а очередь после
|
||||
mix снята уже после извлечения текущего выходного блока из очереди.
|
||||
|
||||
В этих четырёх прогретых окнах не было потерь capture/reference PCM, выходного
|
||||
starvation, backend underrun/overflow или потери событий диагностики.
|
||||
Отдельные отсутствующие AEC references были и в baseline (4 кадра за окно),
|
||||
и в остальных вариантах (4–5). Это существующее ограничение привязки reference,
|
||||
а не проверка акустического качества. Первоначальный output starvation и
|
||||
временное увеличение PCM-резерва учитываются отдельно от стабильного окна.
|
||||
|
||||
Повтор baseline дал 30,76 мс capture backend и 34,99 мс возраста TX-кадра.
|
||||
Двухминутный прогон выбранного capture 10 мс под нагрузкой четырёх CPU-процессов
|
||||
дал после прогрева 15,81 и 28,55 мс соответственно; PCM после mix — 18,67 мс.
|
||||
Потерь PCM, backend underrun/overflow и потери событий диагностики в этом окне
|
||||
не было. За 75 секунд окна зарегистрировано 25 отсутствующих AEC references.
|
||||
Отдельный минутный прогон рации: capture backend в среднем 15,48 мс, без потерь PCM.
|
||||
|
||||
Сборка `vibechat` и 6 аудиотестов прошли. Изолированный интеграционный тест
|
||||
подтвердил объединение выходных маршрутов и восстановление capture/playback после
|
||||
перезапуска тестового PulseAudio. Запускать весь стенд через `dbus-run-session`,
|
||||
чтобы имя его PulseAudio не конфликтовало с сервером пользовательской сессии.
|
||||
В fixture перед `radio_audio_init` создаётся `radio_instance`, освобождаемый после
|
||||
`radio_audio_destroy`; это исключает ложную ошибку регистрации mute callback.
|
||||
Полный `check.sh` вне sandbox: 156/156, 9/9 proxy-интеграций, burst и load — PASS.
|
||||
В sandbox сетевые тесты не проходят из-за запрета сокетов; этот запуск не является
|
||||
проверкой сетевых регрессий.
|
||||
|
||||
## Референсы
|
||||
|
||||
Первичные исходники и документация просмотрены 2026-10-01; ссылки на master могут
|
||||
|
||||
Reference in new issue
Block a user