.. _音频传输管理模块: 音频传输管理模块说明 ======================================= 简介 ######################## 本章主要介绍audio_rf音频传输模块,用户可以基于该模块实现: * 实现ADC采集数据并启动编码输出; * 实现接收数据进行解码并输出到DAC; * 实现数据流简易管理; 模块层次划分: .. image:: audio_rf_Hierarphy.png :alt: "图1.1 模块层次划分" :align: center .. centered:: 图1.1 模块层次划分 相关文件: * apps/app/bsp/common/audio_rf_trans/audio_rf_mge.c * apps/app/bsp/common/audio_rf_trans/audio2rf_send.c * apps/app/bsp/common/audio_rf_trans/rf2audio_recv.c * apps/app/bsp/common/audio_rf_trans/trans_packet.c * apps/app/bsp/common/audio_rf_trans/trans_unpacket.c * apps/app/bsp/common/audio_rf_trans/rf_send_queue.c * apps/app/bsp/common/encoder/encoder_stream.c ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 音频发送相关接口 ####################### 函数enc_obj \*audio2rf_encoder_io(u32(\*enc_fun)(void \*, void \*, void \*), void \*p_queue_ops, bool need_isr) ****************************************************************************************************************************** .. note:: 该函数实现初始化编码器,用于音频传输应用; - 初始化编码器后,再将编码链路挂载到AUDIO_ADC中断; - 调用该函数前需确保AUDIO_ADC已工作 1. enc_fun:编码器选择,可传入ump2或者opus等编码器初始化接口; * ump3_encode_api:ump2编码器初始化api; * opus_encode_api:opus编码器初始化api; * sbc_encode_api:sbc/msbc/usbc编码器初始化api; * speex_encode_api:speex编码器初始化api; * ima_encode_api:ima编码器初始化api; * jla_lw_encode_api:jla_lw编码器初始化api; 2. p_queue_ops:编码输出使用的队列对应句柄指针; 3. need_isr:标志位,是否使用队列中断主动给蓝牙发数,目前队列中断仅用于带连接的BLE方案,周期广播不使用队列中断; 4. 返回值:编码句柄 函数u32 audio2rf_encoder_start(enc_obj \*obj) **************************************************************** .. note:: 该函数实现启动音频编码发送; 1. 返回值:启动成功 0; 函数u32 audio2rf_start_cmd(queue_obj \*p_queue, u32 sr, u32 br, AUDIO_FORMAT enc_type) ************************************************************************************************************ .. note:: 该函数实现发送编码头信息包给远端;远端接收编码信息包后启动解码; 1. p_queue:队列句柄指针,传音频时一般为编码输出使用的队列句柄指针; 2. sr:编码采样率; 3. br:编码码率; 4. enc_type:编码对应的解码类型; 5. 返回值:0:成功 非0:失败; 函数u32 audio2rf_stop_cmd(queue_obj \*p_queue) ******************************************************** .. note:: 该函数实现发送停止包给远端;远端接收停止包后停止解码; 1. p_queue:队列句柄指针,传音频时一般为编码输出使用的队列句柄指针; 2. 返回值:0:成功 非0:失败; 函数u32 audio2rf_ack_cmd(queue_obj \*p_queue, u8 ack_cmd, u8 \*data, u16 len) ******************************************************************************************************* .. note:: 该函数实现发送停止包给远端;远端接收停止包后停止解码; 1. p_queue:队列句柄指针,一般为接收端解码成功回复发送端使用的队列句柄指针; 2. ack_cmd:需要回复ack的命令包; 3. data:ack参数buff; 4. len:ack参数长度; 5. 返回值:0:成功 非0:失败; 函数u32 audio2rf_send_packet(void \*p_queue, RADIO_PACKET_TYPE type, u8 \*data, u16 data_len) ************************************************************************************************************************* .. note:: 该函数实现发送cmd或者数据包; 1. p_queue:发送数据所需的队列指针 2. type:包类型; 3. data:发送数据buff; 4. data_len:发送数据长度; 5. 返回值:成功:0 失败:请查看errno-base.h 函数u32 rf_enc_output(void \*priv, u8 \*data, u16 len) ***************************************************************************** .. note:: 该函数实现编码器输出数据并进行无线传输,由编码器回调; - 无线传输模块出错导致无法正常发送时停止编码,发送繁忙时等待下次编码输出 - 该函数在启动编码器时传入编码器output参数; 1. priv:私有结构体,此处为编码句柄; 2. data:输出数据buff; 3. len:输出数据长度; 4. 返回值:本次消耗的编码数据字节长度; 函数void audio2rf_encoder_stop(queue_obj \*p_queue, ENC_STOP_WAIT wait) ********************************************************************************************** .. note:: 该函数实现停止编码和数据发送,并发送停止包给远端; 1. p_queue:编码输出使用的发送队列指针; 2. wait:是否等待编码数据消耗完成; 3. 返回值:无 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 音频接收相关接口 ####################### 结构体变量struct if_decoder_io dec_io_for_rf **************************************************** .. note:: 该结构体变量为解码输入输出管理句柄,解码器通过input接口获取数据,解码完成后通过output接口输出数据; 函数dec_obj \*rf2audio_decoder_start(RF_RADIO_ENC_HEAD \*p_enc_head, sound_stream_obj \*p_rf_stream, u32 output_sr) ***************************************************************************************************************************************** .. note:: 该函数实现音频传输接收开始,启动解码器; - 音频传输接收到编码头信息后,启动相应解码器开始解码; 1. p_enc_head:编码头信息,依据该信息初始化解码器; 2. p_rf_stream:音频数据源句柄; 3. output_sr:解码后的pcm数据输出采样率; 4. 返回值:成功返回解码句柄;失败返回NULL 函数void rf2audio_decoder_stop(dec_obj \*p_recv_dec_obj, bool(\*unregist_func)(void \*)) ************************************************************************************************************** .. note:: 该函数实现音频传输接收停止,关闭解码器; 1. p_recv_dec_obj:解码句柄; 2. unregist_func:后级注销接口;可选择注销DAC或USB_MIC; 3. 返回值:无 函数u32 rf2audio_receiver_write_data(dec_obj \*p_recv_dec_obj, u8 \*data, u32 data_len) ************************************************************************************************************ .. note:: 该函数实现将接收的音频数据写入接收缓存buff; 1. p_recv_dec_obj:解码句柄; 2. data:写入的数据buff; 3. data_len:写入的数据长度; 4. 返回值:本次已成功写入的数据长度; 函数int rf2audio_receiver_mp_input(void \*priv, u32 addr, void \*buf, int len, u8 type) ****************************************************************************************** .. note:: 该函数实现读取缓存中的音频数据; - 音频接收缓存cbuf为rf_data_buff,由cbuf_rf_data管理,解码器启动后读取; 1. priv:私有参数,此处透传解码句柄; 2. addr:解码输入偏移,此处未用上; 3. buf:读取的数据buff; 4. len:读取的数据长度; 5. type:解码输入类型,此处未用上; 6. 返回值:本次已成功读取的数据长度; 函数void rf2audio_receiver_kick_decoder(void \*p_stream_in, void \*psound) **************************************************************************** .. note:: 该函数实现kick解码器启动一次解码; - 接收数据并写入缓存后,启动解码器去缓存中读取数据; - 启动前会判断缓存数据是否满足一帧,满足则启动解码,不满足则退出 1. p_stream_in:数据流管理句柄,该参数为空强制启动一次解码; 2. psound:音频数据句柄 3. 返回值:无; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 数据封包/解包相关接口 ####################### 函数u32 ar_trans_pack(RADIO_PACKET_TYPE type, u8 \*data, u16 data_len) **************************************************************************** .. note:: 该函数实现音频传输封包发送接口; - 发送前会查询发送状态和可发送长度,条件未满足退出发送; 1. type:发送的数据类型; * AUDIO2RF_START_PACKET:音频起始包,包含编码信息; * AUDIO2RF_DATA_PACKET:音频数据包; * AUDIO2RF_STOP_PACKET:音频停止包; 2. data:发送的数据buff; 3. data_len:发送的数据长度; 4. psound:音频数据句柄 5. 返回值:0:成功 非0:失败; 函数bool ar_trans_unpack(rev_fsm_mge \*ops, u8 \*buff, u16 len, u16 \*offset) ************************************************************************************************* .. note:: 该函数实现音频传输接收拆包; - 状态机解析封包的数据头,并分发给下一级; 1. ops:状态机管理句柄; 2. buff:接收数据buff; 3. len:接收数据长度; 4. pcnt:有效数据偏移指针; 5. 返回值:true:找到有效数据 false:未找到有效数据; 函数int unpack_data_deal(rev_fsm_mge \*ops, u8 \*buff, u16 packet_len) **************************************************************************** .. note:: 该函数实现音频传输接收拆包并分发给应用层; - 调用状态机解析封包函数ar_trans_unpack进行拆包,并分发给应用层; 1. ops:状态机管理句柄; 2. buff:接收数据buff; 3. len:接收数据长度; 4. 返回值:true:找到有效数据 false:未找到有效数据; 函数s32 packet_cmd_post(void \*p_pool, RADIO_PACKET_TYPE cmd, u8 \*data, u16 data_len) ************************************************************************************************************ .. note:: 该函数实现将解析出的cmd包及其所带参数post到缓存中; - 调用状态机解析封包函数ar_trans_unpack进行拆包,并分发给应用层; 1. p_pool:cmd缓存池; 2. cmd:cmd命令包; 3. data:cmd命令包所带参数; 4. data_len:cmd命令包所带参数长度; 5. 返回值:成功:0 失败:错误值请查看errno-base.h; 函数u32 packet_cmd_get(void \*p_pool, u8 \*packet, u8 packet_len) **************************************************************************** .. note:: 该函数实现从缓存池中获取cmd包及其所带参数; - 调用状态机解析封包函数ar_trans_unpack进行拆包,并分发给应用层; 1. p_pool:cmd缓存池; 2. packet:应用保存cmd及其参数的缓存; 3. packet_len:应用保存cmd及其参数的缓存长度; 4. 返回值:成功:读出的cmd包长度 失败:0; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 发送队列相关接口 ####################### 函数u32 rf_queue_init(queue_obj \*obj, audio2rf_send_mge_ops \*ops, void \*p_cbuf) ***************************************************************************************** .. note:: 该函数实现初始化发送队列和软中断; 1. obj:应用传入的队列句柄指针; 2. ops:蓝牙发送接口集合,传入的ops指针为非空时会注册队列发送中断,发送中断会通过ops的发送接口发送数据给蓝牙; 3. p_cbuf:发送队列环形buff管理句柄; 4. 返回值:无 函数u32 rf_send_push2queue(queue_obj \*obj, u8 \*packet_data, u16 packet_len) **************************************************************************************** .. note:: 该函数实现将发送给蓝牙的数据压入队列,如果初始化队列时有注册中断,则启动中断发送; 1. obj:应用传入的队列句柄指针; 2. packet_data:发送数据buff; 3. packet_len:发送数据长度; 4. 返回值:成功:0 失败:请查看errno-base.h 函数void rf_send_queue_isr(void) **************************************************** .. note:: 该中断函数实现轮询注册到中断的队列,将发送队列中的数据主动推给蓝牙,蓝牙底层会定时起中断发送给远端,该中断用于带连接的ble传输方案; 1. 返回值:无 函数u32 read_data_from_queue(queue_obj \*obj, u8 \*buf, u32 len) ************************************************************************* .. note:: 该函数实现用户从发送队列读取数据,与rf_send_queue_isr不同的是,read_data_from_queue函数是后级主动从队列取数; 1. obj:队列句柄指针,指定需要被取走数据的队列; 2. buf:从队列读取到的数据都放到该缓存; 3. len:需要从队列读取的数据长度; 4. 返回值:从队列读取到的数据长度; 函数void rf_queue_uninit(queue_obj \*obj, IS_WAIT need_wait) **************************************************************** .. note:: 该函数实现注销用户传入的发送队列 1. obj:用户需要注销的队列句柄指针; 2. need_wait:是否等待队列的数据被消耗完;