高通8650 AudioReach 架构中 Virtual Mic & Loopback

背景

有整车客户项目,要将一块平板设备集成到座舱内,也就是作为车载平板使用。该平板移除了电池,并加入了 MCU,MIC 和 Speaker 也被去掉改为使用座舱上的 MIC 和 Speaker。整块平板仅供电与座舱物理连接,MIC 和 Speaker 的数据则通过无线方式进行传输。此外,平板上还特意添加了一个 USB Type-C 接口,用于实现 DP in 功能。传统的有线投屏通常是将音视频从平板投放到外部显示器,而 DP in 则让平板充当显示器,将音视频投射到平板上。

虚拟麦克风

问:如何将座舱内麦克风的录音传输给平板上的第三方应用程序,比如会议类应用?这个问题主要针对未连接耳机的场景。

答:上层的任何应用程序在获取录音时,最终都会通过 Android 的标准 API 调用到 AudioFlinger,从 HAL 获取录音。因此,我们可以在 AudioFlinger 中创建一个 IPC,并添加一个read接口。当 AudioFlinger 从 HAL 读取麦克风录音时,进行场景区分,调用这个 IPC 的read接口。该接口需要在应用程序中实现,因此平板上会有一个应用程序通过局域网与座舱保持连接,并且具备足够的权限。当 IPC read接口被调用时,这个应用程序将从座舱获取录音并返回。参考代码如下:

未经测试
status_t AudioFlinger::RecordThread::createAudioPatch_l(const struct audio_patch *patch,
                                                          audio_patch_handle_t *handle)
{
   
    status_t status = NO_ERROR;
	... ...
    if (inDeviceType() == AUDIO_DEVICE_IN_BUILTIN_MIC && sock <= 0) {
   
        struct sockaddr_in addr;
        memset(&addr, 0, sizeof(struct sockaddr_in));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr("10.106.246.70");
        addr.sin_port = htons(2333);

        sock = socket(AF_INET, SOCK_DGRAM, 0);
        if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == 0) {
   
            sendto(sock, &mBufferSize, sizeof(mBufferSize), 0, NULL, 0);
        } else
            ALOGE("%d, error: %s.\n", __LINE__, strerror(errno));
    }
    return status;
}

bool AudioFlinger::RecordThread::threadLoop()
{
   
			... ...
            ATRACE_BEGIN("read");
            size_t bytesRead;
            status_t result;
            ALOGE("%p, %s, inDeviceType() == AUDIO_DEVICE_IN_BUILTIN_MIC %d, sock %d, mBufferSize %zu",
                    this, __func__, inDeviceType() == AUDIO_DEVICE_IN_BUILTIN_MIC, sock, mBufferSize);
            if (inDeviceType() == AUDIO_DEVICE_IN_BUILTIN_MIC && sock > 0) {
   
                bytesRead = recvfrom(sock, (uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, 0, NULL, 0);
                result = bytesRead;
            } else {
   
                result = mSource->read((uint8_t*)mRsmpInBuffer + rear * mFrameSize, mBufferSize, &bytesRead);
            }   
            ATRACE_END();
}

IPC可以选择其他方案,比如 Binder,或者直接使用 AudioControl。如果使用基于网络的 socket,是否可以绕过应用程序这一环节,直接与座舱连接,从而省去一层中转?

补充一下,AudioControl 是一个独立的进程,可以参考以下示例:

#include <android/hardware/automotive/audiocontrol/2.0/IAudioControl.h>

using namespace android::hardware::automotive::audiocontrol::V2_0;
android::sp<IAudioControl> audiocontrol = IAudioControl::getService();

int32_t main(int argc, char** argv) {<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值