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部分录音的策略问题,最后评估了一下,放弃了这种方式,这个问题也只能等以后有机会再看了!

发布了11 篇原创文章 · 获赞 4 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_21059825/article/details/88866300