В настоящее время я экспериментирую с обработкой сигналов в реальном времени, поэтому я пошел и попробовал PortAudio (от C).
У меня есть два аудиоинтерфейса на моем компьютере, встроенный звук (Intel HD Audio) и аудиоинтерфейс USB. Оба обычно нормально работают под ALSA в Linux. Я также попробовал аудиоинтерфейс USB под JACK в Linux, и он тоже отлично работает.
Чем я занимаюсь:
Мой код просто инициализирует PortAudio, открывает и запускает поток (один канал, paInt32
формат образца, defaultLowInputLatency
/ defaultLowOutputLatency
, хотя я пытался изменить его на paFloat32
или defaultHighInputLatency
/ defaultHighOutputLatency
, что ничего не улучшило).
При каждом вызове обратного вызова он копирует sizeof(int32_t) * frameCount
байтов через memcpy
из ввода в буфер вывода, а затем возвращает paContinue
. Больше он ничего не делает в обратном вызове. Ни выделения памяти, ни системных вызовов, ничего, что это могло бы заблокировать. Он просто выводит то, что прочитал. Код очень простой, но я не могу его запустить.
Замена memcpy
циклом, копирующим frameCount
элементы типа int32_t
из входного буфера в выходной буфер, ничего не изменила.
Что я пробовал:
Следующие сценарии были опробованы с PortAudio.
- Ввод и вывод через аудиоинтерфейс USB, механизм обратного вызова на PortAudio, бэкэнд ALSA.
- Ввод и вывод через аудиоинтерфейс USB, блокировка ввода-вывода на PortAudio с размером буфера 1024 сэмплов, бэкэнд ALSA.
- Ввод через аудиоинтерфейс USB, вывод через встроенный звук, механизм обратного вызова на PortAudio, бэкэнд ALSA.
- Ввод через аудиоинтерфейс USB, вывод через встроенный звук, блокировка ввода-вывода на PortAudio с размером буфера 1024 сэмпла, бэкэнд ALSA.
- Ввод и вывод через аудиоинтерфейс USB, механизм обратного вызова на PortAudio, бэкэнд JACK.
- Ввод и вывод через аудиоинтерфейс USB, блокировка ввода / вывода на PortAudio с размером буфера 1024 сэмплов, бэкэнд JACK.
Проблемы, с которыми я столкнулся:
Результаты были следующими. (Числа представляют сценарии, описанные выше.)
- Нет вывода с устройства.
- Выход с устройства неустойчивый (прерывистый). Постоянно много опустошения буфера.
- Нет вывода с устройства.
- Выход из устройства нереальный. Иногда это работает, иногда нет. (Ничего не меняя, просто запускайте исполняемый файл несколько раз.) Когда он работает, задержка начинается с низкой, но со временем увеличивается и становится очень заметной.
- Нет вывода с устройства.
- Нет вывода с устройства.
Между каждой попыткой ALSA проверялась, остается ли она отзывчивой (иногда она полностью «зависала», так что ни одно приложение больше не могло выводить звук) и перезагружала систему в случае, если ALSA «зависла», а затем продолжала тестирование.
Дополнительные сведения, которые могут быть полезны при отслеживании проблемы:
В сценариях, где нет вывода вообще, я получаю следующие сообщения об ошибках при использовании ALSA в качестве серверной части.
Expression 'err' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3350
Expression 'ContinuePoll( self, StreamDirection_In, &pollTimeout, &pollCapture )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 3876
Expression 'PaAlsaStream_WaitForFrames( stream, &framesAvail, &xrun )' failed in 'src/hostapi/alsa/pa_linux_alsa.c', line: 4248
При использовании JACK в качестве серверной части появляется следующее сообщение об ошибке.
Cannot lock down 42435354 byte memory area (Cannot allocate memory)
Кроме того, независимо от того, какой метод я использую, я всегда получаю эти предупреждения.
ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2267:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
ALSA lib pcm_route.c:867:(find_matching_chmap) Found no matching channel map
При использовании ALSA я также получаю одну или две жалобы на недоработки.
ALSA lib pcm.c:7905:(snd_pcm_recover) underrun occurred
Функции PortAudio, которые я вызываю (Pa_Initialize
, Pa_OpenStream
, Pa_StartStream
, Pa_StopStream
, Pa_CloseStream
, Pa_Terminate
, в этом порядке), все возвращают paNoError
.
Пример paex_read_write_wire.c
(блокировка ввода-вывода), который поставляется с PortAudio, обычно может получить доступ к устройству, но также имеет множество недоработок (как в моем тестовом примере 2).
В любом случае в dmesg
нет ничего интересного. (Только что проверил, поскольку ALSA имеет компонент уровня ядра.)
Мой вопрос:
Кто-нибудь знает, в чем проблема и как я могу ее исправить? Или, по крайней мере, как я могу немного сузить круг вопросов?