alsa sample rate跟踪 <4>

alsa sample rate跟踪 <4>

接下来,要看看open流程中都往pcm上挂了哪些东东。
aplay的main函数中调用snd_pcm_open函数,并传入了一个snd_pcm_t指针handle的地址:

static snd_pcm_t *handle;
 err = snd_pcm_open(&handle, pcm_name, stream, open_mode);



这个时候handle还是干净的。

snd_pcm_open中将snd_pcm_t指针的地址直接传给了函数snd_pcm_open_noupdate:

 return snd_pcm_open_noupdate(pcmp, snd_config, name, stream, mode, 0);



 
snd_pcm_open_noupdate中将snd_pcm_t指针的地址直接传给了函数snd_pcm_open_conf:

  err = snd_pcm_open_conf(pcmp, name, root, pcm_conf, stream, mode);



  
snd_pcm_open_conf中将snd_pcm_t指针的地址直接传给了函数_snd_pcm_plug_open:

  // 此处 open_func 为_snd_pcm_plug_open函数
  err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);



  
_snd_pcm_plug_open中定义了一个snd_pcm_t指针,并将其地址传给了函数snd_pcm_open_slave:

 snd_pcm_t *spcm;
 err = snd_pcm_open_slave(&spcm, root, sconf, stream, mode, conf);



 
snd_pcm_open_slave中将snd_pcm_t指针的地址直接传给了函数snd_pcm_open_named_slave:

 return snd_pcm_open_named_slave(pcmp, NULL, root, conf, stream,
     mode, parent_conf);



     
snd_pcm_open_named_slave中将snd_pcm_t指针的地址直接传给了函数snd_pcm_open_noupdate:

  return snd_pcm_open_noupdate(pcmp, root, str, stream, mode,
          hop + 1);



      
snd_pcm_open_noupdate中将snd_pcm_t指针的地址直接传给了函数snd_pcm_open_conf:

  err = snd_pcm_open_conf(pcmp, name, root, pcm_conf, stream, mode);



  
snd_pcm_open_conf中将snd_pcm_t指针的地址直接传给了函数_snd_pcm_dmix_open:

  // 此处 open_func 为_snd_pcm_dmix_open函数
  err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);



 
_snd_pcm_dmix_open中处理:
定义slave_params结构体:

 struct slave_params params;



初始化slave_params结构体:

 /* the default settings, it might be invalid for some hardware */
 params.format = SND_PCM_FORMAT_S16;
 params.rate = 48000;  // 原来这儿有个48000,怪不得asound.conf是否指定rate 48000都会调用rate plug。
 params.channels = 2;
 params.period_time = -1;
 params.buffer_time = -1;
 bsize = psize = -1;
 params.periods = 3;



将snd_pcm_t指针的地址和params传给了函数snd_pcm_dmix_open:

 err = snd_pcm_dmix_open(pcmp, name, &dopen, ¶ms,
    root, sconf, stream, mode);



    
snd_pcm_dmix_open函数中相关处理:
首先定义:

 snd_pcm_t *pcm = NULL, *spcm = NULL;
 snd_pcm_direct_t *dmix = NULL;



为dmix分配空间:

 dmix = calloc(1, sizeof(snd_pcm_direct_t));



对dmix成员进行赋值:

 dmix->ipc_key = opts->ipc_key;
 dmix->ipc_perm = opts->ipc_perm;
 dmix->ipc_gid = opts->ipc_gid;
 dmix->semid = -1;
 dmix->shmid = -1;



给pcm分配空间并初始化:

 ret = snd_pcm_new(&pcm, dmix->type = SND_PCM_TYPE_DMIX, name, stream, mode);



将snd_pcm_dmix_ops赋值给pcm的ops,并将dmix赋值给pcm的private_data:

 pcm->ops = &snd_pcm_dmix_ops;
 pcm->fast_ops = &snd_pcm_dmix_fast_ops;
 pcm->private_data = dmix;



初始化dmix另外一些成员:

 dmix->state = SND_PCM_STATE_OPEN;
 dmix->slowptr = opts->slowptr;
 dmix->max_periods = opts->max_periods;
 dmix->sync_ptr = snd_pcm_dmix_sync_ptr;



以spcm为参数调用snd_pcm_open_slave:

  ret = snd_pcm_open_slave(&spcm, root, sconf, stream,
      mode | SND_PCM_NONBLOCK, NULL);



     
snd_pcm_open_slave的调用过程见上面_snd_pcm_plug_open的分析。
最终调用到了下面这一步:
snd_pcm_open_conf中将snd_pcm_t指针的地址直接传给了函数_snd_pcm_hw_open:

  // 此处 open_func 为_snd_pcm_hw_open函数
  err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);



  
_snd_pcm_hw_open中将snd_pcm_t指针的地址直接传给了函数snd_pcm_hw_open:

 err = snd_pcm_hw_open(pcmp, name, card, device, subdevice, stream,
         mode | (nonblock ? SND_PCM_NONBLOCK : 0),
         0, sync_ptr_ioctl);
  



snd_pcm_hw_open中的处理:
调用snd_open_device打开设备:(snd_open_device中调用open实现设备打开)

 fd = snd_open_device(filename, fmode);  // 这儿的filename是dev目录下的设备文件,如:/dev/snd/pcmC1D1p



将snd_pcm_t指针的地址直接传给了函数snd_pcm_hw_open_fd:

 return snd_pcm_hw_open_fd(pcmp, name, fd, 0, sync_ptr_ioctl);



 
snd_pcm_hw_open_fd中的处理:
定义:

 snd_pcm_t *pcm = NULL;
 snd_pcm_hw_t *hw = NULL;



通过ioctl对fd进行一些操作。
为hw分配空间:

 hw = calloc(1, sizeof(snd_pcm_hw_t));



初始化hw成员:

 hw->version = ver;
 hw->card = info.card;
 hw->device = info.device;
 hw->subdevice = info.subdevice;
 hw->fd = fd;
 hw->sync_ptr_ioctl = sync_ptr_ioctl;
 /* no restriction */
 hw->format = SND_PCM_FORMAT_UNKNOWN;
 hw->rate = 0;
 hw->channels = 0;



给pcm分配空间并初始化:

 ret = snd_pcm_new(&pcm, SND_PCM_TYPE_HW, name, info.stream, mode);



将snd_pcm_hw_ops赋值给pcm的ops,将hw赋值给pcm的private_data:

 pcm->ops = &snd_pcm_hw_ops;
 pcm->fast_ops = &snd_pcm_hw_fast_ops;
 pcm->private_data = hw;
 pcm->poll_fd = fd;
 pcm->poll_events = info.stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
 pcm->monotonic = monotonic;



将pcm赋值给传入的snd_pcm_t指针的地址:

 *pcmp = pcm;



 
从snd_pcm_open_slave出来。
回到snd_pcm_dmix_open:

调用snd_pcm_direct_initialize_slave函数进行初始化:

  // params是_snd_pcm_dmix_open中定义并初始化的结构体
  ret = snd_pcm_direct_initialize_slave(dmix, spcm, params);



函数snd_pcm_direct_initialize_slave的注释:

/*
 * this function initializes hardware and starts playback operation with
 * no stop threshold (it operates all time without xrun checking)
 * also, the driver silences the unused ring buffer areas for us
 */



snd_pcm_direct_initialize_slave中设置了hw_params的各种参数,然后调用了snd_pcm_hw_params函数:

 ret = snd_pcm_hw_params(spcm, hw_params);



将hw_params的参数保存到snd_pcm_dmix_open的dmix中:

 /* store some hw_params values to shared info */
 dmix->shmptr->hw.format = snd_mask_value(hw_param_mask(hw_params, SND_PCM_HW_PARAM_FORMAT));
 dmix->shmptr->hw.rate = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_RATE);
 dmix->shmptr->hw.buffer_size = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_BUFFER_SIZE);
 dmix->shmptr->hw.buffer_time = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_BUFFER_TIME);
 dmix->shmptr->hw.period_size = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIOD_SIZE);
 dmix->shmptr->hw.period_time = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIOD_TIME);
 dmix->shmptr->hw.periods = *hw_param_interval(hw_params, SND_PCM_HW_PARAM_PERIODS);



然后调用了snd_pcm_sw_params函数:

 ret = snd_pcm_sw_params(spcm, sw_params);



接下来调用了snd_pcm_start:

 ret = snd_pcm_start(spcm);



 
从snd_pcm_direct_initialize_slave出来。
回到snd_pcm_dmix_open:

将spcm赋值给dmix:

  dmix->spcm = spcm;



给pcm的部分成员赋值:

 pcm->poll_fd = dmix->poll_fd;
 pcm->poll_events = POLLIN; /* it's different than other plugins */
 pcm->mmap_rw = 1;



将pcm赋值给传入的snd_pcm_t指针的地址:

 *pcmp = pcm;


 

从snd_pcm_open_slave出来。 
回到_snd_pcm_plug_open:

_snd_pcm_plug_open中将snd_pcm_t指针的地址和spcm传给了函数snd_pcm_plug_open:

 err = snd_pcm_plug_open(pcmp, name, sformat, schannels, srate, rate_converter,
    route_policy, ttable, ssize, cused, sused, spcm, 1);



    
snd_pcm_plug_open函数中定义了一个snd_pcm_plug_t指针,并分配了snd_pcm_plug_t对象。
然后初始化snd_pcm_plug_t对象,并将该对象赋值给snd_pcm_t指针的private_data。
并将snd_pcm_plug_ops赋值给snd_pcm_t指针的ops成员。
代码列出来,可能更明了:

/**
 * \brief Creates a new Plug PCM
 * \param pcmp Returns created PCM handle
 * \param name Name of PCM
 * \param sformat Slave (destination) format
 * \param slave Slave PCM handle
 * \param close_slave When set, the slave PCM handle is closed with copy PCM
 * \retval zero on success otherwise a negative error code
 * \warning Using of this function might be dangerous in the sense
 *          of compatibility reasons. The prototype might be freely
 *          changed in future.
 */
int snd_pcm_plug_open(snd_pcm_t **pcmp,
        const char *name,
        snd_pcm_format_t sformat, int schannels, int srate,
        const snd_config_t *rate_converter,
        enum snd_pcm_plug_route_policy route_policy,
        snd_pcm_route_ttable_entry_t *ttable,
        unsigned int tt_ssize,
        unsigned int tt_cused, unsigned int tt_sused,
        snd_pcm_t *slave, int close_slave)
{
 snd_pcm_t *pcm;
 // 定义指针
 snd_pcm_plug_t *plug;
 int err;
 assert(pcmp && slave);

 // 分配空间
 plug = calloc(1, sizeof(snd_pcm_plug_t));
 if (!plug)
  return -ENOMEM;
 plug->sformat = sformat;
 plug->schannels = schannels;
 plug->srate = srate;
 plug->rate_converter = rate_converter;
 // 将slave pcm赋值过来
 plug->gen.slave = plug->req_slave = slave;
 plug->gen.close_slave = close_slave;
 plug->route_policy = route_policy;
 plug->ttable = ttable;
 plug->tt_ssize = tt_ssize;
 plug->tt_cused = tt_cused;
 plug->tt_sused = tt_sused;
 
 err = snd_pcm_new(&pcm, SND_PCM_TYPE_PLUG, name, slave->stream, slave->mode);
 if (err < 0) {
  free(plug);
  return err;
 }
 pcm->ops = &snd_pcm_plug_ops;
 pcm->fast_ops = slave->fast_ops;
 pcm->fast_op_arg = slave->fast_op_arg;
 // 将plug赋值到pcm的private_data
 pcm->private_data = plug;
 pcm->poll_fd = slave->poll_fd;
 pcm->poll_events = slave->poll_events;
 pcm->mmap_shadow = 1;
 pcm->monotonic = slave->monotonic;
 snd_pcm_link_hw_ptr(pcm, slave);
 snd_pcm_link_appl_ptr(pcm, slave);
 *pcmp = pcm;

 return 0;
}


 

小结一下。
aplay传入的snd_pcm_t指针地址在snd_pcm_plug_open中被赋值
其中:

 pcm->ops = &snd_pcm_plug_ops;
 pcm->fast_ops = slave->fast_ops;
 pcm->private_data = plug;
 plug->gen.slave = plug->req_slave = slave;



slave在snd_pcm_dmix_open中被赋值:

 pcm->ops = &snd_pcm_dmix_ops;
 pcm->fast_ops = &snd_pcm_dmix_fast_ops;
 pcm->private_data = dmix;
  dmix->spcm = spcm;



spcm在snd_pcm_hw_open_fd中被赋值:

 pcm->ops = &snd_pcm_hw_ops;
 pcm->fast_ops = &snd_pcm_hw_fast_ops;
 pcm->private_data = hw;
 pcm->poll_fd = fd;
 hw->fd = fd;



其中fd是打开的设备文件句柄。

结构体的赋值已经基本清晰。
下面来看看snd_pcm_hw_params的函数调用关系:

                                                                       snd_pcm_hw_params
                                                                          /                         \
                                                                         /                           \
                                          _snd_pcm_hw_params               snd_pcm_prepare
                                                                   /
                                                                  /
                                        snd_pcm_plug_hw_params
                                                    /                        \
                                                   /                          \
                   snd_pcm_plug_insert_plugins        _snd_pcm_hw_params
                                                   /                                       /
                                                  /                                       /
                     snd_pcm_plug_change_rate        snd_pcm_rate_hw_params
                                                /                                           /
                                               /                                           /
                            snd_pcm_rate_open        snd_pcm_hw_params_slave
                                                                                            /
                                                                                           /
                                                                  snd_pcm_generic_hw_params
                                                                                            /
                                                                                           /
                                                                    _snd_pcm_hw_params
                                                                                        /
                                                                                       /
                                                                   snd_pcm_direct_hw_params
               
开发linux audio driver的同学应该很熟悉hw:x,x设备。
可以aplay -D hw:x,x xxx.wav来指定使用hw:x,x设备播放音频。
这样指定之后,alsa lib将不会对音频进行处理,也就是说除了hw之外,其他的plug都不会被使用。
在open的时候,只调用了_snd_pcm_hw_open。
在set params时,也只调用了snd_pcm_hw_hw_params。
这样的话,声音数据直接扔给了audio driver,alsa lib中不会对采样率,声道,格式等进行处理。

<?xml version="1.0" encoding="UTF-8"?> <!-- Copyright (C) 2015 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <!-- Default Volume Tables included by Audio Policy Configuration file --> <!-- Full Default Volume table for all device category --> <volumes> <reference name="FULL_SCALE_VOLUME_CURVE"> <!-- Full Scale reference Volume Curve --> <point>0,0</point> <point>100,0</point> </reference> <reference name="SILENT_VOLUME_CURVE"> <point>0,-9600</point> <point>100,-9600</point> </reference> <!-- #ifndef OPLUS_BUG_STABILITY //YaJun.Li@MM.AudioServer.Policy, 2019/08/21,Add for voice volume --> <reference name="DEFAULT_VOICE_VOLUME_CURVE"> <!-- Default Voice reference Volume Curve --> <point>0,-5400</point> <point>1,-4700</point> <point>2,-4200</point> <point>3,-3800</point> <point>4,-3400</point> <point>5,-3000</point> <point>6,-2600</point> <point>7,-2200</point> <point>8,-1800</point> <point>9,-1500</point> <point>10,-1200</point> <point>11,-900</point> <point>12,-600</point> <point>13,-300</point> <point>14,0</point> </reference> <!-- #endif OPLUS_BUG_STABILITY --> <reference name="DEFAULT_SYSTEM_VOLUME_CURVE"> <!-- Default System reference Volume Curve --> <point>1,-6000</point> <point>2,-3100</point> <point>3,-2800</point> <point>4,-2600</point> <point>5,-2400</point> <point>6,-2200</point> <point>7,-2000</point> <point>8,-1800</point> <point>9,-1600</point> <point>10,-1400</point> <point>11,-1200</point> <point>12,-1000</point> <point>13,-800</point> <point>14,-600</point> <point>15,-400</point> <point>16,-200</point> </reference> <reference name="DEFAULT_MEDIA_VOLUME_CURVE"> <!-- Default Media reference Volume Curve --> <!-- #ifndef OPLUS_BUG_STABILITY //YaJun.Li@PSW.MM.AudioServer.Policy, 2019/08/21 //Modify for headset music min and default volume <point>1,-5800</point> <point>20,-4000</point> <point>60,-1700</point> <point>100,0</point> #else /* OPLUS_BUG_STABILITY */ --> <point>1,-7000</point> <point>5,-6200</point> <point>10,-5700</point> <point>15,-5100</point> <point>20,-4500</point> <point>25,-4000</point> <point>30,-3500</point> <point>35,-3100</point> <point>40,-2700</point> <point>45,-2400</point> <point>50,-2100</point> <point>55,-1700</point> <point>60,-1300</point> <point>65,-1000</point> <point>70,-700</point> <point>75,-400</point> <point>80,-100</point> <!-- #endif /* OPLUS_BUG_STABILITY */ --> </reference> <!-- #ifdef OPLUS_BUG_STABILITY //Qinhui.Gu@PSW.MM.AudioServer.Policy, 2019/12/11, add USB_HEADSET device category for tuning separately --> <reference name="DEFAULT_MEDIA_VOLUME_CURVE_USB_HEADSET"> <!-- USB_HEADSET Media reference Volume Curve --> <point>1,-6400</point> <point>5,-6200</point> <point>10,-5600</point> <point>15,-5000</point> <point>20,-4400</point> <point>25,-3800</point> <point>30,-3400</point> <point>35,-3100</point> <point>40,-2800</point> <point>45,-2500</point> <point>50,-2200</point> <point>55,-1800</point> <point>60,-1500</point> <point>65,-1200</point> <point>70,-800</point> <point>75,-400</point> <point>80,-150</point> </reference> <!-- #endif /* OPLUS_BUG_STABILITY */ --> <reference name="DEFAULT_MEDIA_VOLUME_CURVE_A2DP"> <!-- Default Media reference Volume Curve --> <!-- #ifndef OPLUS_BUG_STABILITY //YaJun.Li@PSW.MM.AudioServer.Policy, 2019/08/21, // Modify for bluetooth headset music min and default volume <point>1,-5800</point> <point>20,-4000</point> <point>60,-1700</point> <point>100,0</point> #else /* OPLUS_BUG_STABILITY */ --> <point>1,-6400</point> <point>5,-5500</point> <point>10,-5000</point> <point>15,-4500</point> <point>20,-4000</point> <point>25,-3700</point> <point>30,-3400</point> <point>35,-3100</point> <point>40,-2800</point> <point>45,-2500</point> <point>50,-2200</point> <point>55,-1800</point> <point>60,-1400</point> <point>65,-1100</point> <point>70,-700</point> <point>75,-400</point> <point>80,-150</point> <!-- #endif /* OPLUS_BUG_STABILITY */ --> </reference> <reference name="DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE"> <!--Default Volume Curve --> <point>1,-4950</point> <point>33,-3350</point> <point>66,-1700</point> <point>100,0</point> </reference> <reference name="DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE"> <!-- Default is Speaker Media Volume Curve --> <!-- #ifndef OPLUS_BUG_STABILITY //YaJun.Li@PSW.MM.AudioServer.Policy, 2019/08/21 //Modify for speaker music default volume for 19065 <point>1,-5800</point> <point>20,-4000</point> <point>60,-1700</point> <point>100,0</point> #else /* OPLUS_BUG_STABILITY */ --> <point>1,-7000</point> <point>5,-5200</point> <point>10,-4500</point> <point>15,-3900</point> <point>20,-3400</point> <point>25,-3000</point> <point>30,-2700</point> <point>35,-2450</point> <point>40,-2150</point> <point>45,-1850</point> <point>50,-1650</point> <point>55,-1350</point> <point>60,-1100</point> <point>65,-800</point> <point>70,-650</point> <point>75,-400</point> <point>80,0</point> <!-- #endif /* OPLUS_BUG_STABILITY */ --> </reference> <reference name="DEFAULT_DEVICE_CATEGORY_EARPIECE_VOLUME_CURVE"> <!--Default Volume Curve --> <point>1,-4950</point> <point>33,-3350</point> <point>66,-1700</point> <point>100,0</point> </reference> <reference name="DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE"> <!-- Default is Ext Media System Volume Curve --> <point>1,-5800</point> <point>20,-4000</point> <point>60,-2100</point> <point>100,-1000</point> </reference> <reference name="DEFAULT_HEARING_AID_VOLUME_CURVE"> <!-- Default Hearing Aid Volume Curve --> <point>1,-12700</point> <point>20,-8000</point> <point>60,-4000</point> <point>100,0</point> </reference> <!-- **************************************************************** --> <!-- Non-mutable default volume curves: --> <!-- * first point is always for index 0 --> <!-- * attenuation is small enough that stream can still be heard --> <reference name="DEFAULT_NON_MUTABLE_VOLUME_CURVE"> <!-- Default non-mutable reference Volume Curve --> <!-- based on DEFAULT_MEDIA_VOLUME_CURVE --> <point>0,-5800</point> <point>20,-4000</point> <point>60,-1700</point> <point>100,0</point> </reference> <reference name="DEFAULT_NON_MUTABLE_HEADSET_VOLUME_CURVE"> <!--Default non-mutable Volume Curve for headset --> <!-- based on DEFAULT_DEVICE_CATEGORY_HEADSET_VOLUME_CURVE --> <point>0,-4950</point> <point>33,-3350</point> <point>66,-1700</point> <point>100,0</point> </reference> <reference name="DEFAULT_NON_MUTABLE_SPEAKER_VOLUME_CURVE"> <!-- Default non-mutable Speaker Volume Curve --> <!-- based on DEFAULT_DEVICE_CATEGORY_SPEAKER_VOLUME_CURVE --> <point>0,-5800</point> <point>20,-4000</point> <point>60,-1700</point> <point>100,0</point> </reference> <reference name="DEFAULT_NON_MUTABLE_EARPIECE_VOLUME_CURVE"> <!--Default non-mutable Volume Curve --> <!-- based on DEFAULT_DEVICE_CATEGORY_EARPIECE_VOLUME_CURVE --> <point>0,-4950</point> <point>33,-3350</point> <point>66,-1700</point> <point>100,0</point> </reference> <reference name="DEFAULT_NON_MUTABLE_EXT_VOLUME_CURVE"> <!-- Default non-mutable Ext Media System Volume Curve --> <!-- based on DEFAULT_DEVICE_CATEGORY_EXT_MEDIA_VOLUME_CURVE --> <point>0,-5800</point> <point>20,-4000</point> <point>60,-2100</point> <point>100,-1000</point> </reference> <reference name="DEFAULT_NON_MUTABLE_HEARING_AID_VOLUME_CURVE"> <!-- Default non-mutable Hearing Aid Volume Curve --> <!-- based on DEFAULT_HEARING_AID_VOLUME_CURVE --> <point>0,-12700</point> <point>20,-8000</point> <point>60,-4000</point> <point>100,0</point> </reference> </volumes> 以上文件路径:/odm/etc/audio/default_volume_tables.xml 一加13 Coloros15,安卓版本15,修改该文件,绕过安卓音频SRC实现系统全局自适应采样率(Dynamic sampling rates)、自适应位深(Bit_perfect)(保持音频文件原始位深,16bit文件不升级位深)、禁用升频和重采样,关闭所有音频音效(effect)以及影响音频质量无损输出的一切音频处理,最大程度上抑制并降低音频抖动(jitter)(最大化优化时钟管理和同步)、最大程度降低音频失真和噪声以及电源纹波和噪声,以输出输入最干净无污染最高质量的HIFI无损原始音频信号直出,输出修改过的完整文件
最新发布
08-12
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <!-- Copyright (c) 2016-2017, 2019, 2021 The Linux Foundation. All rights reserved Not a Contribution. --> <!-- Copyright (C) 2015 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <audioPolicyConfiguration version="7.0" xmlns:xi="http://www.w3.org/2001/XInclude"> <!-- version section contains a “version” tag in the form “major.minor” e.g version=”1.0” --> <!-- Global configuration Decalaration --> <globalConfiguration speaker_drc_enabled="true"/> <!-- Modules section: There is one section per audio HW module present on the platform. Each module section will contains two mandatory tags for audio HAL “halVersion” and “name”. The module names are the same as in current .conf file: “primary”, “A2DP”, “remote_submix”, “USB” Each module will contain the following sections: “devicePorts”: a list of device descriptors for all input and output devices accessible via this module. This contains both permanently attached devices and removable devices. “mixPorts”: listing all output and input streams exposed by the audio HAL “routes”: list of possible connections between input and output devices or between stream and devices. "route": is defined by an attribute: -"type": <mux|mix> means all sources are mutual exclusive (mux) or can be mixed (mix) -"sink": the sink involved in this route -"sources": all the sources than can be connected to the sink via vis route “attachedDevices”: permanently attached devices. The attachedDevices section is a list of devices names. The names correspond to device names defined in <devicePorts> section. “defaultOutputDevice”: device to be used by default when no policy rule applies --> <modules> <module name="primary" halVersion="2.0"> <attachedDevices> <item>Speaker</item> <item>Speaker Safe</item> <item>Earpiece</item> <item>Telephony Tx</item> <item>Built-In Mic</item> <item>Built-In Back Mic</item> <item>Telephony Rx</item> </attachedDevices> <defaultOutputDevice>Speaker</defaultOutputDevice> <mixPorts> <mixPort name="primary output" role="source" flags="AUDIO_OUTPUT_FLAG_PRIMARY AUDIO_OUTPUT_FLAG_FAST"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="raw" role="source" flags="AUDIO_OUTPUT_FLAG_RAW AUDIO_OUTPUT_FLAG_FAST"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="hifi_playback" role="source" /> <mixPort name="deep_buffer" role="source" flags="AUDIO_OUTPUT_FLAG_DEEP_BUFFER"> <profile name="" format="AUDIO_FORMAT_PCM_24_BIT_PACKED" samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="compressed_offload" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD AUDIO_OUTPUT_FLAG_NON_BLOCKING AUDIO_OUTPUT_FLAG_GAPLESS_OFFLOAD"> <profile name="" format="AUDIO_FORMAT_MP3" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/> <profile name="" format="AUDIO_FORMAT_AAC_LC" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/> <profile name="" format="AUDIO_FORMAT_AAC_HE_V1" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000 64000 88200 96000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/> <profile name="" format="AUDIO_FORMAT_AAC_HE_V2" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO AUDIO_CHANNEL_OUT_MONO"/> </mixPort> <mixPort name="voice_tx" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_OUT_MONO AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="mmap_no_irq_out" role="source" flags="AUDIO_OUTPUT_FLAG_DIRECT AUDIO_OUTPUT_FLAG_MMAP_NOIRQ"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="voip_rx" role="source" flags="AUDIO_OUTPUT_FLAG_VOIP_RX"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="incall_music_uplink" role="source" flags="AUDIO_OUTPUT_FLAG_INCALL_MUSIC"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> <mixPort name="primary input" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3"/> </mixPort> <mixPort name="fast input" role="sink" flags="AUDIO_INPUT_FLAG_FAST"> <profile name="" format="AUDIO_FORMAT_PCM_8_24_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3"/> </mixPort> <mixPort name="hifi_input" role="sink" /> <mixPort name="voice_rx" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/> </mixPort> <mixPort name="mmap_no_irq_in" role="sink" flags="AUDIO_INPUT_FLAG_MMAP_NOIRQ"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 11025 12000 16000 22050 24000 32000 44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO AUDIO_CHANNEL_IN_FRONT_BACK AUDIO_CHANNEL_INDEX_MASK_3"/> </mixPort> <mixPort name="voip_tx" role="sink" flags="AUDIO_INPUT_FLAG_VOIP_TX"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="8000 16000 32000 48000" channelMasks="AUDIO_CHANNEL_IN_MONO"/> </mixPort> </mixPorts> <devicePorts> <devicePort tagName="Earpiece" type="AUDIO_DEVICE_OUT_EARPIECE" role="sink"> </devicePort> <devicePort tagName="Speaker" type="AUDIO_DEVICE_OUT_SPEAKER" role="sink"> </devicePort> <devicePort tagName="Speaker Safe" type="AUDIO_DEVICE_OUT_SPEAKER_SAFE" role="sink"> </devicePort> <devicePort tagName="BT SCO" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO" role="sink"> </devicePort> <devicePort tagName="BT SCO Headset" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET" role="sink"> </devicePort> <devicePort tagName="BT SCO Car Kit" type="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT" role="sink"> </devicePort> <devicePort tagName="Telephony Tx" type="AUDIO_DEVICE_OUT_TELEPHONY_TX" role="sink"> </devicePort> <devicePort tagName="USB Device Out" type="AUDIO_DEVICE_OUT_USB_DEVICE" role="sink"> </devicePort> <devicePort tagName="USB Headset Out" type="AUDIO_DEVICE_OUT_USB_HEADSET" role="sink"> </devicePort> <devicePort tagName="BT A2DP Out" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP" role="sink" encodedFormats="AUDIO_FORMAT_LDAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_AAC AUDIO_FORMAT_SBC"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000 88200 96000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </devicePort> <devicePort tagName="BT A2DP Headphones" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES" role="sink" encodedFormats="AUDIO_FORMAT_LDAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_AAC AUDIO_FORMAT_SBC"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000 88200 96000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </devicePort> <devicePort tagName="BT A2DP Speaker" type="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER" role="sink" encodedFormats="AUDIO_FORMAT_LDAC AUDIO_FORMAT_APTX AUDIO_FORMAT_APTX_HD AUDIO_FORMAT_AAC AUDIO_FORMAT_SBC"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000 88200 96000" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </devicePort> <devicePort tagName="Built-In Mic" type="AUDIO_DEVICE_IN_BUILTIN_MIC" role="source"> </devicePort> <devicePort tagName="Built-In Back Mic" type="AUDIO_DEVICE_IN_BACK_MIC" role="source"> </devicePort> <devicePort tagName="BT SCO Headset Mic" type="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET" role="source"> </devicePort> <devicePort tagName="Telephony Rx" type="AUDIO_DEVICE_IN_TELEPHONY_RX" role="source"> </devicePort> <!-- TODO: Enable multi-channel recording --> <devicePort tagName="USB Device In" type="AUDIO_DEVICE_IN_USB_DEVICE" role="source"> </devicePort> <devicePort tagName="USB Headset In" type="AUDIO_DEVICE_IN_USB_HEADSET" role="source"> </devicePort> </devicePorts> <routes> <route type="mix" sink="Earpiece" sources="primary output,raw,deep_buffer,mmap_no_irq_out,voip_rx"/> <route type="mix" sink="Speaker" sources="primary output,raw,deep_buffer,compressed_offload,mmap_no_irq_out,voip_rx"/> <route type="mix" sink="Speaker Safe" sources="primary output,raw,deep_buffer,compressed_offload,mmap_no_irq_out,voip_rx"/> <route type="mix" sink="BT SCO" sources="primary output,raw,deep_buffer,voip_rx"/> <route type="mix" sink="BT SCO Headset" sources="primary output,raw,deep_buffer,voip_rx"/> <route type="mix" sink="BT SCO Car Kit" sources="primary output,raw,deep_buffer,voip_rx"/> <route type="mix" sink="USB Device Out" sources="primary output,raw,deep_buffer,compressed_offload,hifi_playback,mmap_no_irq_out,voip_rx"/> <route type="mix" sink="USB Headset Out" sources="primary output,raw,deep_buffer,compressed_offload,hifi_playback,mmap_no_irq_out,voip_rx"/> <route type="mix" sink="Telephony Tx" sources="voice_tx,incall_music_uplink"/> <route type="mix" sink="primary input" sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In"/> <route type="mix" sink="fast input" sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In"/> <route type="mix" sink="voice_rx" sources="Telephony Rx"/> <route type="mix" sink="hifi_input" sources="USB Device In,USB Headset In" /> <route type="mix" sink="mmap_no_irq_in" sources="Built-In Mic,Built-In Back Mic,USB Device In,USB Headset In"/> <route type="mix" sink="voip_tx" sources="Built-In Mic,Built-In Back Mic,BT SCO Headset Mic,USB Device In,USB Headset In"/> <route type="mix" sink="BT A2DP Out" sources="primary output,deep_buffer,compressed_offload,voip_rx"/> <route type="mix" sink="BT A2DP Headphones" sources="primary output,deep_buffer,compressed_offload,voip_rx"/> <route type="mix" sink="BT A2DP Speaker" sources="primary output,deep_buffer,compressed_offload,voip_rx"/> </routes> </module> <!-- A2DP Input Audio HAL --> <module name="a2dp" halVersion="2.0"> <mixPorts> <mixPort name="a2dp input" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/> </mixPort> </mixPorts> <devicePorts> <devicePort tagName="BT A2DP In" type="AUDIO_DEVICE_IN_BLUETOOTH_A2DP" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100 48000" channelMasks="AUDIO_CHANNEL_IN_MONO AUDIO_CHANNEL_IN_STEREO"/> </devicePort> </devicePorts> <routes> <route type="mix" sink="a2dp input" sources="BT A2DP In"/> </routes> </module> <!-- Usb Audio HAL --> <module name="usb" halVersion="2.0"> <mixPorts> <mixPort name="usb_accessory output" role="source"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </mixPort> </mixPorts> <devicePorts> <devicePort tagName="USB Host Out" type="AUDIO_DEVICE_OUT_USB_ACCESSORY" role="sink"> <profile name="" format="AUDIO_FORMAT_PCM_16_BIT" samplingRates="44100" channelMasks="AUDIO_CHANNEL_OUT_STEREO"/> </devicePort> </devicePorts> <routes> <route type="mix" sink="USB Host Out" sources="usb_accessory output"/> </routes> </module> <!-- Remote Submix Audio HAL --> <xi:include href="r_submix_audio_policy_configuration.xml"/> </modules> <!-- End of Modules section --> <!-- Volume section --> <xi:include href="audio_policy_volumes.xml"/> <xi:include href="default_volume_tables.xml"/> <!-- End of Volume section --> </audioPolicyConfiguration> 以上文件位于:vendor/etc/audio_policy_configuration.xml 一加13 coloros15,修改该文件,绕过安卓音频src实现系统全局自适应采样率、自适应位深(16bit、24bit、32bit齐全,并保持音频文件原始位深)、禁用升频和重采样,关闭所有音频音效(effect)以及影响音频质量无损输出的一切音频处理,并且最大程度上抑制降低音频抖动(jitter)、音频失真和噪声、电源噪声,以输出最干净最高质量的hifi无损原始音频信号直出,输出修改过的完整文件
08-12
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值