PortAudio ненадежен: Expression '' не удалось

В настоящее время я экспериментирую с обработкой сигналов в реальном времени, поэтому я пошел и попробовал 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.

  1. Ввод и вывод через аудиоинтерфейс USB, механизм обратного вызова на PortAudio, бэкэнд ALSA.
  2. Ввод и вывод через аудиоинтерфейс USB, блокировка ввода-вывода на PortAudio с размером буфера 1024 сэмплов, бэкэнд ALSA.
  3. Ввод через аудиоинтерфейс USB, вывод через встроенный звук, механизм обратного вызова на PortAudio, бэкэнд ALSA.
  4. Ввод через аудиоинтерфейс USB, вывод через встроенный звук, блокировка ввода-вывода на PortAudio с размером буфера 1024 сэмпла, бэкэнд ALSA.
  5. Ввод и вывод через аудиоинтерфейс USB, механизм обратного вызова на PortAudio, бэкэнд JACK.
  6. Ввод и вывод через аудиоинтерфейс USB, блокировка ввода / вывода на PortAudio с размером буфера 1024 сэмплов, бэкэнд JACK.

Проблемы, с которыми я столкнулся:

Результаты были следующими. (Числа представляют сценарии, описанные выше.)

  1. Нет вывода с устройства.
  2. Выход с устройства неустойчивый (прерывистый). Постоянно много опустошения буфера.
  3. Нет вывода с устройства.
  4. Выход из устройства нереальный. Иногда это работает, иногда нет. (Ничего не меняя, просто запускайте исполняемый файл несколько раз.) Когда он работает, задержка начинается с низкой, но со временем увеличивается и становится очень заметной.
  5. Нет вывода с устройства.
  6. Нет вывода с устройства.

Между каждой попыткой 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 имеет компонент уровня ядра.)

Мой вопрос:

Кто-нибудь знает, в чем проблема и как я могу ее исправить? Или, по крайней мере, как я могу немного сузить круг вопросов?


person no.human.being    schedule 09.02.2016    source источник
comment
Пожалуйста, покажите свой код.   -  person CL.    schedule 11.02.2016
comment
Ну вот! Большое спасибо за ваше время и усилия! /// PortAudio (на основе обратного вызова): pastebin.com/MrHpkXEA /// PortAudio (блокировка ввода-вывода ): pastebin.com/MDdUZ8W3 /// RtAudio (на основе обратного вызова): pastebin.com/YCQ0JpSR   -  person no.human.being    schedule 11.02.2016
comment
FWIW, у меня такая же проблема на Ubuntu 16.04.1 с простым приложением PortAudio. Я периодически получаю эту ошибку. Действительно, очень неприятно!   -  person Chris Merck    schedule 12.12.2016
comment
У меня аналогичные проблемы с pyaudio на rasberian. Тестирование с предложенным ответом на добавление пустых фреймов.   -  person www139    schedule 24.11.2019


Ответы (2)


Когда вы записываете только один блок семплов, на воспроизводящем устройстве заканчиваются семплы как раз тогда, когда вы собираетесь записать следующий блок.

Перед запуском цикла чтения / записи следует заполнить буфер устройства воспроизведения нулевыми отсчетами.

person CL.    schedule 10.02.2016
comment
Спасибо! Вы уверены, что именно так работает PortAudio? Это API реального времени. Обратный вызов дает вам входной и выходной буфер и количество кадров и (насколько я понимаю) ожидает, что вы прочитаете ТОЧНО это количество кадров из одного и запишете это количество кадров в другой. Я ожидал, что API будет вызывать меня в каждом блоке, а затем выводить то, что я написал, в выходной буфер сразу после того, как я вернусь. (Так что вызывайте каждый блок и задержку в 1 блок, так как блок, который обрабатывается I, всегда выводится на следующей итерации.) Это также то, как это делается в примерах. Я не думаю, что тут задействован буфер. - person no.human.being; 10.02.2016
comment
Теоретически об этом должен позаботиться API реального времени. Работают ли примеры программ PortAudio? - person CL.; 10.02.2016
comment
Как я уже сказал, я пробовал пример paex_read_write_wire.c (поскольку, как и мое приложение, оно выполняет как ввод, так и вывод, но использует блокирующий ввод-вывод). Он не выпадает, как у меня, но он все время опускается ниже нормы, и производительность сильно искажается. В paex_saw.c есть образец кода, который выводит пилообразную волну с помощью механизма обратного вызова (но не имеет ввода), и это работает со встроенным звуком (но также выводит предупреждения ALSA об отсутствии карты каналов), но вызывает много недогрузок (и искажений) на Интерфейс USB. Обратите внимание, что интерфейс USB отлично работает с обычными приложениями под ALSA. - person no.human.being; 10.02.2016
comment
Если PA вообще не работает, ваша программа ничего не может сделать. - person CL.; 10.02.2016
comment
Значит, сама библиотека сломана? (Разве это не маловероятно, учитывая, что это довольно распространено?) Что мне делать? Попробуйте еще одну библиотеку? Я только что пришел из простой ALSA, где у меня были серьезные проблемы с задержкой, поэтому люди сказали мне использовать API на основе обратного вызова. (Кроме того, ALSA содержит ошибки. Я уже наткнулся на них, но работал над ними. ;-)) Я провел небольшое исследование и обнаружил, что PortAudio, похоже, довольно широко используется и предназначен для обработки в реальном времени (что соответствует моим потребностям). Я хотел бы разработать несколько алгоритмов обработки звука, но все, с чем я имею дело, - это сломанные API. :-( - person no.human.being; 10.02.2016
comment
Ошибки ALSA, упомянутые в вашем предыдущем вопросе, на самом деле являются ошибками в Python или alsaaudio. Вам, вероятно, следует использовать другой язык. - person CL.; 10.02.2016
comment
Что ж, я уже пробовал и C, и C ++. rtAudio тоже доставляет мне проблемы. Проблема здесь (не считая того странного обстоятельства, что мое основное аудиоустройство имеет идентификатор 4): кажется, что оно попеременно читает и записывает. Я получаю искажение. Когда я увеличиваю буфер, я слышу, что он включается и выключается. Однако задержка, похоже, остается постоянной. Теперь у меня есть три библиотеки, которые явно не работают. Возможно, какая-то проблема с моей машиной / ОС? - person no.human.being; 14.02.2016
comment
На вашем компьютере работают другие программы, поэтому я предполагаю, что проблема в вашем коде. - person CL.; 14.02.2016
comment
Хотя мой код довольно минимален. Вы смотрели на это? Я имею в виду, что примеры программ тоже не работают. Мои алгоритмы работают при запуске с аудиофайлами, я просто не могу запустить ввод-вывод для реального оборудования. Тем не менее, очень важно, что я могу каким-то образом выполнить ввод-вывод. - person no.human.being; 15.02.2016

Мне неясны детали, но для меня переключение с низкой задержки ввода / вывода по умолчанию на высокую задержку ввода / вывода по умолчанию вылечило эту проблему, и я не могу почувствовать изменение задержки.

person CodeSoda    schedule 25.03.2020