Перенаправление аудио / создание альтернативных звуковых дорожек в Android

У кого-нибудь есть опыт (использование OpenSL ES, ALSA и т. Д.) С перенаправлением звука или созданием новых звуковых дорожек в Android? Конечная цель - создать виртуальный микрофон для замены внешнего микрофона, где можно воспроизводить аудиофайлы, как если бы они говорили в микрофон. Приложения, имеющие доступ к микрофону с AudioSource.MIC следует использовать этот альтернативный поток. Для работы с голосовыми вызовами нет необходимости, я считаю, что добиться такого рода функциональности сложнее, поскольку все это делается в радио.

Есть идеи, с чего начать? Я провел некоторые исследования с OpenSL и ALSA, но, похоже, мне нужно будет упаковать новую прошивку (ПЗУ), чтобы определить собственные пути аудио. Если этого можно избежать, я бы хотел создать решение на уровне приложений. Телефоны "рутированы" (имеют su binaries). Целевым устройством для этого является Samsung Galaxy S4 Google Edition (GT-i9505G). В частности, я ищу конфигурации аудио драйвера / исходный код или любые ссылки для i9505G.

Заранее спасибо!

редактировать - я проверил исходное дерево CyanogenMod 10.2, а также драйверы jfltexx и ядро. Вот содержимое ядра / Samsung/ JF / Sound: http://pastebin.com/7vK8THcZ. Это где-нибудь задокументировано?

1 ответ

Решение

Однажды я реализовал функциональность, которая вам нужна, в телефоне на платформе QQcomcom APQ8064 (которая, кажется, почти такая же, как и в вашем целевом устройстве). Ниже приводится краткое изложение того, что я могу вспомнить из-за того, что у меня больше нет доступа к написанному мною коду или среде, в которой я могу легко вносить подобные изменения. Так что, если этот ответ читается как беспорядок фрагментарных воспоминаний, это потому, что это именно то, что есть.

Эта информация также может более или менее применяться к другим платформам Qualcomm (например, MSM8960 или MSM8974), но, скорее всего, будет совершенно бесполезной для платформ других поставщиков (NVidia Tegra, Samsung Exynos, TI OMAP и т. Д.).

Краткое замечание: метод, который я использовал, означает, что звук, который получает приложение записи, будет проходить микширование / регулировку громкости в мультимедийной среде Android и / или в мультимедийном DSP платформы. Так что если вы играете что-то на 75% громкости, записываете и затем воспроизводите запись на 75%, это может звучать довольно тихо. Если вы хотите получить необработанные данные PCM (после декодирования, но перед микшированием / регулировкой громкости), вам придется рассмотреть другой подход, например, настроить AudioFlinger, но это не то, что я пытался или могу предоставить информацию.


Несколько мест интереса:

Аудио драйверы платформы. В частности, файл msm-pcm-routing.c.

Файл настроек ALSA UCM (Use-Case Manager). Это просто пример файла настроек UCM. Существует много вариантов этих файлов в зависимости от используемой платформы, поэтому у ваших файлов может быть немного другое имя (хотя оно должно начинаться с snd_soc_msm_), и его содержимое, вероятно, также будет немного отличаться от того, на которое я ссылался.
ПРИМЕЧАНИЕ для Kitkat и более поздних версий: файлы настроек UCM использовались на Jellybean (и, возможно, ICS). Насколько я понимаю, эти настройки были перемещены в файл с именем mixer_paths.xml на Киткат. Содержимое практически одинаковое, просто в другом формате.

Аудио код HAL. ALSA UCM присутствует в libalsa-intf и AudioHardware / AudioPolicyManager / ALSADevice код присутствует в audio-alsa, Обратите внимание, что этот код предназначен для Jellybean, так как это последняя версия, с которой я знаком. Структура каталогов (и, возможно, некоторые файлы / классы) отличается в Kitkat.

Если вы откроете файл настроек UCM и выполните поиск "HiFiPROXY Rx" вы найдете что-то вроде этого:

SectionVerb
Name "HiFiPROXY Rx"

EnableSequence
    'AFE_PCM_RX Audio Mixer MultiMedia1':1:1
EndSequence

DisableSequence
    'AFE_PCM_RX Audio Mixer MultiMedia1':1:0
EndSequence

# ALSA PCMs
CapturePCM 0
PlaybackPCM 0
EndSection

Это определяет глагол (по сути, основа варианта использования аудио; есть также модификаторы, которые можно применять поверх глаголов для таких вещей, как одновременное воспроизведение и запись) с именем "HiFiPROXY Rx" (HiFi moniker используется для большинства глаголов без голосового вызова, PROXY относится к используемому аудиоустройству, и Rx означает выход) и указывает, в какой элемент управления ALSA записывать и что записывать в них, когда сценарий использования должен быть включен / отключен. Наконец, в нем перечислены устройства воспроизведения / захвата ALSA PCM, которые будут использоваться в этом случае. Например, PlaybackPCM 0 означает, что должно использоваться устройство воспроизведения 0 (подразумевается, что карта ALSA представляет собой встроенный аппаратный кодек, который обычно является картой 0). Эти глаголы выбираются аудио HAL на основе варианта использования (воспроизведение музыки, голосовой вызов, запись, ...), какие аксессуары вы подключили и т. Д.


Если вы посмотрите вверх "AFE_PCM_RX Audio Mixer" в таблице msm_qdsp6_widgets в msm-pcm-routing.c вы увидите, что это относится к списку элементов управления микшера с именем afe_pcm_rx_mixer_controls это выглядит так:

static const struct snd_kcontrol_new afe_pcm_rx_mixer_controls[] = {
    SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_AFE_PCM_RX,
    MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer,
    msm_routing_put_audio_mixer),
    SOC_SINGLE_EXT("MultiMedia2", MSM_BACKEND_DAI_AFE_PCM_RX,
    ... and so on...

В этом списке перечислены внешние DAI, которые вам разрешено подключать к внутреннему DAI (AFE_PCM_RX). Чтобы получить представление о том, как они связаны друг с другом, см. Эти диаграммы.
AFE_PCM_RX а также AFE_PCM_TX представляет собой пару DAI на некоторых платформах Qualcomm, которые реализуют своего рода фиктивное / прокси-устройство. Что вы делаете, это подача аудио в AFE_PCM_RX который затем обрабатывается мультимедийным DSP (QDSP), а затем вы можете прочитать его обратно AFE_PCM_TX, Это используется для реализации маршрутизации аудио через USB и WiFi, а также A2DP IIRC.

Назад к AFE_PCM_RX Audio Mixer MultiMedia1 линия: это говорит о том, что вы кормите MultiMedia1 в AFE_PCM_RX Audio Mixer, MultiMedia1 используется для нормального воспроизведения / записи и соответствует pcmC0D0 (вы должны иметь возможность перечислить устройства на вашем телефоне с adb shell cat /proc/asound/devices). Есть и другие интерфейсные DAI, такие как MultiMedia3 а также MultiMedia5 которые используются в особых случаях, таких как воспроизведение с низкой задержкой и воспроизведение аудио с низким энергопотреблением.
Когда вы кормите MultiMedia1 к AFE_PCM_RX Audio Mixer все, что вы записываете на устройство воспроизведения 0 на карте 0, будет подано в AFE_PCM_RX задний конец DAI. Чтобы прочитать его обратно, вы можете настроить глагол UCM, который делает что-то вроде 'MultiMedia1 Mixer AFE_PCM_TX':1:1, а затем вы читаете из pcmC0D0c (которое должно быть устройством захвата ALSA по умолчанию).


Простым тестом будет вытащить файл настроек UCM из вашего телефона (должен находиться где-то под /system/etc/) и изменить "HiFi" глагола EnableSequence с чем-то вроде:

'AFE_PCM_RX Audio Mixer MultiMedia1':1:1
'AFE_PCM_RX Audio Mixer MultiMedia3':1:1
'AFE_PCM_RX Audio Mixer MultiMedia5':1:1

(и аналогично в DisableSequence, но с :1:0 в конце каждой строки).

Затем перейдите к "Capture Music" модификатор (это плохо названный модификатор для нормальной записи) и изменение SLIM_0_TX в AFE_PCM_TX,

Скопируйте измененный файл настроек UCM обратно на телефон (требуется разрешение root) и перезагрузите телефон. Затем начните воспроизведение (подключите проводную гарнитуру / наушники и отключите звуки касания, чтобы глагол с низкой задержкой не был выбран), и начните запись с AudioSource.MIC, После этого проверьте запись и посмотрите, удалось ли вам записать звук воспроизведения. Если нет, то, возможно, был выбран аудиоглагол с низким энергопотреблением, и вам придется изменить "HiFi Low Power" глагол аналогично тому, что вы сделали с "HiFi" глагол. Это поможет вам, если у вас включены все отладочные отпечатки в аудио HAL (т.е. раскомментируйте #define LOG_NDEBUG 0 во всех файлах cpp, где вы можете его найти), чтобы вы могли видеть, какие глаголы / модификаторы UCM выбраны.


Модификация, которую я описал выше, становится немного утомительной, так как вы должны охватить все MultiMedia внешние интерфейсы DAI для всех соответствующих глаголов и модификаторов.
IIRC, я смог упростить это до одной строки на глагол / модификатор:

'AFE_PCM_RX Port Mixer SLIM_0_RX':1:1

Если вы посмотрите на "HiFi ", "HiFi Low Power ", "HiFi Lowlatency" глаголы вы увидите, что они все используют SLIMBUS_0_RX задний конец DAI, поэтому я использую это с помощью AFE_PCM_RX Port Mixer который позволяет мне установить соединение от внутреннего DAI до другого внутреннего DAI. Если вы посмотрите на afe_pcm_rx_port_mixer_controls а также intercon таблицы в msm-pcm-routing.c вы заметите, что нет SLIM_0_RX запись для AFE_PCM_RX Port Mixer, так что вам придется добавить их самостоятельно (это просто вопрос копирования отдельных существующих строк и изменения имен).


Некоторые из других изменений, которые вам, вероятно, придется сделать:

  • В frameworks / base и frameworks / av (например, AudioManager, AudioService, AudioSystem) вам придется добавить новый AudioSource постоянный и убедитесь, что он будет признан во всех необходимых местах.

  • В файле настроек UCM вам нужно будет добавить несколько новых глаголов / модификаторов, чтобы правильно настроить элементы управления ALSA, когда ваш новый AudioSource используется.

  • В аудио HAL вам нужно будет внести некоторые изменения, чтобы ваши новые глаголы / модификаторы были выбраны, когда ваш новый AudioSource используется. Обратите внимание, что есть базовый класс AudioPolicyManagerALSA называется AudioPolicyManagerBase который вам также может потребоваться изменить (он находится в другом месте исходного дерева).

Другие вопросы по тегам