2016-02-09 3 views
1

В настоящее время я экспериментирую с обработкой сигналов в реальном времени, поэтому я пошел и попробовал PortAudio (от C).PortAudio ненадежный: выражение «...» не выполнено

У меня есть два аудиоинтерфейса на моем компьютере, встроенный звук (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 в качестве backend появляется следующее сообщение об ошибке.

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

Мой вопрос:

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

+0

Пожалуйста, покажите свой код. –

+0

Здесь вы идете! Большое спасибо за ваше время и усилия! /// PortAudio (на основе обратного вызова): http://pastebin.com/MrHpkXEA /// PortAudio (блокирование ввода-вывода): http://pastebin.com/MDdUZ8W3 /// RtAudio (callback- основанный): http://pastebin.com/YCQ0JpSR –

+0

FWIW, я получаю такую ​​же проблему на Ubuntu 16.04.1 с простым приложением PortAudio. Я получаю эту ошибку с перерывами. Очень расстраивает! –

ответ

0

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

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

+0

Спасибо! Вы уверены, что это так, как это работает с PortAudio? Это API реального времени. Обратный вызов дает вам входной и выходной буфер и количество кадров и (насколько я понимаю) ожидает, что вы будете читать ТОЧНО это количество кадров из одного и записать это количество кадров в другое.Я ожидал, что API вызовет меня на каждом блоке, а затем выведет то, что я написал, в выходной буфер сразу после возвращения. (Таким образом, вызов на каждом блоке и 1 «задержка» блока, поскольку процесс блока I всегда выводится на следующей итерации.) Это также то, как это делается в примерах. Я не думаю, что есть буфер. –

+0

Теоретически API реального времени должен позаботиться об этом. Используются ли примерные программы PortAudio? –

+0

Как я уже сказал, я попробовал пример 'paex_read_write_wire.c' (поскольку, как и мое приложение, он выполняет вход и вывод, но использует блокирующий ввод-вывод). Он не «выпадает», как у меня, но он все время разрушается, а выход сильно искажен. В «paex_saw.c» есть образец кода, который выводит пилообразную волну с использованием механизма обратного вызова (но не имеет ввода), и это работает на встроенном звуке (но также выводит предупреждения ALSA о «карте каналов»), но вызывает множество недоработок (и искажения) на интерфейсе USB. Обратите внимание, что интерфейс USB отлично работает с «обычными» приложениями в ALSA. –

Смежные вопросы