AndroidTV:Mstar平台AudioPath及声音曲线配置-飞外

一、Audio Path配置

在HW 修改电路之后,SW 通常也需要重新修改匹配硬件,这样才能保证功能的正常使用。

下面以VGA 通过的line-lin 为例:

从原理图上看,VGA通道的PC audio in 是属于芯片端的pin 脚是Y3,AA4,对应的 port 是line-in 第 0 路。

mstar 平台 audio 的映射关系包含audio in,audio out,以及内部 audio mux。对应的是board.h 文件中的三个结构体:

// audio-in , 右侧对应的是通道,左侧是对应的声音进入的port static AudioMux_t BOARD_AudioMux_t[BOARD_AUDIO_INPUT_SOURCE_TYPE_SIZE] = {AUDIO_DSP1_DVB_INPUT}, //AUDIO_SOURCE_DTV {AUDIO_DSP1_DVB_INPUT}, //AUDIO_SOURCE_DTV2 {AUDIO_DSP4_SIF_INPUT}, //AUDIO_SOURCE_ATV {AUDIO_AUIN4_INPUT}, //AUDIO_SOURCE_PC {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_YPbPr {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_YPbPr2 {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_AV {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_AV2 {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_AV3 {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_SV {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_SV2 {AUDIO_AUIN4_INPUT}, //AUDIO_SOURCE_SCART {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_SCART2 {AUDIO_HDMI_INPUT}, //AUDIO_SOURCE_HDMI {AUDIO_HDMI_INPUT}, //AUDIO_SOURCE_HDMI2 {AUDIO_HDMI_INPUT}, //AUDIO_SOURCE_HDMI3 {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_DVI {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_DVI2 {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_DVI3 {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_KTV// audio mux,右侧对应的通道也即input source,左侧对应的是耳机/喇叭的port static AudioMux_t BOARD_AudioPath_t[BOARD_AUDIO_PATH_TYPE_SIZE] = {AUDIO_T3_PATH_I2S}, //AUDIO_PATH_MAIN_SPEAKER {AUDIO_T3_PATH_AUOUT1}, //AUDIO_PATH_HP {AUDIO_T3_PATH_AUOUT0}, //AUDIO_PATH_LINEOUT {AUDIO_PATH_NULL}, //AUDIO_PATH_SIFOUT {AUDIO_PATH_NULL}, //AUDIO_PATH_SCART1 = SIF out {AUDIO_T3_PATH_AUOUT0}, //AUDIO_PATH_SCART2 = Lineout {AUDIO_T3_PATH_SPDIF}, //AUDIO_PATH_SPDIF {AUDIO_PATH_NULL}, //AUDIO_PATH_HDMI {AUDIO_T3_PATH_MIXER_MAIN}, // AUDIO_PATH_MIXER_MAIN {AUDIO_T3_PATH_MIXER_SECONDARY}, // AUDIO_PATH_MIXER_SECONDARY {AUDIO_PATH_NULL}, // AUDIO_PATH_7 {AUDIO_T3_PATH_MIXER_DMA_IN}, // AUDIO_PATH_MIXER_DMA_IN// audio-out, 是输出path 的选择static AudioOutputType_t BOARD_AudioOutputType_t[BOARD_AUDIO_OUTPUT_TYPE_SIZE] = {AUDIO_I2S_OUTPUT}, //AUDIO_PATH_MAIN_SPEAKER {AUDIO_AUOUT1_OUTPUT}, //AUDIO_PATH_HP {AUDIO_AUOUT0_OUTPUT}, //AUDIO_PATH_LINEOUT {AUDIO_NULL_OUTPUT}, //AUDIO_PATH_SIFOUT {AUDIO_NULL_OUTPUT}, //AUDIO_PATH_SCART1 = SIF out {AUDIO_AUOUT0_OUTPUT}, //AUDIO_PATH_SCART2 = Lineout};

从上面的信息可以看到,line-in 里面AUDIO_AUIN0_INPUT port 对应了YPBPR,AV,DVI,DVI2,DVI3 几个通道,未看到VGA通道,配置audio in, out ,mux 信息之后,需要在系统中生效就必须初始化,设置到寄存器中去,继续查到找到三个结构体,分别保存在systeminfo模块的m_pAudioMuxInfo,m_pAudioPathInfo,m_pAudioOutputTypeInfo三个成员中,通过下面接口获取:

@vendormstarsupernovaprojectssysteminfosrcSystemInfo.cppconst AudioMux_t* SystemInfo::GetAudioInputMuxInfo() if(m_pAudioMuxInfo != NULL) return m_pAudioMuxInfo; ASSERT(0);const AudioPath_t* SystemInfo::GetAudioPathInfo() if(m_pAudioPathInfo != NULL) return m_pAudioPathInfo; ASSERT(0);const AudioOutputType_t* SystemInfo::GetAudioOutputTypeInfo() if(m_pAudioOutputTypeInfo != NULL) return m_pAudioOutputTypeInfo; ASSERT(0);}

接着在_InputSourceTypeToAudioInputType(vendormstarsupernovaprojectscustomizationMStarSDKaudiomapi_audio_customer.cpp)接口中获取,根据通道进行设置:

static AUDIO_INPUT_TYPE _InputSourceTypeToAudioInputType(MAPI_INPUT_SOURCE_TYPE eSourceType) const AudioMux_t* const p_AudioInputMux = mapi_syscfg_fetch::GetInstance()- GetAudioInputMuxInfo(); AUDIO_INPUT_TYPE eAudioInputType = AUDIO_NULL_INPUT; MAPI_U32 u32Port = 0xFF; switch(eSourceType) case MAPI_INPUT_SOURCE_DTV: u32Port = p_AudioInputMux[MAPI_AUDIO_SOURCE_DTV].u32Port; break; ........ case MAPI_INPUT_SOURCE_YPBPR: u32Port = p_AudioInputMux[MAPI_AUDIO_SOURCE_YPBPR].u32Port; break; case MAPI_INPUT_SOURCE_YPBPR2: u32Port = p_AudioInputMux[MAPI_AUDIO_SOURCE_YPBPR2].u32Port; break; case MAPI_INPUT_SOURCE_VGA: case MAPI_INPUT_SOURCE_VGA2: case MAPI_INPUT_SOURCE_VGA3: u32Port = p_AudioInputMux[MAPI_AUDIO_SOURCE_PC].u32Port; break; case MAPI_INPUT_SOURCE_HDMI: case MAPI_INPUT_SOURCE_HDMI2: case MAPI_INPUT_SOURCE_HDMI3: case MAPI_INPUT_SOURCE_HDMI4: u32Port = p_AudioInputMux[MAPI_AUDIO_SOURCE_HDMI].u32Port; break; case MAPI_INPUT_SOURCE_DVI: u32Port = p_AudioInputMux[MAPI_AUDIO_SOURCE_DVI].u32Port; break; ...... eAudioInputType = _u32PortToAudioInputType(u32Port); return eAudioInputType;}

到这里可以发现VGA,VGA2,VGA3 使用的是 audio in 结构体中的source (MAPI_AUDIO_SOURCE_PC) 对应的的port :

diff --git a/serials/MST160D_10ABQM_18443_DTMB_AH/Board.h b/serials/MST160D_10ABQM_18443_DTMB_AH/Board.hindex 24b27d5..da095f1 100755--- a/serials/MST160D_10ABQM_18443_DTMB_AH/Board.h+++ b/serials/MST160D_10ABQM_18443_DTMB_AH/Board.h@@ -820,7 +820,7 @@ static AudioMux_t BOARD_AudioMux_t[BOARD_AUDIO_INPUT_SOURCE_TYPE_SIZE] = {AUDIO_DSP1_DVB_INPUT}, //AUDIO_SOURCE_DTV {AUDIO_DSP1_DVB_INPUT}, //AUDIO_SOURCE_DTV2 {AUDIO_DSP4_SIF_INPUT}, //AUDIO_SOURCE_ATV- {AUDIO_AUIN4_INPUT}, //AUDIO_SOURCE_PC+ {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_PC {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_YPbPr {AUDIO_NULL_INPUT}, //AUDIO_SOURCE_YPbPr2 {AUDIO_AUIN0_INPUT}, //AUDIO_SOURCE_AV

因此将AUDIO_AUIN4_INPUT 换成AUDIO_AUIN0_INPUT 即可。

如果 speaker 和 headphone 同一路硬件输出,优先以speaker 为主,同时AUDIO_OUTPUT_HP 的audio path 可以配置为NULL。

更多mstar 平台音频属性,音效设置详参文件:drvAUDIO_if.h,mapi_audio_datatype.h,apiAUDIO.h,mapi_audio.h,mapi_audio_customer.cpp,mapi_audio.cpp,MSrv_SSSound.cpp

二、声音曲线配置

mstar平台在配置完音频通道,调通功放后,需要调整声音曲线和声音功率。声音功率是调整音量逻辑最大值(100)时,喇叭(负载)功率的最大值,而声音曲线是音量0 ~ 100 整个区间,对应的音频输出的增益大小,所以声音功率调试也是曲线调试的一部分。

(1)增益寄存器

例如,我当前平台音频输出对应的bank 是0x112D

其中,音频输出通道有6个,如下

两个寄存器组成16 位,来完成增益值的配置。

(2)增益调整
从上面的excel表格中,可以知悉每个音频通道的增益调整的寄存器的16个bit位。接好喇叭(负载的阻值要和客户要求一样,例如;8欧姆),播放1KHZ -12 db 的音源,接上示波器量负载电压。

最大功率调整:将电视音量调整到最大值100,再调整对应输出通道寄存器值,观察电压变化,并计算功率,达到客户要求的功率为止。

曲线调整:最大功率就是音量为100时,寄存器的增益值。接着在调整0~99区间对应的增益值。

(3)音频曲线配置

在customer_1.ini 中配置

TypeID = 5;[VolumeCurve]bEnabled = TRUE;u8Volume_Int[101] =  INT_LINE1,  INT_LINE2,  INT_LINE3,  INT_LINE4,  INT_LINE5,  INT_LINE6,  INT_LINE7,  INT_LINE8,  INT_LINE9,  INT_LINEa,  INT_LINEb  u8Volume_Fra[101] =  FRA_LINE1,  FRA_LINE2,  FRA_LINE3,  FRA_LINE4,  FRA_LINE5,  FRA_LINE6,  FRA_LINE7,  FRA_LINE8,  FRA_LINE9,  FRA_LINEa,  FRA_LINEb  };

数组中的宏可以根据不同功放进行客制化参数配置,如:

INT_LINE1=0x7FINT_LINE2='0x46,0x42,0x40,0x3E,0x3C,0x3a,0x38,0x36,0x34,0x32'INT_LINE3='0x30,0x2E,0x2D,0x2C,0x2B,0x2A,0x29,0x28,0x27,0x26'INT_LINE4='0x25,0x24,0x23,0x22,0x21,0x20,0x1F,0x1E,0x1E,0x1D'INT_LINE5='0x1D,0x1C,0x1C,0x1B,0x1B,0x1A,0x1A,0x19,0x19,0x18'INT_LINE6='0x18,0x17,0x17,0x16,0x16,0x15,0x15,0x15,0x14,0x14'INT_LINE7='0x14,0x14,0x13,0x13,0x13,0x13,0x12,0x12,0x12,0x12'INT_LINE8='0x11,0x11,0x11,0x11,0x10,0x10,0x10,0x10,0x0F,0x0F'INT_LINE9='0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0E,0x0E,0x0E,0x0E'INT_LINEa='0x0E,0x0E,0x0E,0x0E,0x0D,0x0D,0x0D,0x0D,0x0D,0x0D'INT_LINEb='0x0D,0x0D,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C'FRA_LINE1=0x00FRA_LINE2='0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00'FRA_LINE3='0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00'FRA_LINE4='0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x04'FRA_LINE5='0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04'FRA_LINE6='0x00,0x04,0x00,0x04,0x00,0x04,0x02,0x00,0x06,0x04'FRA_LINE7='0x02,0x00,0x06,0x04,0x02,0x00,0x06,0x04,0x02,0x00'FRA_LINE8='0x06,0x04,0x02,0x00,0x06,0x04,0x02,0x00,0x07,0x06'FRA_LINE9='0x05,0x04,0x03,0x02,0x01,0x00,0x07,0x06,0x05,0x04'FRA_LINEa='0x03,0x02,0x01,0x00,0x07,0x06,0x05,0x04,0x03,0x02'FRA_LINEb='0x01,0x00,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00'

配置文件在

mapi_audio_customer.cppvoid mapi_audio_customer::SetAbsoluteVolume(const MAPI_U8 u8Path, MAPI_U8 uPercent, const MAPI_U8 uReserve) const MAPI_U8 TransVolum_int = 0; MAPI_U8 TransVolum_fra = 0; UNUSED(uReserve); if(uPercent = MAPI_AUDIO_VOLUME_ARRAY_NUMBER) uPercent = MAPI_AUDIO_VOLUME_ARRAY_NUMBER - 1; printf("SetAbsoluteVolume: uPercent value overflow!!! //check if system configuration provide customized volume curve. const VolumeCurve_t* const curve = mapi_syscfg_fetch::GetInstance()- GetVolumeCurve(); if ((curve != NULL) (curve- bEnabled == 1)) TransVolum_int = curve- u8Volume_Int[uPercent]; TransVolum_fra = curve- u8Volume_Fra[uPercent]; else // Use default volume table. TransVolum_int = (MAPI_U8)(u8Volume[uPercent] 8); TransVolum_fra = (MAPI_U8)(u8Volume[uPercent] 0x00FF); printf("SetAbsoluteVolume: u8Path = 0x%x",u8Path); printf("SetAbsoluteVolume: Set Volume int value = 0x%x", TransVolum_int); printf("SetAbsoluteVolume: Set Volume fra value = 0x%x", TransVolum_fra); MApi_AUDIO_SetAbsoluteVolume(u8Path, TransVolum_int, TransVolum_fra);}

通过mapi_syscfg_fetch::GetInstance()- GetVolumeCurve()即获取ini配置声音曲线表,u8Patch 对应的就是 lineout0,lineout1,lingout2,lineout3

最后通过MApi_AUDIO_SetAbsoluteVolume(u8Path, TransVolum_int, TransVolum_fra) 设置到主芯片寄存器:

/////////////////////////////////////////////////////////////////////////////////// @ingroup Audio_BASIC_SOUNDEFFECT/// @brief  Function  Name: MDrv_SOUND_AbsoluteVolume()/// @brief  Function  Description: This routine is used to set the absolute u8Volume of audio u8Path./// @param u8Path  : for audio u8Path0 ~ u8Path6/// @param u8Vol1  : MSB 7-bit register value of 10-bit u8Volume/// range from 0x00 to 0x7E , gain: +12db to -114db (-1 db per step)/// @param u8Vol2  : LSB 3-bit register value of 10-bit u8Volume/// range from 0x00 to 0x07 , gain: -0db to -0.875db (-0.125 db per step)//////////////////////////////////////////////////////////////////////////////// void MApi_AUDIO_SetAbsoluteVolume( MS_U8 u8Path, MS_U8 u8Vol1, MS_U8 u8Vol2 );

当使用外挂混音,需要固定主芯片输出时,以下通过MApi_XC_WriteByte 直接固定了lineout0(0x112D) 这一路的输出,

MAPI_U8 mapi_audio_customer::fixOutputVolumeOffset() const #define REGADDR (0x112D00) MAPI_U8 TransVolum_int = 0; MAPI_U8 TransVolum_fra = 0; MAPI_U16 u16Temp = 0x0000; const MAPI_U16 u16Vga = 0x0c00; const MAPI_U16 u16Hdmi = 0x0400; const MAPI_U16 u16tv = 0x04c0; // atv, dtv const MAPI_U16 u16Storage = 0x0b80; const MAPI_U16 u16Cvbs = 0x0a80; if(MAPI_INPUT_SOURCE_VGA == m_mainCurInputSrc) u16Temp = u16Vga; else if(MAPI_INPUT_SOURCE_ATV == m_mainCurInputSrc || MAPI_INPUT_SOURCE_DTV == m_mainCurInputSrc) u16Temp = u16tv; else if(MAPI_INPUT_SOURCE_CVBS = m_mainCurInputSrc MAPI_INPUT_SOURCE_CVBS_MAX m_mainCurInputSrc) u16Temp = u16Cvbs; else if (MAPI_INPUT_SOURCE_YPBPR = m_mainCurInputSrc MAPI_INPUT_SOURCE_YPBPR_MAX m_mainCurInputSrc) u16Temp = u16Cvbs; else if(MAPI_INPUT_SOURCE_HDMI = m_mainCurInputSrc MAPI_INPUT_SOURCE_HDMI_MAX m_mainCurInputSrc) u16Temp = u16Hdmi; else if(MAPI_INPUT_SOURCE_STORAGE == m_mainCurInputSrc) u16Temp = u16Storage; else return 0; TransVolum_int = (u16Temp 8); TransVolum_fra = (u16Temp 0x00FF); printf("[%s][%d] fix the android output to 4.6db ",__FUNCTION__,__LINE__); printf("[%s][%d] source id: %d, reg[0x112D].value = 0x%04x ",__FUNCTION__,__LINE__,m_mainCurInputSrc,u16Temp); printf("[%s][%d] int: 0x%02x, fra: 0x%02x ",__FUNCTION__,__LINE__,TransVolum_int,TransVolum_fra); MApi_XC_WriteByte(REGADDR , TransVolum_fra); MApi_XC_WriteByte(REGADDR + 1, TransVolum_int); return 1;}

其它路也可以通过这种方式固定。