1、dirac 库的模块图
1.1 Dirac_Initialize
S32 Dirac_Initialize (ESelectedFilter selectedFilter, U32 applicationId);该函数用于DiracLib的初始化,必须最先被调用。参数selectedFilter是一个枚举类型,有效的取值范围定义在dirac.h中,例如:
enum ESelectedFilter_tag
{
My_first_earphone_44k,
My_second_earphone_44K,
My_speaker_44K,
};
则参数可以等于My_first_earphone_44k,My_second_earphone_44K以及My_speaker_44K这三者其中之一,表示针对特定的播放设备进行音效优化。在系统运行过程中,可以使用新的参数来重新调用该初始化函数,以便调整优化效果,或者切换到另一种播放设备。
返回值:0 --> 初始化成功;Others --> 不支持的参数。
1.2 Dirac_Convert
S32 Dirac_Convert (S16 *inbuffer, S16 *outbuffer, U32 bufSize, U32 mode, S32 volume_dB, U32 applicationId);该函数用于对一个16-bit采样的音频数据块进行优化。目前只支持16-bit采样的数据。参数:
inbuffer:指向输入数据块首地址的指针。
outbuffer:指向输出数据块首地址的指针,必要时可以等于inbuffer,即允许输出数据覆盖输入数据块。
bufSize:数据块中的16-bit采样个数。对于stereo来说,指的是两个声道的采样总数。
mode:0 --> 输入单声道数据,输出单声道数据;
1 --> 输入立体声数据,对左右声道混音之后作为单声道处理并输出;
2 --> 输入立体声数据,输出立体声数据。
volume_dB:该参数用于确保输出音量的峰值不会大于volume_dB,取值范围是0 ~ -40。如果输入信号的音量未知或者未经设定,volume_dB可以取0;否则volume_dB可以等于输入信号所设定的音量。
备注:
1)先调用该函数处理一段音频数据,然后再播放该段音频,以达到改善音质的目的。
2)bufSize的大小(即每次处理多少个采样)可根据实际情况选择,使得声音不出现中断。
3)若有Digital Volume Control,应尽量在调用Dirac_Convert()之后进行,以提高信噪比。
4)对于立体声音频,左右声道的采样数据在数据块中应该是交替排列的(PCM格式)。
5)经过该函数处理之后,输出数据的音量大约会降低6dB左右。
返回值:0 --> 处理成功;-1 --> DiracLib未初始化;-2 --> 不支持的参数。
1.3 Dirac_Enable
void Dirac_Enable (U32 applicationId);该函数允许Dirac_Convert()对音频数据进行优化处理。缺省状态为允许。
1.4 Dirac_Disable
void Dirac_Disable (U32 attenuation_dB, U32 applicationId);该函数禁止Dirac_Convert()对音频数据进行优化处理。此时,Dirac_Convert()处于Bypass状态,但仍会将输入数据的音量降低,以便和正常工作模式下的音量保持一致。具体降低的幅度由参数attenuation_dB指定,有效的取值范围为0(dB) ~ 12(dB)。
当暂时不需要Dirac_Convert()对音频数据进行优化处理时,请调用Dirac_Disable()以便使Dirac_Convert()进入Bypass状态,而不是把Dirac_Convert()整个屏蔽掉,因为这将可能导致音量发生变化。
参数:attenuation_dB,当播放设备为耳机时,建议取值为9;当播放设备为外放时,建议取值为1。
2、调试流程步骤
2.1 代码路径(示例:添加dirac驱动 )
\alps\wingcust\wt93007\base\config \ProjectConfig.mk
\alps\mediatek\platform\common\hardware\audio\aud_drv\AudioMTKStreamManager.cpp
\alps\mediatek\platform\common\hardware\audio\include\ AudioMTKStreamManager.h
\alps\mediatek\platform\mt6589\hardware\audio\aud_drv\AudioMTKHardware.cpp
\alps\mediatek\platform\mt6589\hardware\audio\aud_drv\AudioMTKHardware.h
\alps\mediatek\platform mt6589\hardware\audio\aud_drv\AudioMTKStreamOut.cpp
\alps\mediatek\platform mt6589\hardware\audio\aud_drv\AudioMTKStreamOut.h
\alps\mediatek\platform\mt6589\hardware\audio\Android.mk
2.2 程序配置
1)流管理源文件修改:\alps\mediatek\platform\common\hardware\audio\aud_drv\AudioMTKStreamManager.cpp
增加函数SetDiracEnable,GetDiracEnable:
status_t AudioMTKStreamManager::SetDiracEnable(int value)
{
ALOGD("XXXXXXX SetDiracEnableSM = %d",value);
if (mStreamOutVector.size()) {
for (size_t i = 0; i < mStreamOutVector.size() ; i++) {
AudioMTKStreamOut *pTempOut = (AudioMTKStreamOut *)mStreamOutVector.valueAt(i);
pTempOut->SetDiracEnable(value);
}
}
return NO_ERROR;
}
int AudioMTKStreamManager::GetDiracEnable()
{
if (mStreamOutVector.size())
{
for (size_t i = 0; i < mStreamOutVector.size() ; i++) {
AudioMTKStreamOut *pTempOut = (AudioMTKStreamOut *)mStreamOutVector.valueAt(i);
int dirac_status = pTempOut->GetDiracEnable();
if (dirac_status)
{
return dirac_status;
}
}
return 0;
}
}
2)流管理配置头文件:\alps \mediatek\platform\common\hardware\audio\include\ AudioMTKStreamManager.h
virtual status_t SetDiracEnable(int value);
virtual int GetDiracEnable();
3)audio硬件 HAL层修改:\alps \mediatek\platform\mt6589\hardware\audio\aud_drv\AudioMTKHardware.cpp
ð setParameters(const String8 &keyValuePairs)
{
if (param.getInt(keyDirac, value) == NO_ERROR) {
param.remove(keyDirac);
//Do nothing for this command .
((AudioMTKStreamManager*)mAudioMTKStreamManager)->SetDiracEnable(value);
goto EXIT_SETPARAMETERS;
}
}
4)流输出源文件修改:\alps \mediatek\platform mt6589\hardware\audio\aud_drv\AudioMTKStreamOut.cpp
AudioMTKStreamOut(uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
{
char value[32];
property_get("persist.af.dirac.status", value, "1");
mDiracEnable = atoi(value);
mIsSet = 1;
mIsSpeakerOld = 1;
mIsSpeakerNew = 1;
ALOGD("XXXXXXX AudioMTKStreamOut mDiracEnable= %d\n", mDiracEnable);
}
void AudioMTKStreamOut:iracInitialize(void)
{
const uint32_t this_device = mAudioResourceManager->getDlOutputDevice();
if(mDiracEnable)
{
size_t retInit;
if((this_device & AUDIO_DEVICE_OUT_SPEAKER)&&((this_device & AUDIO_DEVICE_OUT_WIRED_HEADSET)||(this_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE)))
{
ALOGD("XXXXXXX Dirac_HDSound_SetBypassAttenuation-1 getDlOutputDevice = %d\n", this_device);
Dirac_Disable(0);
//Dirac_HDSound_SetBypassAttenuation(0,0);
}
else if ((this_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE)||(this_device & AUDIO_DEVICE_OUT_WIRED_HEADSET))
{
if(1 == mDiracEnable)
{
retInit = Dirac_Initialize (Earphone_MEP100_44k, 0);
ALOGD("XXXXXXX DiracInitialize Earphone_MEP100_44k = %d, getDlOutputDevice = %d\n", retInit, this_device);
}
else if(2 == mDiracEnable)
{
retInit = Dirac_Initialize (Earphone_MEP200_44k, 0);
ALOGD("XXXXXXX DiracInitialize Earphone_MEP200_44k = %d, getDlOutputDevice = %d\n", retInit, this_device);
}
else if(3 == mDiracEnable)
{
retInit = Dirac_Initialize (Earphone_PISTON100_44k, 0);
ALOGD("XXXXXXX DiracInitialize Earphone_PISTON100_44k = %d, getDlOutputDevice = %d\n", retInit, this_device);
}
else if(4 == mDiracEnable)
{
retInit = Dirac_Initialize (Earphone_PISTON200_44k, 0);
ALOGD("XXXXXXX DiracInitialize Earphone_PISTON200_44k = %d, getDlOutputDevice = %d\n", retInit, this_device);
}
Dirac_Enable(0);
}
else if (this_device & AUDIO_DEVICE_OUT_SPEAKER)
{
retInit = Dirac_Initialize (Speaker_44k, 0);
ALOGD("XXXXXXX DiracInitialize Speaker_44k = %d, getDlOutputDevice = %d\n", retInit, this_device);
Dirac_Enable(0);
//Dirac_MaxSPL_SetVolumeBoost(6,0);
}
else
{
ALOGD("XXXXXXX Dirac_HDSound_SetBypassAttenuation getDlOutputDevice = %d\n", this_device);
Dirac_Disable(0);
//Dirac_HDSound_SetBypassAttenuation(0,0);
}
}
else
{
if((this_device & AUDIO_DEVICE_OUT_WIRED_HEADSET)||(this_device & AUDIO_DEVICE_OUT_WIRED_HEADPHONE))
{
ALOGE("XXXXXXX Dirac_HDSound_SetBypassAttenuation(3) mDiracEnable = %d,\n", mDiracEnable);
Dirac_Disable(0);
//Dirac_HDSound_SetBypassAttenuation(4,0);
}
}
}
status_t AudioMTKStreamOut::SetDiracEnable(int value)
{
char diracValue[32];
mIsSet = 1;
mDiracEnable = value;
sprintf(diracValue, "%d", mDiracEnable);
ALOGD("XXXXXXX SetDiracEnable diracValue= %s\n", diracValue);
property_set("persist.af.dirac.status", diracValue);
return NO_ERROR;
}
int AudioMTKStreamOut::GetDiracEnable(void)
{
ALOGD("XXXXXXX GetDiracEnable mDiracEnable= %d\n", mDiracEnable);
return mDiracEnable;
}
WriteDataToAudioHW(const void *buffer, size_t bytes)
{
{
if (mIsSet || isSwitch)
{
mIsSet = 0;
isSwitch = 0;
DiracInitialize();
}
uint32_t retConvert;
retConvert = Dirac_Convert_integer((S16 *)inbuffer, (S16 *)inbuffer, bytes/2, 2, 0, 0);
//ALOGD("XXXXXXX after Dirac_Convert_integer, bytes = %d, retConvert = %d\n", bytes, retConvert);
}
}
5)流输出头文件修改:\alps \mediatek\platform\mt6589\hardware\audio\aud_drv\AudioMTKStreamOut.h
#include "dirac_types.h"
#include "dirac.h"
status_t SetDiracEnable(int value);
int GetDiracEnable(void);
void DiracInitialize(void);
增加dirac库的头文件,dirac_types.h,dirac.h,DiracLib_test3.a 到\alps \mediatek\platform\mt6589\hardware\audio\aud_drv\ 目录下
6)修改makefile:\alps \mediatek\platform\mt6589\hardware\audio\Android.mk
增加下面一行:LOCAL_LDFLAGS := $(LOCAL_PATH)/aud_drv/DiracLib_test3.a