habrahabr

Микширование звука в Cubian

  • пятница, 2 января 2015 г. в 02:10:45
http://habrahabr.ru/post/247205/

Когда передо мной встала задача проиграть параллельно несколько аудио-файлов на Cubian, я ещё об этом не догадывался. Уже много лет в линуксе проблема микширования звука отсутствует: и ALSA умеет это нативно, и множество саунд-серверов предлагают свои услуги на любой вкус и кошелёк.
Но оказалось, что проблема есть, и она обширнее, чем я предполагал изначально:


Проблема №1. Решённая. Phonon и pulseaudio


Итак, впервые я столкнулся с рассматриваемой проблемой, когда писал приложение на QT. В качестве звукового API был выбран phonon. И, стоило мне запустить приложение впервые, как я обнаружил, что аудио-драйвера от sunxi не умеют микшировать звук. Обескураженный этим обстоятельством, я установил пульс… и не получил никакого результата. Точнее, результаты были разными: то щелчки и хрипение, то полная тишина. В зависимости от того, какие ещё пакеты устанавливались. Перепробовав все доступные саунд-демоны (а их в дебиане оказалось не так много), я вернулся на пульс, потому что проблема так и не решилась и, очевидно, лежала где-то глубже.
Для тех, кто в настройки pulseaudio никогда не вдавался, я сделаю небольшое
отступление
Пульс может работать в двух режимах: системный и пользовательский. Рассмотрим оба отдельно:
1. Системный. Не рекомендуется на многопользовательских системах. Почему – смотрите документацию, там про это подробно. В случае встроенных систем вполне пригоден и иногда даже оптимален. Демон самостоятельно занимает аудиоустройсто и даёт доступ (в том числе, к настройкам звука) всем пользователям из группы pulse-access (а не pulse, это важно).
Для включения этого режима в дебиане необходимо в файле /etc/default/pulseaudio включить параметр: PULSEAUDIO_SYSTEM_START=1. Далее, удаляем из группы audio всех пользователей, кроме pulse. Прибиваем все сессионные экземпляры pulseaudio, если такие были, и запускаем сервис pulseaudio. Чтобы пользователь мог пользоваться звуком, добавляем его в группу pulse-access.
2. Сессионный. Работает как на многопользовательских, так и на встроенных системах. Но надо понимать, что если драйвера вашей карты не умеют микшировать, в каждый конкретный момент звук сможет играть только один пользователь. По умолчанию, в дебиане включён именно этот режим. Чтобы пользователь мог взаимодействовать со звуковой картой, его надо добавить в группу audio
Потому как в контексте более глобальной проблемы некоторые неочевидные моменты могут сильно затруднить жизнь.
Когда первая итерация не принесла желаемого результата, я решил выяснить, что знает об этой проблеме гугль. Гугль отвечал скупо и неохотно. Я смог выяснить только то, что vlc-backend фонона использовать не стоит, надо использовать gstreamer (для меня это было несколько удивительно, потому что я всегда считал vlc основным медиа-движком).
В результате, первая проблема была решена совсем уж чёрной магией: установкой пакета gstreamer0.10-plugins-ugly. И фонон заиграл.

Проблема №2. Нерешённая. VoIP и pulseaudio


Второй задачей было по одной команде отправлять на аудиовыход поток с VoIP-а, а по другой – проигрывать аудиофайл. Первая часть решается астериском с chan_alsa. Но chan_alsa полностью занимает устройство и не отдаёт, пока не выгрузишь модуль. Поэтому снова пульс.
В этот раз всё оказалось забавнее: chan_alsa делает с пульсом нечто такое, что пока его не выгрузишь, звук не играет ни он сам, ни любое другое приложение. При запуске пульса с подробным дебагом удаётся выловить ошибку, вся суть которой сводится к «у вас кривые драйвера карточки, отправьте вот эти данные разработчикам драйверов». Ну, раз проблема в драйверах ALSA, я решил попробовать OSS. В этот раз звук даже был, но с такими перерывами, что затея сразу потеряла смысл.
Так как всё это происходило на фоне уже решённой первой проблемы и отлично играющего sox'а, я подумал, что проблема не столько в драйверах, сколько в модуле астериска, и решил заменить его… например, на linphone. Когда проблема в точности повторилась с софтфоном, возникли подозрения, что дело не в конкретном приложении, а… ну, может быть в ресэмплинге войпового аудиопотока в родной для карточки PCM.
Так как задачи проигрывать звук одновременно из разных источников в этом случае не было, а linphone занимает устройство только на время непосредственно проигрывания звука, было решено удалить из схемы пульс.

Несмотря на то, что сама задача была решена, проблема вывода войп-аудиопотока через пульс осталась. И если кто-нибудь найдёт её решение, я буду очень благодарен.