• Android/Automotive 多声道录音支持


    1. 内核驱动

    2.  系统配置

    2.1  配置文件

    AF 查找HW DEV可以看出,优先PRIMARY接口

    1. AudioFlinger.cpp
    2. static const char * const audio_interfaces[] = {
    3.     AUDIO_HARDWARE_MODULE_ID_PRIMARY,
    4.     AUDIO_HARDWARE_MODULE_ID_A2DP,
    5.     AUDIO_HARDWARE_MODULE_ID_USB,
    6. };

    配置Configure文件路径: /vendor/etc/audio/audio_policy_configuration.xml

    为什么是这个文件名称,APM代码有描述:

    1. APM_AudioPolicyManager.cpp:
    2. #define AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH 128
    3. #define AUDIO_POLICY_XML_CONFIG_FILE_NAME "audio_policy_configuration.xml"
    4. static status_t deserializeAudioPolicyXmlConfig(AudioPolicyConfig &config) {
    5. char audioPolicyXmlConfigFile[AUDIO_POLICY_XML_CONFIG_FILE_PATH_MAX_LENGTH];
    6. std::vector<const char*> fileNames;
    7. status_t ret;
    8. if (property_get_bool("ro.bluetooth.a2dp_offload.supported", false)) {
    9. if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false) &&
    10. property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
    11. // Both BluetoothAudio@2.0 and BluetoothA2dp@1.0 (Offlaod) are disabled, and uses
    12. // the legacy hardware module for A2DP and hearing aid.
    13. fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
    14. } else if (property_get_bool("persist.bluetooth.a2dp_offload.disabled", false)) {
    15. // A2DP offload supported but disabled: try to use special XML file
    16. fileNames.push_back(AUDIO_POLICY_A2DP_OFFLOAD_DISABLED_XML_CONFIG_FILE_NAME);
    17. }
    18. } else if (property_get_bool("persist.bluetooth.bluetooth_audio_hal.disabled", false)) {
    19. fileNames.push_back(AUDIO_POLICY_BLUETOOTH_LEGACY_HAL_XML_CONFIG_FILE_NAME);
    20. }
    21. fileNames.push_back(AUDIO_POLICY_XML_CONFIG_FILE_NAME);

    2.2  修改

     如上可以看出channelMasks 配置缺少多声道

    修改后://增加四声道

    注:source理解为发送端,sink理解为接受端 

    3. APP方法

    3.1 使用AudioRecord原生接口:

    为了从设备获取超过两个声道的音频,使用一个通到索引掩码:channelIndexMask

    1. final AudioFormat audioFormat=new AudioFormat.Builder()
    2. .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
    3. .setSampleRate(44100)
    4. .setChannelIndexMask(0xf/*4 channels,0...3*/)
    5. .build();
    6. final AudioRecord audioRecord = new AudioRecord.Builder()
    7. .setAudioFormat(audioFormat)
    8. .build();

    AudioFormat.java  代码setChannelIndexMask 接口如下:

     

    注意:当setChannelMask和setChannelIndexMask都设置的时候,AudioRecord只是用setChannleMask的值(最大为两个通道)。

    System/media/audio/include/system/audio-base.h针对AUDIO_CHANNEL_INDEX定义如下:

     

    3.2 使用AAudio接口:

    AAudio 是Android为解决声音延时的高效Native接口,Andriod系统标配,目前大量使用在公网对讲机,语音对讲,Voip,RTC项目中。

    1. #include
    2. result = AAudio_createStreamBuilder(&inputBuilder);
    3. if (result != AAUDIO_OK) {
    4. LOGE("%s create Stream inputBuilder failed", __func__);
    5. }
    6. AAudioStreamBuilder_setDirection(inputBuilder, AAUDIO_DIRECTION_INPUT); //设置流的方向
    7. AAudioStreamBuilder_setDeviceId(inputBuilder, AAUDIO_UNSPECIFIED);
    8. AAudioStreamBuilder_setSampleRate(inputBuilder, 48000);
    9. AAudioStreamBuilder_setChannelCount(inputBuilder, 4);//设置channel->4
    10. AAudioStreamBuilder_setFormat(inputBuilder, AAUDIO_FORMAT_PCM_I16);
    11. AAudioStreamBuilder_setPerformanceMode(inputBuilder, AAUDIO_PERFORMANCE_MODE_LOW_LATENCY);
    12. //数据回调
    13. AAudioStreamBuilder_setDataCallback(inputBuilder, inDataCallback, this);
    14. //create input stream
    15. result = AAudioStreamBuilder_openStream(inputBuilder, &inputStream);
    16. if (result != AAUDIO_OK) {
    17. LOGE("%s open inputStream failed", __func__);
    18. }
    19. result = AAudioStream_requestStart(inputStream);
    20. if (result != AAUDIO_OK) {
    21. LOGE("%s inputStream request Start failed", __func__);
    22. }
    23. //数据分析:
    24. aaudio_data_callback_result_t inDataCallback(
    25.         AAudioStream *stream,
    26.         void *userData,
    27.         void *audioData,
    28.         int32_t numFrames) {
    29. //note 1. 16bit->2bytes * channel->4,所以这里每帧是8个字节
    30.     memcpy(buffer, audioData, numFrames *8);//AudioCapure数据
    31.     return AAUDIO_CALLBACK_RESULT_CONTINUE;
    32. }

  • 相关阅读:
    MySQL之索引
    淘宝API关键词搜索接口调用示例
    因为axios请求后端,接收不到token的问引出的问题
    认证学习2 - Base认证讲解、代码实现、演示
    Spring Security整合企业微信的扫码登录,企微的API震惊到我了
    微信小程序获取openid流程
    操作系统复习第四章:存储器管理
    从零开始学前端:DOM、BOM、焦点事件、键盘事件 --- 今天你学习了吗?(JS:Day20)
    技术团队:研发中的短跑冲刺和马拉松游戏
    LeetCode刷题day24||回溯算法理论基础&&77. 组合--回溯
  • 原文地址:https://blog.csdn.net/liaochaoyun/article/details/126260094