Android 框架层录音音量调节功能引入

来源:互联网 发布:rs485 传输的数据样例 编辑:程序博客网 时间:2024/06/05 00:10

    录音音量安卓系统本身并未提供相关接口,同时录音音量调节也需要硬件的支持。如果硬件支持,是可以实现的。share一下的我的方案。

先说一下思路,对于驱动来说,仅仅是调节相关ctl值就可以了。如此以来,可以看到和paly back的音量调节会有很大区别,play back调节音量,在policy startoutput时,会getVolume,音量的生效是在audioflinger 做mix时,将音量计算到音频波形中。所以,对于录音音量调节,我们需要把上层设置音量数值,直接给kernel就ok了。

1.来看驱动的支持

diff --git a/kernel/sound/soc/codecs/rk616_codec.c b/kernel/sound/soc/codecs/rk616_codec.cindex 831bb24..0d6949f 100755--- a/kernel/sound/soc/codecs/rk616_codec.c+++ b/kernel/sound/soc/codecs/rk616_codec.c@@ -1940,6 +1940,14 @@ static const struct snd_kcontrol_new rk616_snd_path_controls[] = {        */        SOC_ENUM_EXT("Modem Input Enable", rk616_modem_input_type,                rk616_modem_input_get, rk616_modem_input_put),+        SOC_SINGLE_TLV("PGAL Capture Volume", RK616_PGAL_CTL,+                RK616_PGA_VOL_SFT, 31, 0, pga_vol_tlv),//0x0a bit 5 is 0+        {+                .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PGAL Capture Switch", \+                .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\+                .put = snd_soc_put_pgal_volsw, \+                .private_value =  SOC_SINGLE_VALUE(RK616_PGAL_CTL, RK616_PGA_MUTE_SFT, 1, 1)+        }, };

2.HAL 层 通过setparameter 完成,记录volume值,在inputstream open时,设置给ctl.

setParameter:    if (param.getInt(String8(SET_INPUT_VOLUME),cVolume) == NO_ERROR){        if (openMixer_l() != NULL){ALOGV("WZ :SET_INPUT_VOLUME truth value: %d",cVolume);            //caculate the truth input volume            if (cVolume <= 0){                cVolume = 0;            }else if(cVolume >= 10){                cVolume = 10;            }            if (cVolume == 0){ALOGV("SET_INPUT_VOLUME value: %d,we need mute",cVolume);//TODO: if future we can setInputVolume while recording,we need setMicMute here//setMicMute(true);}else{    //setMicMute(false);                cVolume *= 3;}            ALOGV("SET_INPUT_VOLUME truth value: %d",cVolume);            struct mixer_ctl * cvCtrl = mixer_get_control(mMixer, "PGAL Capture Volume", 0);            mixer_ctl_set_int(cvCtrl,(long long) cVolume);mInputVolume = cVolume;        }else{            ALOGE("WZ :SET_INPUT_VOLUME openMixer fail");}    }

AudioInputStream::open_l

struct mixer_ctl * cvCtrl = mixer_get_control(mMixer, "PGAL Capture Volume", 0);mixer_ctl_set_int(cvCtrl,(long long) mHardware->mInputVolume);    //adjust input stream volume, mute mic    if (mHardware->mInputVolume == 0){       setGain(0.0);}

3.关于框架层,两个方面,一个是需要设置时在系统setting 数据库中保存,再一个在audioservice服务利用AudioSystem setparameter实现。

安卓本身音频框架中,设置播放音量,AudioService :: setStreamVolumeIndex->AudioSystem->AudioPolicyService->AudioPolicy完成。

来看具体实现:

1)获取音量:

    /** @see AudioManager#getInputVolume() */    public int getInputVolume(){         readInputVolumeSettings();//从数据库读取 return mInputVolume;    }
2)设置音量

    /** @see AudioManager#setInputVolume(int) */    public void setInputVolume(int index) {        sendMsg(mAudioHandler,        MSG_PERSIST_SET_INPUT_VOLUME,        SENDMSG_QUEUE,        index,        0,        null,        0);AudioSystem.setParameters("set_input_volume="+index);mInputVolume = index;Log.d(TAG,"setInputVolume mInputVolume: " + index);}

再者就是,添加接口到frameworks/base/media/java/android/media/IAudioService.aidl,在audiomanager中为上层app提供接口,ok,框架层部分基本完成了。

1 0
原创粉丝点击