DSP

audio:mt6236 录音驱动小结

2019-07-13 12:44发布

目录 一 基本框架 二 源码分析 三 FAQ   摘要 本文主要描述MT6236平台之录音流程,且着重针对驱动源代码做分析,包括时序图,源码层次,以及做了问题的总结。
一基本框架 1.1框架  













二源码分析 2.1时序图 与状态机 以36为例: 时序图:不单单以任务为节点,  















2.2主要文件,函数以及数据结构 这里只要讨论驱动相关: 相关宏:__MED_AUD_REC_MOD__       AUD_REC_ENABLE       DSP_SOLUTION       SMART_PHONE_CORE 根据audio.mak: 36的 med and audio的代码都是使用V1   文件(自上往下) 描述 UI   vapp_soundrec_util.cpp vapp_soundrec.cpp 录音应用UI相关 mdi_audio.c mdi层封装record接口函数,当然还包括其他函数 aud_api.c API包括了主要的音频模块接口函数,播放器,录音等等,到这里未知,这些文件都是为UI层服务的接口文件。 aud_ilm.c audio消息封装层,转发消息到: MED_TASK Med_Task   aud_media.c Med_task的对UI层的消息的执行函数 aud_record.c 独立的录音的功能函数--这里是med_task来调用的。 aud_recorder_media.c media层函数定义,功能:操作内存,与L1audio Task 交互。操作硬件层,调用PCM WAV等算法。       函数(自上而下) 描述 UI   vadp_soundrec_rec_start() 录音应用的UI接口 mdi_audio_start_record() mdi层封装接口 media_aud_start_record() API层音频模块接口,到这里未知,这些文件都是为UI层服务的接口函数。 aud_send_record_req() Audio ILM层负责封装消息给Med Task Med TASK   aud_media_record_req_hdlr() MedTask层对UI层的消息处理函数 aud_rec_start_record() 独立的录音的功能函数--这里是med_task来调用的。 _aud_recorder_media_record() media层函数定义,功能…..录音的硬件驱动都在这里操作。 Media_Record() 最终操作DSP HW的函数,注册回调函数给L1audio_Task   根据每一层的contex数据结构来理解: 数据结构(自上而下) 组成 描述 g_sndrec_cntx   UI层的audio record上下文 aud_context_p   Med task层的audio record 上下文 med_aud_recorder_t  kal_int32 (*open)  kal_int32 (*close)  kal_int32 (*start)  kal_int32 (*stop) …... Audio Recorder interfaces这些都是media层的接口, 直接打开底层硬件驱动,包括文件操作,设置格式,申请释放buffer, 调用wav PCM等算法         请注意关键点: 1. #defineAUD_RECORDER_MEM_MARGIN             (512)//对齐     #defineAUD_RECORDER_BUFFER_THRESHOLD       (200)  /* 200 words (400 bytes) bydefault */ 2. 刚开始录的时候要跳过2fame   Media_Record函数里面: media.recorded_time = -40; // skip two speechframes   3.开关MIC:L1SP_SetInputSource(custom_cfg_hw_aud_input_path(msg_p->input_source)); 4.文件创建:_aud_recorder_media_open() 5.Allocate buffers_aud_recorder_media_record() 5.1Buffer for amr: 5.2buffer for ring:---采用环形缓冲机制,-----详细内容请是参考环形buffer设计原理  aud_util_alloc_ring_buffer_ext(AUD_RING_BUFFER_SIZE,&self_p->ring_buffer_p);  Media_SetBuffer(self_p->ring_buffer_p,AUD_RING_BUFFER_LEN); --->size:AUD_RING_BUFFER_SIZE----是BUFFER_THRESHOLD的10倍 --->len:AUD_RING_BUFFER_LEN 和Media层的media.ctrl.rb_size ;media.ctrl.rb_base一致,   Med_v Task 读取L1audio_Buffer的新data:Media_GetReadBuffer();   6.L1audio与Med Task之间的回调函数 首先注册回电函数: _aud_recorder_media_event_callback_fct  Med Task:           Media_Record(media_format, _aud_recorder_media_event_callback_fct,param_p); ------>media.media_handler = media_handler; L1audio_Task:     mediaInit(L1Audio_GetAudioID() ); ----->L1Audio_SetEventHandler( uint16 audio_id,L1Audio_EventHandler handler ) ----->l1audio.evHandler[audio_id] = handler;//handle放到L1audio的handle里面   回调函数_aud_recorder_media_read_data_fct()---->write data to FS 更新文件大小偏移,这样文件就可以逐步加大             /* Update file offset */             self_p->file_offset += len;             *written_len = len;   Callback 门限是:AUD_RECORDER_BUFFER_THRESHOLD;   7.通过L1audio_Task来读取DSP的数据 函数:amrDediEncReadFromDSP-------AMR   pcmReadFromDSP();-------PCM  wavReadFromDSP((int16*)wav.tmp_buf[wav.tmp_w&FRAME_BUF_MASK] );----WAV …...等等 8.驱动硬件开始录音的函数: amrRecord() /*     * Stuff no-dataframe first to handle the situation when DSP issues     * interrupt toMCU for recording, but at that timethe AMR codec in DSP     * has notfinished its job.     */     三FAQ总结 1.DSP层上面时候发出中断呢? 首先:DSP的时钟与NCU同步,估计是通过系统网络同步时钟:TDMA定时器,定时地产生中断。 其次 :当buffer到达AUD_RECORDER_BUFFER_THRESHOLD时候,触发中断通知MCU。 处理流程是这样 isrC_Main---->定时地发送中断信号过来,---->激活高级中断处理例程kal_activate_hisr(l1audio.hisr);--->HISR判断是否满足AUD_RECORDER_BUFFER_THRESHOLD----->满足则通知L1audio_Task 和Med_Task--->写数据到FS.   2.文件时如何逐步加大的呢?也就是说offset写的过程。 一开始就会创建一个临时文件,每次buffer读回来写到文件之后,offset就计算一下偏移大小, /* Update file offset */ self_p->file_offset += len;  *written_len =len; 原先的文件句柄不变,根据这个offset,不停地带该文件句柄的最后一簇,查找长度为len的簇,累计到该句柄后面。 更详细请参考文件系统读写流程。   3.能否同时录音上行和下行呢? No;  函数amrRecord(){ *DP_SC_MUTE = 0x0002;  /* uplink path only */}   4.录音格式是那一种? Arm---:MEDIA_AMR_WB Wav:---: