Sprd 9832A Android6.0 FM模式下的幾種Audio路徑以及非原生FM的音量調節

一.FM三種模式下的Audio路徑

先放兩張圖:
圖一:sprd9832A的Audio部分的框圖
sprd9832A的Audio部分的框圖
圖二:三種FM模式Audio路徑框圖
三種FM模式Audio路徑框圖
下面說的內容,會用到上面這兩張圖。

模式1:Line_in-Codec Loop(模擬FM)

先看一下,AudioTester上面顯示的框圖(下圖主機處於耳機模式“Headset”),圖三
在這裏插入圖片描述
可以看到,藍色的路徑,FM的信號是從Codec進來之後,直接又從Codec播放出去;紅色的路徑,FM信號從Codec給到主控,這個是錄音的通道,對應文章開始圖二中紅色箭頭的路徑;

再看下圖,詳細給出了Codec的模塊的路徑,圖四
在這裏插入圖片描述
可以看到,FM的信號是從“AIL/AIR”接口輸入,類似於MIC的輸入,然後通過“FM record path”給到主控錄音,通過“FM playback patch”直接輸出。

圖三AudioTester工具中,看到的Codec部分可以調節增益的地方,在上圖有清晰的體現;VBC部分可以調節增益的地方,在 圖一和圖二 中也有清晰的體現。

模式2:Line_in-VBC-Codec Loop(模擬FM)

看一下,AudioTester上面顯示的框圖(下圖主機處於耳機模式“Headset”),圖五
在這裏插入圖片描述
可以看到,和“模式1”對比,主要差別是,藍色的播放路徑,先經過了“VBC”模塊,然後才進入Codec播放出去,對應文章開始圖二中棕色箭頭的路徑。

然後在“VBC”模塊中,多了一個可以調節增益的地方“ST”,可以在圖一和圖二中看到“ST”所處的位置,更詳細的看下圖紅框處, 圖六
在這裏插入圖片描述
所以,其實圖五中的“ST”就是“VBC”單元中的“Side Tone”模塊,這個模塊有15個音量等級,文章後面會講到。

模式3: Digital FM-VBC-Codec Loop(數字FM)

再看一下,AudioTester上面顯示的框圖(下圖主機處於耳機模式“Headset”),圖七
在這裏插入圖片描述
可以看到,和之前兩種模式對比,FM的輸入源改變了,直接數字信號輸入,不經過Codec了,對應文章開始圖二中藍色箭頭的路徑。

二.非原生FM的音量調節

我做的車載項目,使用的是“模式3”這種數字FM,因爲FM的輸出音源,都不會經過系統,所以,系統裏面音源的音量調節對於FM沒有作用。比如,當收聽FM的時候,同時有導航播報,此時需要減小FM音量,讓導航音量正常出來,這種情況。

一開始,我調了Codec這邊的RX_PGA和CG的增益,這個是調節耳機通道的模擬輸出增益,發現導航和FM的音量同時都減小了,並且這種修改,無法在程序運行時動態修改,這樣是不行的。

然後,我看到“ST”這裏,這裏FM的音源輸入之後,還沒有混入系統音源輸出,並且看到這個“ST”有15個level等級,都可以調節增益,如下圖, 圖八
在這裏插入圖片描述
我猜測,這裏就是調節FM音量的地方,但是,當我用工具調節了這裏的增益之後,並沒有效果,我估計,程序裏面應該有一個可以調節這裏的接口,可能因爲沒有使用原生FM,沒有調用到這個接口,所以工具調節這裏沒有作用。

查看原生FM代碼,找到如下代碼片段:

    public boolean setVolume(int volume) {
        boolean value = false;
        Log.d(TAG, "setVolume FM_Volume=" + volume);
        if (mIsDeviceOpen) {
            if (0 == volume) {
                mFmManager.setMute(true);
            } else {
                mFmManager.setMute(false);
            }
            mAudioManager.setParameter("FM_Volume", "" + volume);
            mFmManager.setVolume(volume);
            value = true;
        }
        return value;
    }

其中有這一行mAudioManager.setParameter("FM_Volume", "" + volume);,追蹤關鍵字FM_Volume,找到如下函數:

static int adev_set_parameters(struct audio_hw_device *dev, const char *kvpairs)
{
	...
	ret = str_parms_get_str(parms, "FM_Volume", value, sizeof(value));
	...
	SetAudio_gain_fmradio(adev,fm_gain);
	...
}

找到函數SetAudio_gain_fmradio,如下:

static int SetAudio_gain_fmradio(struct tiny_audio_device *adev, uint32_t gain)
{
    audio_pga_apply(adev->pga,gain,"digital-fm");
    return 0;
}

可以看到,上面函數audio_pga_apply設置了“digital-fm”的增益,再追下去:

int audio_pga_apply(struct audio_pga *pga, int val, const char *name)
{
	struct pga_profile *profile = NULL;
	int i;

	if (!pga) {
		ALOGE("PGA is NULL");
		return -1;
	}

	ALOGD("'%s' apply", name);

	profile = profile_get_by_name(pga, name);
	if (!profile) {
		ALOGE("Profile name '%s' is not exists", name);
		return -1;
	}

	for (i = 0; i < profile->length; i++) {
		audio_pga_set(profile->item[i].ctl, (val >> profile->item[i].bit),
				attribute_get_by_ctl(&pga->attribute, profile->item[i].ctl));
	}

	return 0;
}

這裏可以看到,這個函數是通過“name”去設置不同的模塊的增益,可以看到源碼裏有很多用這個函數設置增益的地方,比如:

 //設置speaker輸出增益
 audio_pga_apply(adev->pga,pga_gain_nv->dac_pga_gain_l,"speaker-l");
 audio_pga_apply(adev->pga,pga_gain_nv->dac_pga_gain_r,"speaker-r");
 //設置MIC輸入增益
 audio_pga_apply(adev->pga,pga_gain_nv->adc_pga_gain_l,"capture-l");
 audio_pga_apply(adev->pga,pga_gain_nv->adc_pga_gain_r,"capture-r");

看到這裏,現在還不能確定,上面的程序接口是否可以調整“Side Tone”模塊的增益,也沒有資料去確認這一點,只能直接調用一下這個接口測試一下了。

在FM里加入測試接口,調動mAudioManager.setParameter("FM_Volume", "" + volume);這個方法,volume值先給了0~100,然後在函數audio_pga_apply里加了log打印,編譯測試。

結果OK,每次調用mAudioManager.setParameter的時候,就會調用audio_pga_apply函數,其參數name = "digital-fm",然後“volume”值的有效範圍是0~16,0的話直接FM靜音,之後有15個音量等級,和 圖八 顯示的“Side Tone”等級吻合。

我推測的結論是,mAudioManager.setParameter("FM_Volume", "" + volume);最終設置的就是“Side Tone”模塊的音量等級的增益,不過由於沒有原廠支持,也沒有更詳細的資料,所以,沒法再去百分百確認,不過,我需要的功能是可以實現了!

遺留問題點

雖然使用mAudioManager.setParameter("FM_Volume", "" + volume);可以調節FM音量,但是操作比較麻煩,尤其和導航混音的時候,所以本來想設置mAudioManager.setParameter("FM_Volume", "" + 0);,讓FM的playback路徑靜音,然後通過record路徑把FM音源錄入系統,再像播放音樂一樣播放出來,這樣修改了之後,FM確實可以播放,和導航的音源在系統裏混音之後,可以很方便的調節彼此的音量,但是,發現,MIC不起作用了,看圖二可以看到,FM的錄音和MIC的錄音是從同一個路徑進去的,所以系統可能在FM錄音的時候,忽略了MIC的聲音或者禁止了MIC,這個應該屬於系統Audio部分錄音的策略問題,最後評估了一下,放棄了這種方式,這個問題也只能等以後有機會再看了!

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