#include "quec_audio.h" #include "quec_debug.h" #include "acm_audio_track.h" #include "acm_audio_def.h" #include "acm_audio_record.h" #include "audio_file.h" #include "mp3dec_api.h" #include "acm_audio_tone.h" #include "audio_bind.h" #include "quec_cust_feature.h" #ifdef QUECTEL_OPEN_CPU #include "ql_fs.h" #include "diag.h" #include "nvm_header.h" #include "FDI_EXT.h" #include "FDI_FILE.h" #include "quec_rtos.h" #define QUEC_OPEN 1 #define DTMF_VOLUME_MAX (16) #define DTMF_VOLUME_MIN (-36) #define ADUIO_FREE(X) do{ \ if(X) { \ free(X); \ X = NULL; \ } \ }while(0) static quec_mutex_t g_audio_mutex = NULL; #define AUDIO_CONFIG_NVM1_NAME "audio_config.nvm" #define MSA_AUDIO1_VERSION "MarvellModem_0001" #define AUDIO_CONFIG_NVM2_NAME "U:/audio_config.nvm" #define AUDIO_VE_NVM1_NAME "U:/audio_ve.nvm" #define AUDIO_GAIN_NVM1_NAME "U:/audio_gain.nvm" #define AUDIO_MEDIA_VE_NVM1_NAME "U:/audio_mediaVE.nvm" #define MSA_AUDIO_VERSION1 "MarvellModem_0001" #define SINGLE_NVM_VERSION1 "MarvellModem_Crane" extern ACM_Configuration g_AudioConfigTable; extern ACMDSP_VEParametersT *g_pVEParamsTable; extern ACMCP_MediaVEarametersT *g_pMediaVEParamsTable; extern unsigned short g_MediaVEParamsCount; extern unsigned short g_VEParamsCount; ACMCP_MediaVEarametersT *f_pMediaVEParamsTable = NULL; ACMDSP_VEParametersT *f_pVEParamsTable = NULL; ACM_Configuration f_AudioConfigTable = {0x08,1,0,{"Audio Configuration"}}; char file_version[][32]={{"3.0."},{"3.0."},{"3.0."}}; extern BOOL isIPCControlInit(void); #if !defined(CRANELR_SUPPORT) && !defined(CRANELRH_SUPPORT) extern size_t ACM_Get_AudioDefaultGainTable_size(void); extern size_t ACM_Get_AudioDefaultVETable_size(void); extern void AudioHAL_AifUseInternalCodec(void); extern int AudioHAL_sspaSetBCLKType(unsigned int type); extern void AudioHAL_AifUseSSPA_NB(void); extern void AudioHAL_AifUseSSPA(void); extern void AudioHAL_AifUseSSPA_32K(void); extern void AudioHAL_AifUseSSPA_48K(void); extern unsigned short g_GainParamsCount; extern ACMCodec_GainT *g_pGainParamsTable; extern ACMCodec_GainT *f_pGainParamsTable; extern size_t ACM_Get_AudioDefaultMediaVETable_size(void); extern size_t ACM_Get_AudioConfigure_size(void); #endif #else #define QUEC_OPEN 0 #endif #define ID_RIFF 0x46464952 #define ID_WAVE 0x45564157 #define ID_FMT 0x20746d66 #define ID_DATA 0x61746164 #define ID_IOS 0x524c4c46//wav data id by IOS #define AUDIO_PLAY 1 #define AUDIO_RECORD 2 #define NEED_USE_OWEN_FS do{if(!fops_inited){quec_register_audio_fops(&file_ops);fops_inited++;}}while(0); #define quec_audio_log(format,...) quec_log("[quau]%s:"format, __func__, ##__VA_ARGS__); static BOOL is_support_samplerate(unsigned int rate) { switch(rate) { case 8000: case 11025: case 12000: case 16000: case 22050: case 24000: case 32000: case 44100: case 48000: return true; } return false; } unsigned int quec_audio_fopen(const char *fname, const char *mode) { int i = 0; unsigned int fp = 0; if(QUEC_OPEN == 1) { fp = (unsigned int)(ql_fopen(fname, (const char * )mode)); } return fp; } int quec_audio_fclose(unsigned int fp) { if(QUEC_OPEN == 1) { return ql_fclose((QFILE *)fp); } } size_t quec_audio_fread(void * buffer, size_t size, size_t num, unsigned int fp) { if(QUEC_OPEN == 1) { return ql_fread(buffer, size, num, (QFILE *)fp); } } size_t quec_audio_fwrite(const void * buffer, size_t size, size_t num, unsigned int fp) { if(QUEC_OPEN == 1) { return ql_fwrite((void*)buffer, size, num, (QFILE *)fp); } } int quec_audio_fseek(unsigned int fp, long offset, int whence) { int ret = -1; int ret1 = -1; if(QUEC_OPEN == 1) { ret1=ql_fseek((QFILE *)fp, offset, whence); if(ret1>=0) ret=0; else ret=ret1; } return ret; } bool quec_audio_file_exist(const char *file_name) { bool ret; if(QUEC_OPEN == 1) { if(ql_access(file_name, 0)<0) ret=0; else ret=1; } return ret; } static audio_file_ops_t file_ops = { .open = quec_audio_fopen, .close = quec_audio_fclose, .seek = quec_audio_fseek, .read = quec_audio_fread, .write = quec_audio_fwrite, .access = quec_audio_file_exist, }; char fops_inited =0; void quec_register_audio_fops(audio_file_ops_t* argv) { register_audio_fops(argv); } /*pcm play start*/ audio_track_handle quec_audio_track_open(unsigned int rate, unsigned int channels, int64_t option, audio_track_callback event_cb) { return audio_track_open(rate,channels,option,event_cb); } int quec_audio_track_write(audio_track_handle handle, uint8_t* data, unsigned int size) { return audio_track_write(handle, data, size); } int quec_audio_track_close(audio_track_handle handle,int force) { return audio_track_close(handle,force); } int quec_audio_track_ctrl(audio_track_handle handle, enum audio_track_control ctrl_type, int ctrl_value) { return audio_track_ctrl(handle,ctrl_type,ctrl_value); } /*pcm play end*/ void quec_audio_pipeline_config(unsigned int rate, unsigned int channel) { acm_audio_track_pipeline_config((uint32_t)rate, (uint32_t)channel); } int quec_audio_track_pipeline_read(unsigned char * buf, unsigned int * size) { return acm_audio_track_pipeline_read((uint8_t *) buf, (uint32_t *) size); } /*pcm record start*/ #ifdef QUEC_AUDIO_DENOISE #include "ql_audio_denoise.h" #include "ql_platform.h" #define NOT_SET_DENOISE_VAD 0 //#include "timer.h" //#include //#include //#include //#include "utlTrace.h" static void *denoise_memory = NULL; static void *denoise_inst_handle = NULL; static void *pcm_data_temp = NULL; static void *pcm_data_send_denoise = NULL;//送入算法处理的数捿 bool ql_denoise_enabled = 0; int32_t denoise_count = 0; //每次要取出的长度,同时也是算法每次处理的长度 void ql_set_denoise_flag(bool onoff) { ql_denoise_enabled = onoff; } bool ql_get_denoise_flag(void) { return ql_denoise_enabled; } #endif audio_record_handle quec_audio_record_open(unsigned int rate, unsigned int channels, int64_t option, audio_record_callback event_cb) { #ifdef QUEC_AUDIO_DENOISE if (ql_denoise_enabled) { if (denoise_inst_handle == NULL) { unsigned int mem_needed = ql_denoise_dsp_get_memory_needed(); quec_debug_print_uart("mem_needed %d ...\r\n", mem_needed); if (mem_needed<=0) { quec_debug_print_uart("ql_denoise_dsp_get_memory_needed error\n"); goto exit; } denoise_memory = malloc(mem_needed); if (denoise_memory == NULL) { quec_debug_print_uart("denoise_memory malloc error\n"); goto exit; } quec_debug_print_uart("OK ql_memory 0x%x ...\r\n", denoise_memory); ql_denoise_set_memory_base(denoise_memory, mem_needed); int32_t sample_rate = rate; int32_t denoise_lvl = 1; // 0.2 - 4.0 int32_t drc_gain = 3; // drc post gain denoise_count = (sample_rate == 8000)?320:640; pcm_data_temp = malloc(denoise_count); pcm_data_send_denoise = malloc(denoise_count); if(pcm_data_send_denoise == NULL || pcm_data_temp == NULL) { quec_debug_print_uart("pcm_data_send_denoise or pcm_data_temp malloc error\n"); if (pcm_data_temp) { free(pcm_data_temp); pcm_data_temp = NULL; } if (pcm_data_send_denoise) { free(pcm_data_send_denoise); pcm_data_send_denoise = NULL; } if(denoise_memory) { free(denoise_memory); denoise_memory = NULL; } goto exit; } denoise_inst_handle = ql_denoise_init(sample_rate, denoise_lvl, drc_gain, 20); if (denoise_inst_handle == NULL) { quec_debug_print_uart("denoise_inst_handle init error\n"); if (pcm_data_temp) { free(pcm_data_temp); pcm_data_temp = NULL; } if (pcm_data_send_denoise) { free(pcm_data_send_denoise); pcm_data_send_denoise = NULL; } if(denoise_memory) { free(denoise_memory); denoise_memory = NULL; } goto exit; } ql_denoise_set_vad_lvl(denoise_inst_handle, NOT_SET_DENOISE_VAD, NOT_SET_DENOISE_VAD); } } #endif exit: return audio_record_open(rate, channels, option,event_cb); } //extern int gettimeofday(struct timeval *tv, void* dummy); int quec_audio_record_read(audio_record_handle handle, uint8_t*data, unsigned int* count) { int ret = -1; int record_ret = -1; uint32_t cur_len = 0; #ifdef QUEC_AUDIO_DENOISE //ql_cpu_fre_set(QL_PP5); if (ql_denoise_enabled) { if (denoise_inst_handle == NULL || denoise_memory == NULL || pcm_data_temp == NULL) { quec_debug_print_uart("denoise_inst_handle or denoise_memory or pcm_data_temp NULL\n"); if (denoise_inst_handle) { ql_denoise_cleanup(denoise_inst_handle); denoise_inst_handle = NULL; } if (denoise_memory) { free(denoise_memory); denoise_memory = NULL; } if (pcm_data_temp) { free(pcm_data_temp); pcm_data_temp = NULL; } if (pcm_data_send_denoise) { free(pcm_data_send_denoise); pcm_data_send_denoise = NULL; } goto exit; //一旦发生其他情况,清除资源,走源接口 } //一帧20ms if (denoise_count != *count) { quec_debug_print_uart("denoise_count %d < *count %d\n",denoise_count,*count); if (denoise_inst_handle) { ql_denoise_cleanup(denoise_inst_handle); denoise_inst_handle = NULL; } if (denoise_memory) { free(denoise_memory); denoise_memory = NULL; } if (pcm_data_temp) { free(pcm_data_temp); pcm_data_temp = NULL; } if (pcm_data_send_denoise) { free(pcm_data_send_denoise); pcm_data_send_denoise = NULL; } goto exit; } //读取数据 cur_len = denoise_count; record_ret = audio_record_read(handle,pcm_data_send_denoise,&cur_len); memcpy(pcm_data_temp,pcm_data_send_denoise,denoise_count); //struct timeval tv ; //struct timeval tv_after; //gettimeofday(&tv, NULL); //quec_debug_print_uart("cur_len %d record_ret=%d,denoise_count=%d\n",cur_len,record_ret,denoise_count); if(record_ret == 0 &&cur_len == denoise_count ) { ret = ql_denoise_process(denoise_inst_handle, pcm_data_send_denoise, (void *)data); //gettimeofday(&tv_after, NULL); //quec_debug_print_uart("process time %d \n",(tv_after.tv_sec - tv.tv_sec)*1000 + (tv_after.tv_usec - tv.tv_usec)/1000); if(ret >= 0) { //处理成功直接返回 *count = denoise_count; return record_ret; } else { //处理失败复制缓存中的数据,进行下一次读取 memcpy(data, pcm_data_temp, *count); *count = denoise_count; return record_ret; } } else { *count = 0; //quec_debug_print_uart("record_ret error or cur_len != denoise_count ,record_ret=%d,cur_len=%d,\n",record_ret,cur_len); return record_ret; } } #endif exit: record_ret = audio_record_read(handle,data,count); return record_ret; } int quec_audio_record_close(audio_record_handle handle,int force) { #ifdef QUEC_AUDIO_DENOISE if(ql_denoise_enabled) { //quec_debug_print_uart("over close \n"); if (denoise_inst_handle) { ql_denoise_cleanup(denoise_inst_handle); denoise_inst_handle = NULL; } if (denoise_memory) { free(denoise_memory); denoise_memory = NULL; } if (pcm_data_temp) { free(pcm_data_temp); pcm_data_temp = NULL; } if (pcm_data_send_denoise) { free(pcm_data_send_denoise); pcm_data_send_denoise = NULL; } } #endif return audio_record_close(handle,force); } int quec_audio_record_ctrl(audio_record_handle handle, enum audio_record_control ctrl_type, int ctrl_value) { return audio_record_ctrl(handle,ctrl_type,ctrl_value); } /*pcm record END*/ /*WAV PALY START*/ int quec_wav_play(const char* file_name, struct audio_track_config* track_config, audio_track_handle* handle) { NEED_USE_OWEN_FS; return wave_playback_start( file_name, track_config, handle); } int quec_wav_play_stop(audio_track_handle handle,char force) { return wave_playback_stop(handle, force); } /*WAV PLAY END*/ /*mp3_play start*/ #ifdef QL_MP3_FUNC int quec_mp3_play(char *file_name,Mp3PlaybackHandle* handle,Mp3PlayConfigInfo* mp3_configInfo) { NEED_USE_OWEN_FS; if(NULL==g_audio_mutex) { quec_rtos_mutex_create(&g_audio_mutex); } return mp3PlayStart(file_name,mp3_configInfo,handle); } int quec_mp3_stream_play_buffer(Mp3PlaybackHandle handle,unsigned char *mp3_buff, int mp3_size) { //加上锁,防止在执行quec_mp3_stream_play_buffer过程中,执行stop,因为异步操作,stop时清除MP3相关参数导致使用野指针 int res =0; if(g_audio_mutex) { quec_rtos_mutex_lock(g_audio_mutex, QUEC_WAIT_FOREVER); } Mp3StreamDataInfo dataInfo; dataInfo.handle = handle; dataInfo.buf = mp3_buff; dataInfo.size = mp3_size; res = mp3StreamPlayBuffer(&dataInfo); if(g_audio_mutex) { quec_rtos_mutex_unlock(g_audio_mutex); } return res; } int quec_mp3_play_stop(Mp3PlaybackHandle handle,int drain) { NEED_USE_OWEN_FS; int res =0; if(g_audio_mutex) { quec_rtos_mutex_lock(g_audio_mutex, QUEC_WAIT_FOREVER); } res =mp3PlayStop(handle,drain); if(g_audio_mutex) { quec_rtos_mutex_unlock(g_audio_mutex); } return res; } int quec_mp3_get_pcm_handle(Mp3PlaybackHandle handle, unsigned int* pcm_handle) { NEED_USE_OWEN_FS; return mp3GetPCMOutHandle(handle,pcm_handle); } #endif /*mp3_play_end*/ /*amr play start*/ #ifdef QL_AMR_FUNC int quec_amr_play(char* file_name,AmrPlaybackHandle* handle,AmrPlaybackConfigInfo* amr_config) { NEED_USE_OWEN_FS; return amrPlayStart(file_name,amr_config,handle); } int quec_amr_stream_play_buffer(AmrPlaybackHandle handle,unsigned char *amr_buff, int amr_size) { return amrPlayBuffer(handle,amr_buff,amr_size); } int quec_amr_play_stop(AmrPlaybackHandle handle,int drain) { NEED_USE_OWEN_FS; return amrPlayStop(handle, drain); } int quec_amr_get_pcm_handle(AmrPlaybackHandle handle, unsigned int* track_handle) { NEED_USE_OWEN_FS; return amrGetPCMOutHandle(handle,track_handle); } /*amr play end*/ /*amr record start*/ int quec_amr_record(char* file_name,AmrEncodeHandle* handle,AmrEncConfigInfo* config) { NEED_USE_OWEN_FS; return amrEncStart(file_name,config,handle); } int quec_amr_record_stop(AmrEncodeHandle handle) { NEED_USE_OWEN_FS; return amrEncStop(handle); } #endif /*amr record end*/ int quec_get_audio_state(void) { int ret; ret = isIPCControlInit(); //quec_debug_print_uart("audio_state, status: %d\n", status); return ret;//1-true;0-false } /*==========================================================*/ /* quec_bind_speakerpa_cb */ /*==========================================================*/ void quec_bind_speakerpa_cb(cb_on_speakerpa cb) { AudioHAL_AifBindSpeakerPA_CB((AUDIOHAL_SpeakerPA_T)cb); } static int g_audio_volume = 5; void quec_set_volume(char vol) { quec_audio_log("quec_set_volume vol:%d\n", vol); if(vol >= 12) { vol = 11; } g_audio_volume = vol; #if defined(CRANELR_SUPPORT) || defined(CRANELRH_SUPPORT) acm_audio_track_load_gain((g_audio_volume==0)? (-36*256):(g_audio_volume*3-21)*256); #else AudioHAL_AifSetVolume(vol); #endif } static char quec_audio_output_type = 0; void quec_set_audio_ouput_type(char mode) { quec_audio_output_type = mode; } char quec_get_audio_ouput_type(void) { return quec_audio_output_type; } #if !defined(CRANELR_SUPPORT) && !defined(CRANELRH_SUPPORT) void quec_set_audio_path_to_handset(void) { AUDIOHAL_AIF_DEVICE_CFG_T config; AUDIOHAL_AIF_LEVEL_T level; level.micLevel = AUDIOHAL_MIC_ENABLE; level.spkLevel = AUDIOHAL_SPK_VOL_7; level.toneLevel = AUDIOHAL_TONE_M3DB; level.sideLevel = AUDIOHAL_SIDE_VOL_7; config.spkSel = AUDIOHAL_SPK_RECEIVER; config.micSel = AUDIOHAL_MIC_LOUDSPEAKER; config.spkType = AUDIOHAL_SPEAKER_STEREO; config.level = &level; AudioHAL_AifOpen(AUDIOHAL_ITF_RECEIVER, &config); //AudioHAL_AifSwitch(AUDIOHAL_ITF_RECEIVER); } void quec_set_audio_path_to_headset(void) { AUDIOHAL_AIF_DEVICE_CFG_T config; AUDIOHAL_AIF_LEVEL_T level; level.micLevel = AUDIOHAL_MIC_ENABLE; level.spkLevel = AUDIOHAL_SPK_VOL_7; level.toneLevel = AUDIOHAL_TONE_M3DB; level.sideLevel = AUDIOHAL_SIDE_VOL_7; config.spkSel = AUDIOHAL_SPK_EARPIECE; config.micSel = AUDIOHAL_MIC_EARPIECE; config.spkType = AUDIOHAL_SPEAKER_STEREO; config.level = &level; AudioHAL_AifOpen(AUDIOHAL_ITF_EARPIECE, &config); } void quec_set_audio_path_to_speaker(void) { AUDIOHAL_AIF_DEVICE_CFG_T config; AUDIOHAL_AIF_LEVEL_T level; level.micLevel = AUDIOHAL_MIC_ENABLE; level.spkLevel = AUDIOHAL_SPK_VOL_7; level.toneLevel = AUDIOHAL_TONE_M3DB; level.sideLevel = AUDIOHAL_SIDE_VOL_7; config.spkSel = AUDIOHAL_SPK_LOUDSPEAKER; config.micSel = AUDIOHAL_MIC_LOUDSPEAKER; config.spkType = AUDIOHAL_SPEAKER_STEREO; config.level = &level; AudioHAL_AifOpen(AUDIOHAL_ITF_LOUDSPEAKER, &config); //AudioHAL_AifSwitch(AUDIOHAL_ITF_LOUDSPEAKER); } void quec_codec_choose(codec_choose_state codec_choose, quec_codecpcm_config* pcm_config) { if(codec_choose == QUEC_AUD_INTERNAL_CODEC) { AudioHAL_AifUseInternalCodec(); }else if(codec_choose == QUEC_AUD_EXTERNAL_CODEC){ if(pcm_config != NULL){ AudioHAL_sspaSetBCLKType(pcm_config->pcmbclk); switch(pcm_config->sample) { case QUEC_PCM_CODEC_SAMPLE_8000: AudioHAL_AifUseSSPA_NB(); break; case QUEC_PCM_CODEC_SAMPLE_16000: AudioHAL_AifUseSSPA(); break; case QUEC_PCM_CODEC_SAMPLE_32000: AudioHAL_AifUseSSPA_32K(); break; case QUEC_PCM_CODEC_SAMPLE_48000: AudioHAL_AifUseSSPA_48K(); break; default : AudioHAL_AifUseSSPA_NB(); break; } } } } int quec_get_volume(void) { return g_audio_volume; } int quec_aud_dtmf_play(QUEC_AUDIOHAL_TONE_TYPE tone, int onoff) { int ret = -1; unsigned int asiic_tone = 0; if(tone > 15) { quec_debug_print_uart("param error\n"); return -1; } if(tone<=QUEC_AUDIOHAL_DTMF_9) { asiic_tone =tone+48; } if(tone>=QUEC_AUDIOHAL_DTMF_A && tone<=QUEC_AUDIOHAL_DTMF_D) { asiic_tone =tone+55; } if(tone==QUEC_AUDIOHAL_DTMF_S) { asiic_tone ='*'; } if(tone==QUEC_AUDIOHAL_DTMF_P) { asiic_tone ='#'; } if( onoff){ return audio_tone_start_ascii(asiic_tone); } else { return audio_tone_stop(); } } int quec_aud_tone_play(int f1, int f2, int onoff) { int ret = -1; if( onoff){ return audio_tone_start_frequency(f1, f2); } else { return audio_tone_stop(); } } int quec_set_dtmf_detect(DTMFDetectionHandler_t cb, int onoff) { DTMFDetectionControl_t DTMFDetectionControl; memset(&DTMFDetectionControl, 0x00, sizeof(DTMFDetectionControl)); if(onoff == 0){ DTMFDetectionControl.dtmfType = AUDIO_DTMF_RX; DTMFDetectionControl.onoff = AUDIO_DTMF_OFF; OEMAudio_UnBindDTMFDetectionHandler(cb, &DTMFDetectionControl); } else { DTMFDetectionControl.dtmfType = AUDIO_DTMF_RX; DTMFDetectionControl.onoff = AUDIO_DTMF_ON; DTMFDetectionControl.dialToneToOthersTones = 25; DTMFDetectionControl.dialTonesToOthersDialTones = dialTonesToOthersDialTones_DEFAULT; DTMFDetectionControl.dialVadDuration = dialVadDuration_DEFAULT; OEMAudio_BindDTMFDetectionHandler(cb, &DTMFDetectionControl); } return 0; } void quec_set_dtmf_volume(int vo) { int dtmf_vol=0; if(vo < 0 || vo >10){ quec_debug_print_uart("volume level error \n"); return; } if(vo==0) { dtmf_vol = DTMF_VOLUME_MIN; } else if(vo==10) { dtmf_vol = DTMF_VOLUME_MAX; } else { dtmf_vol = DTMF_VOLUME_MIN + ((DTMF_VOLUME_MAX-DTMF_VOLUME_MIN)/10)*vo; } //quec_debug_print_uart("dtmf_vol %d \n",dtmf_vol); ACMAudioSetDTMFVolume(dtmf_vol); } // tx dsp gain: -36~12 void quec_set_txdspgain(signed char gain) { if(gain < -36) gain = -36; if(gain > 12) gain = 12; AudioHAL_AifSetTxDSPGain(gain); } signed char quec_get_txdspgain(void) { return AudioHAL_AifGetTxDSPGain(); } // tx codec gain: 0~4 static short txcodecgain = 0; void quec_set_txcodecgain(short gain) { if(gain < 0) gain = 0; if(gain >= 4) gain = 4; txcodecgain = gain; AudioHAL_AifSetTxCodecGain(gain, gain); } short quec_get_txcodecgain(void) { return txcodecgain; } int quec_set_txcodec_gain_table(unsigned int profile_id, unsigned int PGA_Stage1, unsigned int PGA_Stage2, unsigned int diggain) { int i = 0,j = 0; for(j = 0; j < g_GainParamsCount; j++) { if (profile_id == g_pGainParamsTable[j].Profile) { break; } } if((int)PGA_Stage1 < 0 || PGA_Stage1 > 3) return -1; if((int)PGA_Stage2 < 0 || PGA_Stage2 > 4) return -1; if(((int)diggain < 0 || diggain > 12) && diggain != 14 && diggain != 16 && diggain != 18 && diggain != 20 && diggain != 23 && diggain != 25 && diggain != 28 && diggain != 31) return -1; if (j < g_GainParamsCount) { g_pGainParamsTable[j].Tx_CodecGain.PGA_Stage1 = (ACMCODEC_PGA_STAGE1)PGA_Stage1; g_pGainParamsTable[j].Tx_CodecGain.PGA_Stage2 = (ACMCODEC_PGA_STAGE2)PGA_Stage2; g_pGainParamsTable[j].Tx_CodecGain.ADC_DigGain = (ACMCODEC_ADC_DIGGAIN)diggain; }else { quec_audio_log("ql_set_txcodec_gain error, profile_id is not right\n"); return -1; } return 0; } //add 20200702 august add to codec table int codec_gain_num(unsigned int profile_id, signed int level, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4, unsigned int data5) { if((profile_id == 0) || (profile_id == 1) || (profile_id == 2) || (profile_id == 3) || (profile_id == 4) || (profile_id == 5) || (profile_id == 64) || (profile_id == 65) || (profile_id == 66) || (profile_id == 67) || (profile_id == 68) || (profile_id == 69) || (profile_id == 70)); else{ return -1; } if((signed int)level < 0 || level > 11){ return -1; } if((signed int)data1 < 0 || data1 > 38){ return -1; } if((signed int)data2 < 0 || data2 > 4){ return -1; } if((signed int)data3 < 0 || data3 > 4){ return -1; } if((signed int)data4 < 0 || data4 > 1){ return -1; } if((signed int)data5 < 0 || data5 > 2){ return -1; } return 0; } int quec_set_codec_gain_table(unsigned int profile_id, signed int level, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4, unsigned int data5) { int i = 0, j = 0; ACMCodec_GainOutT codec_gain; unsigned int c_level[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,14,16,18,20,23,25,28,32,36,40,45,51,57,64,71,80,90,101,113,127,143,160,180,201,226,254}; memset(&codec_gain, 0, sizeof(ACMCodec_GainOutT)); if(codec_gain_num(profile_id,level,data1,data2,data3,data4,data5) == -1) { quec_audio_log("ql_set_codec_gain error, input is not ok\n"); return -1; } if (!isIPCControlInit()) { quec_audio_log("ql_set_codec_gain error, audio init is not ok\n"); return -1; } data1 = c_level[data1]; for(j = 0; j < g_GainParamsCount; j++) { if (profile_id == g_pGainParamsTable[j].Profile) { break; } } codec_gain.DAC_DigGain = (ACMCODEC_DAC_DIGGAIN)data1; //in-codec 内置codec的数字增?? codec_gain.DAC_Gain = (ACMCODEC_DAC_GAIN)data2; //in-codec 内置codec的模拟增?? codec_gain.RCV_Gain = (ACMCODEC_RCV_GAIN)data3; //in-codec 内置codec的坬筒增?? codec_gain.ClassG_Mode = (ACMCODEC_CLASSG_MODE)data4; //in-codec 内置codec的耳机增益 codec_gain.ClassD_Gain = (ACMCODEC_CLASSD_GAIN)data5; //in-codec 内置codec的喇坭增?? codec_gain.Reserved1 = 0; if(NULL==f_pGainParamsTable) { f_pGainParamsTable = (ACMCodec_GainT *)malloc(sizeof(ACMCodec_GainT)*10); memcpy(f_pGainParamsTable,(void *)g_pGainParamsTable,sizeof(ACMCodec_GainT)*10); } if (j < g_GainParamsCount) { memcpy(&f_pGainParamsTable[j].Rx_CodecGain[level], &codec_gain, sizeof(codec_gain)); memcpy(&g_pGainParamsTable[j].Rx_CodecGain[level], &codec_gain, sizeof(codec_gain)); // quec_update_audio_parameters(QUEC_ADUIO_GAIN_NVM,f_pGainParamsTable); //save in nvm } else { if(f_pGainParamsTable) { free(f_pGainParamsTable); f_pGainParamsTable=NULL; } quec_audio_log("ql_set_codec_gain error, profile_id is not right\n"); return -1; } if(f_pGainParamsTable) { free(f_pGainParamsTable); f_pGainParamsTable=NULL; } return 0; } extern ACMDSP_VEParametersT *g_pVEParamsTable ; int quec_set_eqcoeff_table(unsigned int profile_id, signed int tx_rx, unsigned int rate, signed short * data)//rx:1,tx:0;8K:1,16k:0; { int i = 0,j = 0; for(j = 0; j < g_GainParamsCount; j++) { if (profile_id == g_pGainParamsTable[j].Profile) { break; } } if (j < g_GainParamsCount) { if(tx_rx == 1){ //rx if(rate == 0){ for(i = 0;i < 24;i++) g_pVEParamsTable[j].RxFreq_eqCoeffArray[0][i] = data[i]; //8k } else if(rate == 1){ for(i = 0;i < 24;i++) g_pVEParamsTable[j].RxFreq_eqCoeffArray[1][i] = data[i]; //16k } else return -1; } else if(tx_rx == 0){ //tx if(rate == 0){ for(i = 0;i < 24;i++) g_pVEParamsTable[j].TxFreq_eqCoeffArray[0][i] = data[i]; //8k } else if(rate == 1){ for(i = 0;i < 24;i++) g_pVEParamsTable[j].TxFreq_eqCoeffArray[1][i] = data[i]; //16k } else return -1; } else return -1; }else { quec_audio_log("ql_set_eqtable error, profile_id is not right\n"); return -1; } return 0; } extern unsigned short g_MediaVEParamsCount; extern ACMCP_MediaVEarametersT *g_pMediaVEParamsTable; int quec_set_mediave_coeff_table(ACMCP_MediaVEarametersT *AudioMediaVETable) { unsigned short i = 0; for (i = 0; i < g_MediaVEParamsCount; i++) { memcpy(&g_pMediaVEParamsTable[i], AudioMediaVETable,sizeof(ACMCP_MediaVEarametersT)); } return 0; } int quec_value_check(int data, int min, int max) { if((data>=min)&&(data<=max)) return 1; return 0; } extern unsigned short g_GainParamsCount; extern ACMCodec_GainT *g_pGainParamsTable; ACMCodec_GainT *f_pGainParamsTable = NULL; int quec_set_dsp_gain_out(unsigned int profile_id, signed short *data) { int i = 0; for(i = 0;i < ACM_VOLUME_CNT;i++) { if(!quec_value_check(data[i],-36,12)) { quec_audio_log("vlaue error"); return -1; } } quec_audio_log("Egan_g_ParamsCount=%d",g_GainParamsCount); for(i = 0; i< g_GainParamsCount; i++) { if (profile_id == g_pGainParamsTable[i].Profile) { break; } } if(NULL==f_pGainParamsTable) { f_pGainParamsTable = (ACMCodec_GainT *)malloc(sizeof(ACMCodec_GainT)*10); memcpy(f_pGainParamsTable,(void *)g_pGainParamsTable,sizeof(ACMCodec_GainT)*10); } if (i < g_GainParamsCount) { quec_audio_log("update value"); memcpy(&f_pGainParamsTable[i].Rx_DSPGain[0], data, ACM_VOLUME_CNT*sizeof(signed short)); memcpy(&g_pGainParamsTable[i].Rx_DSPGain[0], data, ACM_VOLUME_CNT*sizeof(signed short)); // quec_update_audio_parameters(QUEC_ADUIO_GAIN_NVM,f_pGainParamsTable); //save in nvm // ACMSingleNvmUpdateParam(); } else { if(f_pGainParamsTable) { free(f_pGainParamsTable); f_pGainParamsTable=NULL; } quec_audio_log("ql_set_codec_gain error, profile_id is not right\n"); return -1; } memcpy(&g_pGainParamsTable[i].Rx_DSPGain[0], &f_pGainParamsTable[i].Rx_DSPGain[0], ACM_VOLUME_CNT*sizeof(signed short)); if(f_pGainParamsTable) { free(f_pGainParamsTable); f_pGainParamsTable=NULL; } return 0; } /*****************************************************************/ //add by 2020/07/08 august add update_audio_parameters /*****************************************************************/ #define SET_STRING(buf, str) strcpy((buf), (str)) extern char *GetSystemReleaseName(void); static int ACMCheckHead(QFILE *fname, char *p) { NVM_Header_ts header; int bytesRead = 0; bytesRead = ql_fread(&header, sizeof(NVM_Header_ts),1, fname); if(bytesRead != sizeof(NVM_Header_ts)){ quec_debug_print_uart(" read NVM head error!!\n"); return -1; } if (strcmp(header.Version, p) != 0){ ql_fclose(fname); quec_debug_print_uart(" NVM file error!!\n"); return -1; } return 0; } static int ACMReadFSTable(char *name, char *buff) { QFILE *ACMTableFileID; int bytesRead = 0; int i = 0,retval = 0; int file_size = 0; size_t g_AudioDefaultGainTable_size = ACM_Get_AudioDefaultGainTable_size(); size_t g_AudioDefaultVETable_size = ACM_Get_AudioDefaultVETable_size(); size_t g_AudioDefaultMediaVETable_size = ACM_Get_AudioDefaultMediaVETable_size(); ACMTableFileID = ql_fopen(name,"r"); file_size = ql_fsize(ACMTableFileID); if(file_size <= sizeof(NVM_Header_ts)){ ql_fclose(ACMTableFileID); quec_debug_print_uart(" NVM file head error, head size: %d!!\n", file_size); return -1; } if(!strcmp(AUDIO_GAIN_NVM1_NAME,name)){ if(ACMCheckHead(ACMTableFileID, SINGLE_NVM_VERSION1) == -1){ return -1; } bytesRead = ql_fread(buff, g_AudioDefaultGainTable_size ,1, ACMTableFileID); // if(bytesRead != sizeof(ACMCodec_GainT)*10) if(bytesRead != g_AudioDefaultGainTable_size) { ql_fclose(ACMTableFileID); return -1; } } if(!strcmp(AUDIO_VE_NVM1_NAME,name)){ if(ACMCheckHead(ACMTableFileID, SINGLE_NVM_VERSION1) == -1){ return -1; } bytesRead = ql_fread(buff,g_AudioDefaultVETable_size, 1, ACMTableFileID); // if(bytesRead != sizeof(ACMDSP_VEParametersT)*10) if(bytesRead != g_AudioDefaultVETable_size) { ql_fclose(ACMTableFileID); return -1; } } if(!strcmp(AUDIO_CONFIG_NVM2_NAME,name)){ if(ACMCheckHead(ACMTableFileID, MSA_AUDIO_VERSION1) == -1){ return -1; } bytesRead = ql_fread(buff,sizeof(g_AudioConfigTable), 1, ACMTableFileID); if(bytesRead != sizeof(g_AudioConfigTable)) { ql_fclose(ACMTableFileID); return -1; } } if(!strcmp(AUDIO_MEDIA_VE_NVM1_NAME,name)){ if(ACMCheckHead(ACMTableFileID, SINGLE_NVM_VERSION1) == -1){ return -1; } bytesRead = ql_fread(buff,g_AudioDefaultMediaVETable_size, 1, ACMTableFileID); // if(bytesRead != sizeof(ACMCP_MediaVEarametersT)*11) if(bytesRead != g_AudioDefaultMediaVETable_size) { ql_fclose(ACMTableFileID); return -1; } } ql_fclose(ACMTableFileID); return 0; } void ql_update_audio_parameters(void) { int ret = 0; NVM_Header_ts header; char sVersion[32] = ""; short a = 3,b = 0 ; FILE_ID ACMTableFileID; size_t g_AudioDefaultGainTable_size = ACM_Get_AudioDefaultGainTable_size(); size_t g_AudioDefaultVETable_size = ACM_Get_AudioDefaultVETable_size(); size_t g_AudioDefaultMediaVETable_size = ACM_Get_AudioDefaultMediaVETable_size(); if(quec_audio_file_exist(AUDIO_GAIN_NVM1_NAME) && (g_pGainParamsTable != NULL)){ f_pGainParamsTable = (ACMCodec_GainT *)malloc(g_AudioDefaultGainTable_size); if(ACMReadFSTable(AUDIO_GAIN_NVM1_NAME, (char *)f_pGainParamsTable) == -1){ quec_debug_print_uart("fs: audio gain read error\n"); free(f_pGainParamsTable); f_pGainParamsTable = NULL; return; } ret = memcmp(g_pGainParamsTable,f_pGainParamsTable,g_AudioDefaultGainTable_size); if(ret){ memcpy(g_pGainParamsTable,f_pGainParamsTable,g_AudioDefaultGainTable_size); ACMTableFileID = FDI_fopen("audio_gain.nvm","wb"); memset((unsigned char *)&header, 0, sizeof(NVM_Header_ts)); sprintf(sVersion, "%d.%d", a, b); SET_STRING(header.Date, ""); SET_STRING(header.time, ""); SET_STRING(header.Version, ""); //SET_STRING(header.HW_ID, GetSystemReleaseName()); strncpy(header.HW_ID,GetSystemReleaseName(), 31); SET_STRING(header.CalibVersion, sVersion); SET_STRING(header.Version, "MarvellModem_Crane"); SET_STRING(header.StructName, "ACMCodec_GainT"); header.StructSize = sizeof(ACMCodec_GainT); header.NumofStructs = (unsigned long)( g_AudioDefaultGainTable_size / sizeof(ACMCodec_GainT)); g_GainParamsCount = header.NumofStructs; if (!FDI_fwrite(&header,sizeof(NVM_Header_ts),1, ACMTableFileID)) ACM_ASSERT(0); if (!FDI_fwrite(g_pGainParamsTable, sizeof(ACMCodec_GainT)*header.NumofStructs, 1, ACMTableFileID)) ACM_ASSERT(0); if (FDI_fclose(ACMTableFileID)) ACM_ASSERT(0); DIAG_FILTER(AUDIO, ACM, ACMCreateGainNvm, DIAG_INFORMATION) diagPrintf("ql ACMCreateGainNvm API called: create or override existing files "); free(f_pGainParamsTable); f_pGainParamsTable = NULL; } else { free(f_pGainParamsTable); f_pGainParamsTable = NULL; } } if(quec_audio_file_exist(AUDIO_VE_NVM1_NAME) && (g_pVEParamsTable != NULL)){ f_pVEParamsTable = (ACMDSP_VEParametersT *)malloc(g_AudioDefaultVETable_size); if(ACMReadFSTable(AUDIO_VE_NVM1_NAME, (char *)f_pVEParamsTable) == -1){ quec_debug_print_uart("fs: audio ve read error\n"); free(f_pVEParamsTable); f_pVEParamsTable = NULL; return; } ret = memcmp(g_pVEParamsTable,f_pVEParamsTable,g_AudioDefaultVETable_size); if(ret){ memcpy(g_pVEParamsTable,f_pVEParamsTable,g_AudioDefaultVETable_size); ACMTableFileID = FDI_fopen("audio_ve.nvm","wb"); memset((unsigned char *)&header, 0, sizeof(NVM_Header_ts)); sprintf(sVersion, "%d.%d", a, b); SET_STRING(header.Date, ""); SET_STRING(header.time, ""); SET_STRING(header.Version, ""); //SET_STRING(header.HW_ID, GetSystemReleaseName()); strncpy(header.HW_ID,GetSystemReleaseName(), 31); SET_STRING(header.CalibVersion, sVersion); SET_STRING(header.Version, "MarvellModem_Crane"); SET_STRING(header.StructName, "ACMDSP_VEParametersT"); header.StructSize = sizeof(ACMDSP_VEParametersT); header.NumofStructs = (unsigned long)( g_AudioDefaultVETable_size / sizeof(ACMDSP_VEParametersT)); g_VEParamsCount = header.NumofStructs; if (!FDI_fwrite(&header,sizeof(NVM_Header_ts),1, ACMTableFileID)) ACM_ASSERT(0); if (!FDI_fwrite(g_pVEParamsTable, sizeof(ACMDSP_VEParametersT)*header.NumofStructs, 1, ACMTableFileID)) ACM_ASSERT(0); if (FDI_fclose(ACMTableFileID)) ACM_ASSERT(0); DIAG_FILTER(AUDIO, ACM, ACMCreateVENvm, DIAG_INFORMATION) diagPrintf("ql ACMCreateVENvm API called: create or override existing files "); free(f_pVEParamsTable); f_pVEParamsTable = NULL; } else { free(f_pVEParamsTable); f_pVEParamsTable = NULL; } } if(quec_audio_file_exist(AUDIO_CONFIG_NVM2_NAME)){ if(ACMReadFSTable(AUDIO_CONFIG_NVM2_NAME, (char*)&f_AudioConfigTable) == -1){ quec_debug_print_uart("fs: audio config read error\n"); return; } ret = memcmp(&g_AudioConfigTable,&f_AudioConfigTable,sizeof(g_AudioConfigTable)); if(ret){ memcpy(&g_AudioConfigTable,&f_AudioConfigTable,sizeof(g_AudioConfigTable)); ACMTableFileID = FDI_fopen("audio_config.nvm","wb"); memset((unsigned char *)&header, 0, sizeof(NVM_Header_ts)); sprintf(sVersion, "%d.%d", a, b); SET_STRING(header.Date, ""); SET_STRING(header.time, ""); SET_STRING(header.Version, ""); //SET_STRING(header.HW_ID, GetSystemReleaseName()); strncpy(header.HW_ID,(const char*)GetSystemReleaseName(), 31); SET_STRING(header.CalibVersion, sVersion); SET_STRING(header.Version, "MarvellModem_0001"); SET_STRING(header.StructName, "ACM_Configuration"); header.StructSize = sizeof(ACM_Configuration); header.NumofStructs = 1; if (!FDI_fwrite(&header,sizeof(NVM_Header_ts),1, ACMTableFileID) || !FDI_fwrite((void*)&g_AudioConfigTable, sizeof(g_AudioConfigTable), 1, ACMTableFileID)) ACM_ASSERT(0); if (FDI_fclose(ACMTableFileID)) ACM_ASSERT(0); DIAG_FILTER(AUDIO, ACM, ACMCreateAudioConfigNvm, DIAG_INFORMATION) diagPrintf("ql ACMCreateAudioConfigNvm API called: create or override existing files "); } } if(quec_audio_file_exist(AUDIO_MEDIA_VE_NVM1_NAME)){ f_pMediaVEParamsTable = (ACMCP_MediaVEarametersT *)malloc(g_AudioDefaultMediaVETable_size); if(ACMReadFSTable(AUDIO_MEDIA_VE_NVM1_NAME, (char *)f_pMediaVEParamsTable) == -1){ quec_debug_print_uart("fs: audio config read error\n"); free(f_pMediaVEParamsTable); f_pMediaVEParamsTable = NULL; return; } ret = memcmp(g_pMediaVEParamsTable,f_pMediaVEParamsTable,g_AudioDefaultMediaVETable_size); if(ret){ memcpy(g_pMediaVEParamsTable,f_pMediaVEParamsTable,g_AudioDefaultMediaVETable_size); ACMTableFileID = FDI_fopen("audio_mediaVE.nvm","wb"); memset((unsigned char *)&header, 0, sizeof(NVM_Header_ts)); sprintf(sVersion, "%d.%d", a, b); SET_STRING(header.Date, ""); SET_STRING(header.time, ""); SET_STRING(header.Version, ""); //SET_STRING(header.HW_ID, GetSystemReleaseName()); strncpy(header.HW_ID,GetSystemReleaseName(), 31); SET_STRING(header.CalibVersion, sVersion); SET_STRING(header.Version, "MarvellModem_Crane"); SET_STRING(header.StructName, "ACMCP_MediaVEarametersT"); header.StructSize = sizeof(ACMCP_MediaVEarametersT); header.NumofStructs = (unsigned long)( g_AudioDefaultMediaVETable_size / sizeof(ACMCP_MediaVEarametersT)); g_MediaVEParamsCount = header.NumofStructs; if (!FDI_fwrite(&header,sizeof(NVM_Header_ts),1, ACMTableFileID)) ACM_ASSERT(0); if (!FDI_fwrite(g_pMediaVEParamsTable, sizeof(ACMCP_MediaVEarametersT)*header.NumofStructs, 1, ACMTableFileID)) ACM_ASSERT(0); if (FDI_fclose(ACMTableFileID)) ACM_ASSERT(0); DIAG_FILTER(AUDIO, ACM, ACMCreateMediaVENvm, DIAG_INFORMATION) diagPrintf("ACMCreateMediaEQNvm API called: create or override existing files "); free(f_pMediaVEParamsTable); f_pMediaVEParamsTable = NULL; } else { free(f_pMediaVEParamsTable); f_pMediaVEParamsTable = NULL; } } } #else #include "audio_port_api.h" extern int vpathSetMode(UINT32 mode); void quec_codec_choose(codec_choose_state codec_choose, quec_codecpcm_config* pcm_config) { if(codec_choose == QUEC_AUD_INTERNAL_CODEC) { vpathSetMode(0); }else if(codec_choose == QUEC_AUD_EXTERNAL_CODEC){ if(pcm_config != NULL){ vpathSetMode(1); AudioPort_SetDelay(0); AudioPort_SetI2S(pcm_config->is_i2s); AudioPort_SetBCLKType((unsigned int)pcm_config->pcmbclk); } } } void quec_set_audio_path_to_handset(void){return;} int quec_get_volume(void){return 0;} int quec_set_dtmf_detect(DTMFDetectionHandler_t cb, int onoff){return 0;} int quec_set_far_mode(int farend){return 0;} int quec_aud_tone_play(int f1, int f2, int onoff){return 0;} int quec_aud_dtmf_play(QUEC_AUDIOHAL_TONE_TYPE tone, int onoff){return 0;} void quec_set_audio_path_to_headset(void){return;} void quec_set_audio_path_to_speaker(void){return;} void quec_set_dtmf_volume(int vo){return;} void quec_set_txdspgain(signed char gain){return;} signed char quec_get_txdspgain(void){return 0;} void quec_set_txcodecgain(short gain){return;} short quec_get_txcodecgain(void){return 0;} int quec_set_codec_gain_table(unsigned int profile_id, signed int level, unsigned int data1, unsigned int data2, unsigned int data3, unsigned int data4, unsigned int data5){return 0;} int quec_set_eqcoeff_table(unsigned int profile_id, signed int tx_rx, unsigned int rate, signed short * data){return 0;} int quec_set_mediave_coeff_table(ACMCP_MediaVEarametersT *AudioMediaVETable){return 0;} int quec_set_dsp_gain_out(unsigned int profile_id, signed short *data){return 0;} int quec_set_txcodec_gain_table(unsigned int profile_id, unsigned int PGA_Stage1, unsigned int PGA_Stage2, unsigned int diggain){return 0;} void ql_update_audio_parameters(void){return;} #endif