Вы пытаетесь выполнять потоковую передачу в реальном времени. Давайте посмотрим на бюджет задержек на протяжении всего процесса.
Во-первых, вы используете 512-байтовые буферы - при условии, что сэмплы равны float
с, а частота сэмплирования 44.1k
, вы обрабатываете 128
сэмплов каждый раз, это дает период буфера ~2.9ms
.
Лучшее, что вы можете получить, это ~7.5ms
при этом размере буфера.
Поток управления:
1: устройство ввода звука генерирует сэмплы и сохраняет их в буфере. После предварительно определенного количества выборок операционная система прерывается для обслуживания аудио. Этот период буфера может быть значительно длиннее, чем 128 выборок. Это T1
2: Операционная система планирует запуск процесса аудио-демона. Он ждет S1
перед запуском
3: Демон аудио работает, обрабатывает аудио, записывает его в буфер и сообщает операционной системе, что сэмплы доступны для чтения. Это время пренебрежимо мало.
4: операционная система планирует запуск процесса ввода, разблокируя вызов на audioInput.read(buffer, 0, buffer.length);
. Он ждет S2
, прежде чем назначить.
5: Вы звоните System.out.println()
. Это потенциально блокирует - особенно когда вы пишете в него ~ 350 раз в секунду - возможно, пока не будет запланирован другой не связанный процесс. S3
6: UDP записывается в сетевой сокет. ОС может поставить его в очередь для передачи - что, вероятно, произойдет через несколько минут
7: Транзит по сети. T2
Принимающая сторона в значительной степени противоположна вышеприведенному.
Таким образом, общая задержка составляет
2 * (T1 + S1 + S2 + S3 + T2)
Я полагаю, что большая часть вашей задержки - это период аппаратной буферизации как при отправке, так и при получении - T1
. Если вы получите намного ниже, чем 10ms
, S1,S2,S3
начнут становиться значимыми.
Примечание:
S1
, S2
являются задержками планирования работы и зависят от загрузки системы и политики планировщика. Обработчики рендеринга аудио обычно запускаются с приоритетом в реальном времени.
- Вы можете устранить
S3
, не войдя в консоль. Эта задержка особенно непредсказуема.
- Время выполнения Java может налагать некоторые скрытые затраты времени выполнения (например, GC). Это будет ограничивающим фактором для надежного звука с низкой задержкой.
Рецепт действительно с низкой задержкой:
- Реализация на C или C ++
- Нет выделения памяти, логирование в цикле рендеринга
- Закрепить стопку и кучу страниц, чтобы предотвратить их замену
- Запуск потоков рендеринга аудио с приоритетом планирования в реальном времени.
- Структуры данных без блокировки для предотвращения инверсии приоритетов.