Быстрый аудиовход/Выход
-
21-08-2019 - |
Вопрос
Вот что я хочу сделать:
Я хочу разрешить пользователю передавать моей программе некоторые звуковые данные (через микрофонный вход), затем удерживать их в течение 250 мс, затем выводить обратно через динамики.
Я уже сделал это, используя Java Sound API.Проблема в том, что это довольно медленно.С момента создания звука до момента, когда звук снова раздастся из динамиков, проходит как минимум около 1-2 секунд, и я еще даже не пытался реализовать логику задержки.Теоретически задержки быть не должно, но она есть.Я понимаю, что вам нужно подождать, пока звуковая карта заполнит свой буфер или что-то в этом роде, и размер сэмпла и частота дискретизации имеют к этому какое-то отношение.
Мой вопрос заключается в следующем:Должен ли я продолжить путь Java, пытаясь сделать это?Я хочу сократить задержку примерно до 100 мс, если это возможно.Есть ли у кого-нибудь опыт использования драйвера ASIO с Java?Предположительно, это быстрее..
Кроме того, я специалист по .NET.Имеет ли смысл это делать с .Вместо этого NET?А как насчет C ++?Я ищу подходящую технологию для использования здесь и, возможно, хороший пример того, как читать / записывать в аудиопотоки ввода / вывода, используя предложенную вами технологическую платформу.Спасибо за вашу помощь!
Решение
Я использовал JavaSound в прошлом и нашел его удивительно ненадежным (и он постоянно меняется между выпусками виртуальной машины).Если вам нравится C #, используйте его, просто используйте DirectX API.Вот пример выполнения того, что вы хотите сделать, используя DirectSound и C #.Вы могли бы использовать плагины эффектов для выполнения вашего 250-миллиметрового эха.
Другие советы
Возможно, вы захотите заглянуть в ДЖЕК, аудио API, предназначенный для обработки звука с низкой задержкой.Кроме того, Google выдает это отличная презентация [PDF] об использовании JACK с Java.
Теоретически задержки быть не должно, но она есть.
Ну, невозможно иметь нулевую задержку.Лучшее, на что вы можете надеяться, - это незаметная задержка (с точки зрения человеческого восприятия).Возможно, вам поможет, если вы опишете свой базовый алгоритм чтения и записи звуковых данных, чтобы люди могли выявить возможные проблемы.
Потенциальная проблема с использованием языка сбора мусора, такого как Java, заключается в том, что GC будет периодически запускаться, прерывая вашу обработку на некоторый произвольный промежуток времени.Однако я был бы удивлен, если при обычном использовании это > 100 мс.Если GC является проблемой, большинство JVM предоставляют альтернативные алгоритмы сбора, которые вы можете попробовать.
Если вы решите пойти по пути C / C ++, я настоятельно рекомендую использовать PortAudio ( http://portaudio.com/ ).Он работает практически со всем на нескольких платформах и дает вам низкоуровневый контроль над звуковыми драйверами без фактической необходимости иметь дело с различными технологиями звуковых драйверов, которые существуют.
Я использовал PortAudio в нескольких проектах, и пользоваться им - настоящее удовольствие.И лицензия разрешительная.
Если ваша цель - низкая задержка, вы не сможете превзойти C.
либсоундио это низкоуровневая библиотека C для ввода и вывода звука в реальном времени.Он даже поставляется с пример программы это делает именно то, что вы хотите - подключает микрофонный вход к выходу колонок.
Это, безусловно, достижимо с JavaSound чтобы получить сквозную задержку в приблизительном размере 100-150 мс.
Основной причиной задержки являются размеры буфера строк захвата и воспроизведения.Размер устанавливается при открытии линий:
- захват:
TargetDataLine#open(AudioFormat format, int bufferSize)
- воспроизведение:
SourceDataLine#open(AudioFormat format, int bufferSize)
- захват:
Если буфер слишком велик, это вызовет избыточную задержку, но если он слишком мал, это вызовет заикание при воспроизведении.Поэтому вам нужно найти баланс между потребностями ваших приложений и вашими вычислительными мощностями.
Размер буфера по умолчанию можно проверить с помощью DataLine#getBufferSize
при вызове #open(AudioFormat format)
.Размер по умолчанию будет варьироваться в зависимости от AudioFormat
и, похоже, предназначен для приложений воспроизведения с высокой задержкой и без заикания (напримерпотоковое вещание в Интернете).Если вы разрабатываете приложение с низкой задержкой, размер буфера по умолчанию слишком велик и его следует изменить.
В моем тестировании с 16-битным PCM AudioFormat
, размер буфера в 1024 байта был довольно близок к идеальному для низкой задержки.
- Вторая и часто упускаемая из виду причина задержки звука - это любое другое действие, выполняемое в потоках захвата или воспроизведения.Например, протоколирование сообщений на консоль может привести к задержке в 10 мс.Выключи его.