Audio In¶
概述¶
音频采集模块,数据来源支持数字麦(PDM)、H_ADC 和 ECHO(内循环来自于 aout 的回声数据);采集到的音频数据存储至内存或者输出至其他模块使用。
输入源¶
ADC
PDM
ECHO_PCM
功能模块¶
去直流滤波器(DC Filter)
录制通路音量调节
增益粗调
增益细调
存储 PCM FIFO¶
PCM0 FIFO
PCM1 FIFO
PCM2 FIFO
功能特性¶
ADC¶
ADC 输入时钟选择,参考结构体 GX_HAL_AIN_ADC_CLK
H_ADC CLK 0
重要
注意:APUS ADC 数量配置最大只支持一路,配置时只有 GX_HAL_AIN_ADC_CLK_0
示例代码
GX_HAL_AIN_INPUT_ADC adc = { .adc_clk_sel = GX_HAL_AIN_ADC_CLK_0, //ADC clk 选择 clk0,该芯片只支持 adc_clk_0 }; gx_hal_ain_adc_set_input(&adc);
PDM¶
当选择数据输入来源于 PDM 时,需要配置管脚复用功能,对应管脚功能分别配置为 PDM_CLK 和 PDM_DATA。
时钟模式选择,参考结构体 GX_HAL_AIN_PDM_CLK_MODE
master 模式
slave 模式(时钟来自于外部)
重要
注意:选择 PDM 时钟模式为 slave 模式时,需要调用时钟配置接口 gx_clk_mod_set_src(GX_CLK_MOD_PDM, GX_CLK_MOD_AUD_SYS_PDM);
输入时钟选择,参考结构体 GX_HAL_AIN_PDM_CLK
1024KHz
2048KHz
3072KHz
6144KHz
重要
注意:选择 PDM 时钟模式为 slave 模式时,为保证数据正确,输入时钟的配置必须与外部提供的时钟一致。
示例代码
/*PDM 时钟模式为 master*/ GX_HAL_AIN_INPUT_PDM pdm = { .pdm_clk_mode = GX_HAL_AIN_PDM_CLK_MASTER, //PDM 时钟模式 master 模式 .pdm_clk_sel = GX_HAL_AIN_PDM_CLK_6144K, //PDM 时钟 6.144M }; gx_hal_ain_pdm_set_input(&pdm); /*PDM 时钟模式为 slave*/ GX_HAL_AIN_INPUT_PDM pdm = { .pdm_clk_mode = GX_HAL_AIN_PDM_CLK_SLAVE, //PDM 时钟模式 slave 模式 .pdm_clk_sel = GX_HAL_AIN_PDM_CLK_6144K, //PDM 时钟 6.144M(根据外部提供的时钟进行配置) }; if (pdm.pdm_clk_mode == GX_HAL_AIN_PDM_CLK_SLAVE) { gx_clk_mod_set_src(GX_CLK_MOD_PDM, GX_CLK_MOD_AUD_SYS_PDM); } gx_hal_ain_pdm_set_input(&pdm);
ECHO¶
输入采样率选择,参考结构体 GX_HAL_AIN_ECHO_PCM_FS
16KHz
32KHz
48KHz
重要
注意:echo 采样率选择需要和 audio out 模块采样率配置对应
示例代码
GX_HAL_AIN_INPUT_ECHO echo = { .echo_pcm_fs = GX_HAL_AIN_ECHO_PCM_FS_48K, //ECHO 输入采样率 48KHz }; gx_hal_ain_echo_set_input(&echo);
DC Filter¶
去直流滤波器,可选择是否开启,也可配置滤波器参数。
去直流滤波器使能配置在 GX_HAL_AIN_CHANNEL_CFG 结构体下的 dcf_enable。
通过函数 gx_hal_ain_dcf_set_params 配置滤波器参数。
备注
无特殊需求不需要改动。
增益粗调¶
增益粗调的调整步进为 6dB,只能增大音量,不能减小音量(每增加 6dB 即为音量放大两倍,如果音量增加 n*6dB 即为音量放大 2^n 倍)
需要调整时配置结构体 GX_HAL_AIN_GAIN 的 coarse 成员
0 为无增益,1 为增加 6dB,向上配置步进为 6dB,最大可配置 9(增加 54dB)。
增益细调¶
增益细调,最小精度为 0.001dB
计算公式是:fine = 8192*pow(10, (fine_vol_dB/20.0));
fine = 8192:无增益无衰减(默认值)
8192 < fine < 32747:音量放大 0~12dB
0 < fine < 8192:音量衰减 0~78dB
重要
注意:fine 配置为 0 时为静音。计算公式中的 fine_vol_dB 为需要调整的音量大小(如 10dB 或 -5dB)。
需要调整时配置结构体 GX_HAL_AIN_GAIN 的 fine 成员。
示例代码
GX_HAL_AIN_GAIN gain = {
.fine = 8192, //增益细调,8192 为默认值无增益无衰减
.coarse = 0, //增益粗调,0 为默认值无增益无衰减
};
gx_hal_ain_pcmw_set_gain(&gain, 1);
Route PCM¶
route 通道参数相关配置,参考结构体 GX_HAL_AIN_CHANNEL_CFG
通道数据源选择 GX_HAL_AIN_CHN_SRC
通道内 pcm 数据大小端 GX_HAL_AIN_PCM_ENDIAN
通道内声道选择
通道中的去直流滤波器使能
通道使能
示例代码
GX_HAL_AIN_CHANNEL_CFG ch_cfg = { .source = GX_HAL_AIN_CHN_SRC_ADC, //PCM 数据来源选择来源于 ADC .endian = GX_HAL_AIN_PCM_ENDIAN_LITTLE_16BIT, //PCM 数据存储大小端为 16bit 小端存储 //... 其余成员使用时按需配置 }; gx_hal_ain_pcmw_start(&ch_cfg, 3);
PCM 录制相关配置见 \ref GX_HAL_AIN_PCMW_CFG(配置函数 \ref gx_hal_ain_pcmw_start)
单次写入 pcm 门限 GX_HAL_AIN_PCMW_FIFO_THRESHOLD
一帧单个声道的 pcm 样点数(中断上报 pcm 样点数)
重要
注意:一帧的样点数最好是 32 的倍数,非 32 的倍数中断时间间隔会稍微有点误差。buffer 大小必须大于等于两帧。
单个 buffer 的大小
重要
注意:单个 buffer 大小必须为 128 的倍数且必须大于等于两帧。
每个 buffer 的起始地址 (物理地址) (该芯片最大可用 pcm buffer 为三个)
重要
注意:buffer 的起始地址必须 8 字节对齐,为保证数据完整性,最好 32 字节对齐。
PCM 写完成中断回调函数 GX_HAL_AIN_PCMW_CB
示例代码
GX_HAL_AIN_PCMW_CFG pcm = { .bit_size = GX_HAL_AIN_PCMW_BS_16, //存储位宽 16bit 存储 .fifo_threshold = GX_HAL_AIN_PCMW_FT_HALF, //二分之一门限(FIFO 内部存满 64 字节数据后写入内存) .cb_func = ain_func_cb, //中断处理函数,函数指针 // ... 其余成员使用时按需配置 }; gx_hal_ain_pcmw_start(&pcm, 1);
示例代码¶
ADC 输入,数据存储至 PCM(SRAM)¶
GX_HAL_AIN_INPUT_ADC adc = {
.adc_clk_sel = GX_HAL_AIN_ADC_CLK_0, //adc clk 选择,该芯片只支持 adc_clk_0
};
gx_hal_ain_adc_set_input(&adc);
GX_HAL_AIN_CHANNEL_CFG channel_cfg[3];
unsigned int channel_num = 3; //实际使用中按需配置,该芯片最大 3
GX_HAL_AIN_PCMW_CFG pcm = {
.bit_size = GX_HAL_AIN_PCMW_BS_16, //存储位宽 16bit 存储
.fifo_threshold = GX_HAL_AIN_PCMW_FT_HALF, //二分之一门限(FIFO 内部存满 64 字节数据后写入内存)
.cb_func = ain_func_cb, //中断处理函数 (函数指针),使用时填入实现的中断回调函数名
.buffer_size = 1024; //PCM buffer 大小,实际使用按需配置
.frame_pcm_num = 128; //中断上报 PCM 样点数,实际使用按需配置
};
for (int i = 0; i < channel_num; ++i) {
channel_cfg[i].dcf_enable = 1;
channel_cfg[i].endian = GX_HAL_AIN_PCM_ENDIAN_LITTLE_16BIT;
channel_cfg[i].source = GX_HAL_AIN_CHN_SRC_ADC;
channel_cfg[i].channel = 0;
channel_cfg[i].enable = 1;
pcmw_cfg.buffer_saddr[i] = (void *)0x2000000; //举例,实际使用按需配置
}
gx_hal_ain_pcmw_set_output(channel_cfg, channel_num);
gx_hal_ain_pcmw_start(&pcmw_cfg, channel_num);
PDM 输入,数据存储至 PCM(SRAM)¶
GX_HAL_AIN_INPUT_PDM pdm = {
.pdm_clk_mode = GX_HAL_AIN_PDM_CLK_MASTER, //PDM 时钟模式 master 模式
.pdm_clk_sel = GX_HAL_AIN_PDM_CLK_6144K, //PDM 时钟 6.144M
};
gx_hal_ain_pdm_set_input(&pdm);
GX_HAL_AIN_CHANNEL_CFG channel_cfg[3];
unsigned int channel_num = 3; //实际使用中按需配置,该芯片最大 3
GX_HAL_AIN_PCMW_CFG pcm = {
.bit_size = GX_HAL_AIN_PCMW_BS_16, //存储位宽 16bit 存储
.fifo_threshold = GX_HAL_AIN_PCMW_FT_HALF, //二分之一门限(FIFO 内部存满 64 字节数据后写入内存)
.cb_func = ain_func_cb, //中断处理函数 (函数指针),使用时填入实现的中断回调函数名
.buffer_size = 1024; //PCM buffer 大小,实际使用按需配置
.frame_pcm_num = 128; //中断上报 PCM 样点数,实际使用按需配置
};
for (int i = 0; i < channel_num; ++i) {
channel_cfg[i].dcf_enable = 1;
channel_cfg[i].endian = GX_HAL_AIN_PCM_ENDIAN_LITTLE_16BIT;
channel_cfg[i].source = GX_HAL_AIN_CHN_SRC_ADC;
channel_cfg[i].channel = 0;
channel_cfg[i].enable = 1;
pcmw_cfg.buffer_saddr[i] = (void *)0x2000000; //举例,实际使用按需配置
}
gx_hal_ain_pcmw_set_output(channel_cfg, channel_num);
gx_hal_ain_pcmw_start(&pcmw_cfg, channel_num);