当前位置:网站首页>Luoda development - audio stream processing - AAC / loopbacktest as an example
Luoda development - audio stream processing - AAC / loopbacktest as an example
2022-07-26 04:00:00 【MicMind】
Audio streaming is mainly in DSP Intermediate processing , Here to aac_dec_interfaces.c and audio_loopback_test_interface.c Two source files to analyze and introduce with examples . The paths of the two files are :
bta_sdk\dsp\middleware\MTK\dspalg\aac_decoder\src
bta_sdk\dsp\middleware\MTK\dspalg\audio_loopback_test\srcamong aac_dec_interface.c There are also in another position :bta_sdk\dsp\middleware\third_party\dspalg\aac_decoder\src
It can be seen from the path that this is a third party ACC Coding function .
1、aac_dec_interfaces.c[MTK\dspalg\aac_decoder\src]
The function of the function passes the input audio data through AAC After encoding, it is sent to the left and right output channels ; if AAC The processing module has not been initialized , Then initialize first and then process the data ; The interface function in the file is :
bool stream_codec_decoder_aac_process (void *para);The flow of the function is shown in the following figure :

AAC The encoding function is :
int AIR_AAC_decoder(void *AAC_INSTANCE, uint8_t *input_buf, int aac_packet_len , int32_t *output_L, int32_t *output_R, int *decoded_len);Parameters AAC_INSTANCE Used to store AAC Instance object of function module initialization , Its value is due to AAC The first parameter of the initialization function returns :
int AIR_AAC_init(void *AAC_INSTANCE, uint8_t *input_buf, int aac_packet_len , int16_t *ch, uint32_t *srate, int16_t *brate);Parameters aac_packet_len by input_buf The length of the audio stream to be processed ;
Parameters input_buf For input audio data , From to Bluetooth channel , For example, the sound stream from the mobile phone ;
Parameters output_L Is the audio stream pointing to the left channel output buffer;
Parameters output_R Is the audio stream output to the right channel buffer;
Parameters decoded_len Express AAC Encode the length of data actually processed ;
From which we can know , The source of the audio stream is 1 Input channels , It flows to No 1 And the 2 A passage , Its interface functions are :
void* stream_codec_get_1st_input_buffer(void* para)
void* stream_codec_get_1st_output_buffer(void* para)
void* stream_codec_get_2nd_output_buffer(void* para)The position of the interface function is :
bta_sdk\dsp\middleware\MTK\dspfw\port\chip\ab156x\src\dsp_lower_layer\dsp_interface\ dsp_feature_interface.cAnalysis code can know , The output channels are 6 individual , Defined by the following macro :
#define CALLBACK_OUTPUT_PORT_MAX_NUM 6Input channels share 5 individual , Defined by the following macro :
#define CALLBACK_INPUT_PORT_MAX_NUM 5The general function to get the cache address of the specified channel is :
void* stream_codec_get_input_buffer(void* para, uint32_t channel)
void* stream_codec_get_output_buffer(void* para, uint32_t channel)The following function , It can be used to obtain the length of the input data stream :
uint16_t stream_codec_get_input_size(void* para)In addition, there is the data width of the output channel , be for the purpose of 16 It's still 32 Bit data format :
uint8_t stream_codec_get_output_resolution(void* para)These functions are used to obtain the cache first address of the corresponding channel data , Then get the length of the data , In this way, these data can be operated .
2、audio_loopback_test_interface.c[bta_sdk\dsp\middleware\MTK\dspalg\audio_loopback_test\src]


Function call flow :

3、 Definition of input and output buffer
that , Another question , How to define the storage fetches obtained by these interfaces , That is to say 1 individual inout buffer, The first 1 individual input buffer Point to the buffer Where is it , Who will go to this buffer Put data in it ?
stream_function_get_1st_inout_buffer
stream_function_get_2nd_inout_buffer
void* stream_codec_get_1st_input_buffer(void* para)
void* stream_codec_get_1st_output_buffer(void* para)
void* stream_codec_get_2nd_output_buffer(void* para)You can know by code , The first address of the storage area is determined by out_ptr[] and in_ptr[] Defined by :
typedef struct DSP_Entry_Para_s {
VOID* mem_ptr;
U16 in_malloc_size;
U16 in_size;
VOID* in_ptr[CALLBACK_INPUT_PORT_MAX_NUM];
U16 out_malloc_size;
U16 codec_out_size;
VOID* out_ptr[CALLBACK_OUTPUT_PORT_MAX_NUM];
U8 in_channel_num;
U8 in_sampling_rate;
U8 out_channel_num;
U8 device_out_channel_num;
U8 software_handled_channel_num;
U8 codec_out_sampling_rate;
TaskHandle_t DSPTask;
U8 with_encoder;
U16 encoder_out_size;
U8 with_src;
U8 src_out_sampling_rate;
U16 src_out_size;
U16 pre_codec_out_size;
U8 pre_codec_out_sampling_rate;
U8 skip_process;
U8 bypass_mode;
bool force_resume;
DSP_FEATURE_RESOLUTION resolution;
DSP_FEATURE_NUMBERING number;
DSP_PKT_INFO_STRU pkt_info;
#ifdef PRELOADER_ENABLE
VOID* feature_ptr;
#endif
} DSP_ENTRY_PARA, *DSP_ENTRY_PARA_PTR;These two specified initializations , It's in the file dsp_callback.c->DSP_Callback_ParaSetup(DSP_STREAMING_PARA_PTR) Finish in , As shown in the following code .

if (stream->callback.FeatureTablePtr->FeatureType != CODEC_PCM_COPY) {
/* malloc in_ptr */
configASSERT(stream->callback.EntryPara.in_channel_num<=CALLBACK_INPUT_PORT_MAX_NUM);
mallocSize = stream->callback.EntryPara.in_malloc_size*stream->callback.EntryPara.in_channel_num;
mem_ptr = DSPMEM_tmalloc(stream->callback.EntryPara.DSPTask, mallocSize, stream);
memset(mem_ptr, 0, mallocSize);
for (i=0 ; i<stream->callback.EntryPara.in_channel_num ; i++)
{
stream->callback.EntryPara.in_ptr[i] = mem_ptr;
mem_ptr += stream->callback.EntryPara.in_malloc_size;
}
/* malloc out_ptr */
chNum = MAX(stream->callback.EntryPara.out_channel_num, 2);
configASSERT(chNum<=CALLBACK_OUTPUT_PORT_MAX_NUM);
mallocSize = stream->callback.EntryPara.out_malloc_size*chNum;
mem_ptr = DSPMEM_tmalloc(stream->callback.EntryPara.DSPTask, mallocSize, stream);
memset(mem_ptr, 0, mallocSize);
for (i=0 ; i<chNum ; i++)
{
stream->callback.EntryPara.out_ptr[i]= mem_ptr;
mem_ptr += stream->callback.EntryPara.out_malloc_size;
}
} else {
//CODEC_PCM_COPY
chNum = MAX(MAX(stream->callback.EntryPara.out_channel_num, 1), stream->callback.EntryPara.in_channel_num);
configASSERT(chNum<=MIN(CALLBACK_INPUT_PORT_MAX_NUM, CALLBACK_OUTPUT_PORT_MAX_NUM));
frameSize = MAX(stream->callback.EntryPara.in_malloc_size, stream->callback.EntryPara.out_malloc_size);
stream->callback.EntryPara.in_malloc_size = stream->callback.EntryPara.out_malloc_size = frameSize;
stream->callback.EntryPara.out_channel_num = chNum;
mallocSize = frameSize*chNum;
if ((frameSize & 3) && (chNum > 1))
{
DSP_MW_LOG_I("[DSP] Unaligned Callback Frame Size:%d!!", 1, frameSize);
}
mem_ptr = DSPMEM_tmalloc(stream->callback.EntryPara.DSPTask, mallocSize, stream);
memset(mem_ptr, 0, mallocSize);
for (i=0 ; i<chNum ; i++)
{
stream->callback.EntryPara.out_ptr[i]= mem_ptr;
stream->callback.EntryPara.in_ptr[i] = mem_ptr;
mem_ptr += frameSize;
}
DSP_MW_LOG_I("[DSP] Callback stream Setup codec is CODEC_PCM_COPY, Frame Size:%d, channel_num:%d", 2, frameSize, chNum);
}function stream_codec_decoder_aac_process(…) In the file dsp_sdk.c Is indexed to data stream_feature_table[] in , As shown in the figure below :

So by analyzing , You can know CODEC_DECODER_AAC This type of , Is in A2DP Is used in , And it is used when decoding , Because you can guess ,AAC Is to serve A2DP Decode the incoming audio , And then through Speaker Play out .

So it is not difficult to understand ,
bool stream_codec_decoder_aac_process (void *para)Function stream_codec_get_1st_input_buffer It means A2DP Of Source Incoming audio stream , and stream_codec_get_1st_output_buffer
and
stream_codec_get_2nd_output_buffer
It's left and right Speaker Output data stream , Flow direction left and right Speaker Two channels ;
- about A2DP, in_channel_num=1, The definition is shown in the figure below :

- about A2DP, out_channel_num=2, As shown in the figure below :

As indicated by the red line ,out_channel_num by 2 perhaps audio.channel_num( as for channel_num What's the value of , Not studied yet , Guess it should be 1 perhaps 2);
边栏推荐
- php中可以使用取绝对值函数 abs() 将负数转成正数
- php eval() 函数可以将一个字符串当做 php 代码来运行
- 苹果在其产品中拿掉了最后一颗Intel芯片
- Testing is not valued? Senior: you should think in another position
- Basic line chart: the most intuitive presentation of data trends and changes
- Summary of senior report development experience: understand this and do not make bad reports
- STM32状态机编程实例——全自动洗衣机(下)
- php 实现从1累加到100的算法
- 容器跑不动?网络可不背锅
- UFS Clk Gate介绍
猜你喜欢

Dat of deep learning

Can't the container run? The Internet doesn't have to carry the blame

WAF details

【程序员必备】七夕表白攻略:”月遇从云,花遇和风,晚上的夜空很美“。(附源码合集)

用GaussDB(for Redis)存画像,推荐业务轻松降本60%

Find My技术|物联网资产跟踪市场规模达66亿美元,Find My助力市场发展

Analysis on the infectious problem of open source license

Aike AI frontier promotion (7.18)

基于Caffe ResNet-50网络实现图片分类(仅推理)的实验复现

Visio: how do Gantt charts merge cells? Solution: overwrite cells
随机推荐
Multi merchant mall system function disassembly lecture 15 - platform side member label
The convolution kernel is expanded to 51x51, and the new CNN architecture slak counterattacks the transformer
研发了 5 年的时序数据库,到底要解决什么问题?
Apply for SSL certificate, configure SSL certificate for domain name, and deploy server; Download and installation of SSL certificate
Kbpc1510-asemi large chip 15A rectifier bridge kbpc1510
1311_ Hardware design_ Summary of ICT concept, application, advantages and disadvantages
按键消抖的Verilog实现
The B2B2C multi merchant system has rich functions and is very easy to open
【单片机仿真项目】外部中断0控制8个发光二极管闪烁
Chinese database oceanbase was selected into the Forrester translational data platform report
Sentinel fusing and current limiting
Wechat applet to realize music player (4) (use pubsubjs to realize inter page communication)
Aike AI frontier promotion (7.18)
zk-SNARK:关于私钥、环签名、ZKKSP
Operator new, operator delete supplementary handouts
【Unity3d Shader】角色投影与倒影
第十八章:2位a~b进制中均位奇观探索,指定整数的 3x+1 转化过程,指定区间验证角谷猜想,探求4份黑洞数,验证3位黑洞数
容器跑不动?网络可不背锅
Data elements
day03_ 1_ Idea tutorial