织梦CMS - 轻松建站从此开始!

罗索

当前位置: 主页>嵌入式开发>Android>

Android如何找到正确的ALSA底层kcontrol接口?

jackyhwei 发布于 2011-09-24 19:45 点击:次 
Android允许开发者在HAL层实现hw mixer,当AudioFlinger探测到存在hw mixer时,则调用mAudioHardware->setMasterVolume()对volume寄存器进行设置,也不会对volume值进行scale。至于sw mixer如何使用scale值的,我没有深入探究。
TAG:

昨天分析了一把snd_kcontrol,可以认为上层应用的确是通过名称标识name来遍历底层的snd_kcontrol链表,从而找到相匹配的kcontrol。见snd_ctl_find_id函数

  1. /** 
  2.  * snd_ctl_find_id - find the control instance with the given id 
  3.  * @card: the card instance 
  4.  * @id: the id to search 
  5.  * 
  6.  * Finds the control instance with the given id from the card. 
  7.  * 
  8.  * Returns the pointer of the instance if found, or NULL if not. 
  9.  * 
  10.  * The caller must down card->controls_rwsem before calling this function 
  11.  * (if the race condition can happen). 
  12.  */ 
  13. struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, 
  14.                      struct snd_ctl_elem_id *id) 
  15.     struct snd_kcontrol *kctl; 
  16.  
  17.     if (snd_BUG_ON(!card || !id)) 
  18.         return NULL; 
  19.     if (id->numid != 0) 
  20.         return snd_ctl_find_numid(card, id->numid); 
  21.     list_for_each_entry(kctl, &card->controls, list) { 
  22.         if (kctl->id.iface != id->iface) 
  23.             continue
  24.         if (kctl->id.device != id->device) 
  25.             continue
  26.         if (kctl->id.subdevice != id->subdevice) 
  27.             continue
  28.         if (strncmp(kctl->id.name, id->name, sizeof(kctl->id.name))) 
  29.             continue
  30.         if (kctl->id.index > id->index) 
  31.             continue
  32.         if (kctl->id.index + kctl->count <= id->index) 
  33.             continue
  34.         return kctl; 
  35.     } 
  36.     return NULL; 

今天继续跟踪Android音频系统时,发现无论如何都找不到Android与snd_kcontrol的联结点,无论是name还是 numid(alsa_amixer controls打印出来的那个numid,即是内核层snd_kcontrol链表元素的numid)都找不到相关关键字。但是它确实可以进行调节音量 等控制。后来我修改内核的Codec驱动,将音量控制的kcontrol.name换成其他字符串,重新编译,Android还是可以进行音量控制。

看起来有点像是通过numid来控制的,《Android音频HAL移植》一文有提到:“设备的切换就需要和驱动联调。例如,目前earpiece 的id为10,那么就可以通过ALSA的amixer设置earpiece的开和关,以及大小。而id的值就需要做驱动的同事提供。”但是还不能就此肯 定。目前也没有找到保存这些值的脚本文件。

 


继续以上问题,我在调节音量时,打印Codec寄存器的值,发现volume寄存器的值根本不会发生变化,但是音量确确实实是变化的。那时就在怀疑 我们Android的音量调节不是通过硬件来实现的,而是有自身的sw mixer机制。晚上和Vic一起吃饭时,聊起这个,肯定了我的猜测。

  1. status_t AudioFlinger::setMasterVolume(float value) 
  2.     // check calling permissions 
  3.     if (!settingsAllowed()) { 
  4.         return PERMISSION_DENIED; 
  5.     } 
  6.  
  7.     // when hw supports master volume, don't scale in sw mixer 
  8.     AutoMutex lock(mHardwareLock); 
  9.     mHardwareStatus = AUDIO_HW_SET_MASTER_VOLUME; 
  10.     if (mAudioHardware->setMasterVolume(value) == NO_ERROR) { 
  11.         value = 1.0f; 
  12.     } 
  13.     mHardwareStatus = AUDIO_HW_IDLE; 
  14.  
  15.     mMasterVolume = value; 
  16.     for (uint32_t i = 0; i < mPlaybackThreads.size(); i++) 
  17.        mPlaybackThreads.valueAt(i)->setMasterVolume(value); 
  18.  
  19.     return NO_ERROR; 

应该是Android允许开发者在HAL层实现hw mixer,当AudioFlinger探测到存在hw mixer时,则调用mAudioHardware->setMasterVolume()对volume寄存器进行设置,也不会对volume值 进行scale。至于sw mixer如何使用scale值的,我没有深入探究。

以后实现hw mixer看看(反正到时也要实现EQ)效果,现在这个音量设置不是线性的,用硬件控制应该更好一点。

PS:标题就不用管它了,默认下Android根本不去找底层的kcontrol接口,而是使用自身的sw mixer。

(sepnic)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201109/15040.html]
本文出处:blog.csdn.net/sepnic 作者:sepnic
顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容