diff --git a/doc/tasks.md b/doc/tasks.md index 49fc0e1f..d6ff0231 100644 --- a/doc/tasks.md +++ b/doc/tasks.md @@ -6,14 +6,20 @@ [ ] **Снижение минимального запаса JB звонка до 20мс** — 15.10.2026: Нижняя граница общего call_jitter изменена с 60 до 20мс; адаптация по 10-секундному окну сохранена. - Изменение не установлено: test_call_jitter обнаружил недостачи PCM даже при ровной доставке после догона. - Диагностика: tick=841, PCM=384/480, depth_before=37мс, encoded=0, processing=30мс, reserve=20мс, spread=0. - Регулятор считает внутреннее накопление SoundTouch доступным запасом и ускоряет до нехватки готового PCM. - Требуется отдельно учитывать сетевой запас 20мс и необходимое накопление обработки при управлении темпом/старте. - Порог SoundTouch зависит от tempo; проверять его по параметрам движка, а не возвращать скрытый минимум 60мс. - Дальше: тест ровной доставки для pull 5/10/20мс, старт/возобновление, рост и спад джиттера, burst и A/V clock. - test_call_video_clock проходит; test_call_jitter намеренно сохраняет строгую проверку отсутствия недостач. - По правилу AGENTS.md реализация остановлена на обнаруженной нестыковке; рабочие приложения остались прежними. + Добавлен общий модуль src/call/call_delay.h/.cpp: direct PCM с удалением одиночных сэмплов (<=2%) + и SoundTouch (<=1.6), вход/выход при избытке 120/40мс, ограниченная история исходного PCM. + Обе границы перехода точные: контекст на входе отбрасывается только до уже выданной позиции; + на выходе выдаётся весь готовый Copy, затем сохранённый raw-хвост. flush/сброс аудиочасов не используются. + Прямой режим только ускорением доводит разность входа/выхода до целого числа кадров 960 сэмплов; + учитывает тишину устройства, не расходует сетевой резерв на коррекцию. Ожидания пересборки кадров нет. + JB начинает/возобновляет PCM при наличии reserve + запрошенный блок; Opus/сетевое окно остались в JB. + Регрессия ровной доставки с запасом 20мс исправлена без ослабления проверки отсутствия underrun. + test_call_delay проверяет каждый сэмпл по Copy/Mix, 20 фаз доставки, 20 начальных пауз, + 200 границ повторного переключения, хвост без flush, изменяемые pull 1..8192 сэмплов. + test_call_jitter проверяет перебой 80мс, рост/спад резерва и отсутствие новых underrun после восстановления. + Семь профильных C++-тестов и полный check.sh (ядро/proxy/burst/load) проходят; desktop/APK собраны, + Android unit-тесты проходят. В периодический лог JB добавлены режим, точный tempo, фаза и число удалений. + Осталось установить и проверить живой звонок: субъективный звук, реальный запас и A/V на двух устройствах. [x] **Завершение звонка и видеопорта после обрыва транспорта** — 15.10.2026: Трасса test_call доказала потерю HANGUP при смене эпохи сигналинга: router reset удалял старую очередь. diff --git a/src/call/call_delay.h b/src/call/call_delay.h index 82ddd77a..3cbbacb9 100644 --- a/src/call/call_delay.h +++ b/src/call/call_delay.h @@ -5,6 +5,12 @@ * Reset SoundTouch наружу не выходят. Владелец сам сбрасывает карту при reset(). * queued — ещё не декодированный вход, reserve — сетевой запас, оба в сэмплах. * Переключение сохраняет хвост исходного PCM; ускорение учитывается отдельно. + * Вход в SoundTouch при избытке >=120мс, выход <=40мс; низкий запас дополнительно + * принуждает выход. Прямой режим ускоряет не более чем на 2%, без замедления. + * Его цель — целая разность входных/выходных кадров по 960 сэмплов. Нижняя огибающая + * запаса за 150..200мс подавляет пилу пакетов; удаление останавливается точно на цели. + * При нехватке входа ускорение не расходует reserve: фазу доводим после восстановления. + * Это выравнивание границ PCM, не синхронизация физических часов двух аудиоустройств. * Внутренние очереди ограничены, размеры pull произвольные, heap в нашем hot path нет. */ #ifndef CALL_DELAY_H #define CALL_DELAY_H @@ -19,9 +25,9 @@ public: enum class Mode { Direct, Stretch, Drain }; struct Stats { Mode mode = Mode::Direct; - double tempo = 1, pending = 0; + double tempo = 1, pending = 0; // Заданный темп и ещё не выданная длительность исходного PCM в сэмплах. uint64_t cuts = 0, entered = 0, exited = 0; - unsigned phase = 0; // Ошибка относительно 20мс выхода; 0 — границы совпадают. + unsigned phase = 0; // В Direct: ошибка относительно 20мс выхода; 0 — границы совпадают. }; CallDelay(Input input, void* input_context, soundtouch::SourceCallback source, void* source_context); CallDelay(const CallDelay&) = delete;