Android 框架層錄音音量調節功能引入

    錄音音量安卓系統本身並未提供相關接口,同時錄音音量調節也需要硬件的支持。如果硬件支持,是可以實現的。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.c
index 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,框架層部分基本完成了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章