音频系统管理(CODEC MANAGER)¶
1、音频系统简介¶
- 芯片内部自带 MIC ADC(MADC)和内部 CODEC(DCODEC);
- 支持模拟 MIC、数字 MIC(PDM)、内部 DAC 播放、外挂 IIS CODEC 多种录音/放音通路;
- 采音与放音经 IIS 专用 IISDMA 搬运,互不占用通用 DMA;
- 驱动程序简单易用,基于 FreeRTOS 编写,只能在 FreeRTOS 的基础上运行。
CI14LP 系列芯片作为一款低功耗智能语音芯片,其语音通路(MADC、DCODEC、IIS、IISDMA)占有非常重要的部分。片内 MADC 支持单通道模拟 MIC 输入和双通道数字 MIC 输入;片内 DCODEC 提供单通道 ADC 与双声道 DAC 输出(支持差分/单端、模拟/数字功放对接)。使用 CI14LP 芯片进行录音和放音,无需外接 CODEC 芯片,大大增加系统稳定性并降低成本。录音和放音组件(codec_manager)将 MADC、DCODEC、IIS 和 IISDMA 串联起来,形成 CI14LP 芯片的语音通路。
2、音频系统管理程序简介¶
CI14LP SDK 提供了一套录音设备和放音设备的驱动程序(codec_manager)。通过调用这套驱动程序提供的 API,用户就可以完成常规配置的录音和放音操作,而不需要考虑繁琐的 IIS、IISDMA、MADC/DCODEC 的配置。
组件源码位于 components\codec_manager\(codec_manager.c / codec_manager.h),同时提供无锁环形队列(ringbuf.c / ringbuf.h)用于双核间音频数据传输。
3、API列表¶
| 函数名 | 描述 |
|---|---|
| cm_init | 初始化音频 CODEC 管理模块 |
| cm_reg_codec | 注册一个音频 CODEC |
| cm_register_codec_callback | 注册 CODEC 事件回调函数 |
| cm_config_pcm_buffer | 配置录音/放音 PCM buffer |
| cm_config_codec | 配置录音/放音音频格式 |
| cm_start_codec | 启动录音或放音 |
| cm_stop_codec | 停止录音或放音 |
| cm_read_codec | 同步读取录制的 PCM 数据 |
| cm_write_codec | 写入放音数据 |
| cm_get_pcm_buffer | 获取空闲 PCM buffer |
| cm_release_pcm_buffer | 释放读到的录音 buffer |
| cm_set_codec_dac_gain | 设置 DAC(播放)增益 |
| cm_set_codec_adc_gain | 设置 ADC(录音)增益 |
| cm_set_codec_adc_digital_gain | 设置 ADC 数字增益 |
| cm_set_codec_alc | 录音 ALC 使能控制 |
| cm_set_codec_dac_enable | DAC 功能使能控制 |
| cm_set_codec_mute | 设置静音模式 |
| cm_config_iis_probe_en | 配置 IIS 探针模式 |
| cm_get_codec_empty_buffer_number | 查询空闲 buffer 数量 |
| cm_get_codec_busy_buffer_number | 查询忙 buffer 数量 |
4、录音示例¶
驱动文件地址:SDK\components\codec_manager\codec_manager.c
初始化代码、获取数据的示例(参考 driver\boards\board.c 中 audio_in_codec_registe() 与示例工程用法):
#include "codec_manager.h"
#define HOST_MIC_RECORD_CODEC_ID 1 // 主MIC录音codec id(sdk_default_config.h定义)
//录音codec硬件信息(板级注册,静态配置)
static const cm_codec_hw_info_t madc_hw_info =
{
.IICx = IIC_NULL, //片内CODEC无需IIC
.input_iis.iisnum = IISNum1_MADC_RX, //录音使用与MADC关联的IIS1 RX
.input_iis.iis_mode_sel = IIS_SLAVE,
.input_iis.codec_device = CM_MADC_ANALOG_MIC_RECORD, //模拟MIC录音
.input_iis.over_sample = IIS_MCLK_FS_256,
.input_iis.iis_data_format = IIS_DF_IIS,
.input_iis.sck_lrck_ratio = IIS_SCK_LRCK_64,
.codec_if =
{
.codec_init = madc_codec_init, //MADC驱动实现
.codec_config = madc_codec_config,
.codec_start = madc_codec_start,
.codec_stop = madc_codec_stop,
.codec_ioctl = madc_codec_ioctl,
},
};
//音频格式
static const cm_sound_info_t host_mic_sound_info =
{
.sample_rate = 16000, //采样率16K
.sample_depth = IIS_DW_16BIT,//采样深度16bit
.channel_flag = CM_CHA_LEFT, //左声道
};
cm_pcm_buffer_info_t record_buffer_info;
void audio_in_codec_registe(void)
{
//注册录音codec
cm_reg_codec(HOST_MIC_RECORD_CODEC_ID, (cm_codec_hw_info_t*)&madc_hw_info);
//配置录音PCM buffer
record_buffer_info.record_buffer_info.block_num = AUDIO_IN_BUFFER_NUM;
record_buffer_info.record_buffer_info.block_size = 160*2; //每帧160点16bit
record_buffer_info.record_buffer_info.buffer_size =
record_buffer_info.record_buffer_info.block_size *
record_buffer_info.record_buffer_info.block_num;
record_buffer_info.record_buffer_info.pcm_buffer = record_pcm_buffer;
cm_config_pcm_buffer(HOST_MIC_RECORD_CODEC_ID, CODEC_INPUT, &record_buffer_info);
//配置录音音频格式
cm_config_codec(HOST_MIC_RECORD_CODEC_ID, CODEC_INPUT, (cm_sound_info_t*)&host_mic_sound_info);
}
读取录音数据:
uint32_t data_addr, data_size;
cm_read_codec(HOST_MIC_RECORD_CODEC_ID, &data_addr, &data_size, wait_tick);
if(data_addr)
{
//处理data_addr指向的data_size字节PCM数据
//处理完成后释放buffer,继续循环录音
cm_release_pcm_buffer(HOST_MIC_RECORD_CODEC_ID, CODEC_INPUT, (void*)data_addr);
}
5、放音示例¶
初始化代码、写入数据播放示例(参考 driver\boards\board.c 中 audio_play_out_codec_registe()):
#include "codec_manager.h"
#define PLAY_CODEC_ID 2 //播音codec id(sdk_default_config.h定义)
//放音codec硬件信息(板级注册,静态配置)
static const cm_codec_hw_info_t dcodec_hw_info =
{
.IICx = IIC_NULL,
.output_iis.iisnum = IISNum1_DCODEC_TX, //放音使用与DCODEC关联的IIS1 TX
.output_iis.iis_mode_sel = IIS_SLAVE,
.output_iis.codec_device = CM_DCODEC_DAC_PLAY, //内部DAC放音
.output_iis.iis_data_format = IIS_DF_IIS,
.codec_if =
{
.codec_init = dcodec_codec_init, //DCODEC驱动实现
.codec_config = dcodec_codec_config,
.codec_start = dcodec_codec_start,
.codec_stop = dcodec_codec_stop,
.codec_ioctl = dcodec_codec_ioctl,
},
};
void audio_play_out_codec_registe(void)
{
//注册放音codec
cm_reg_codec(PLAY_CODEC_ID, (cm_codec_hw_info_t*)&dcodec_hw_info);
//放音引脚、功放使能配置
pad_config_for_power_amplifier();
}
获取 buffer 并写入数据播放:
uint32_t ret_p = 0;
//获取空闲PCM buffer
cm_get_pcm_buffer(PLAY_CODEC_ID, &ret_p, portMAX_DELAY);
int16_t *out_p = (int16_t *)ret_p;
if(out_p)
{
memcpy(out_p, pcm_src, 320*2); //填入待播放数据
cm_write_codec(PLAY_CODEC_ID, out_p, portMAX_DELAY); //写入播放
}
6、codec 设备类型¶
cm_codec_device_t 指定 codec_manager 管理的设备通路:
| 枚举值 | 说明 |
|---|---|
| CM_MADC_ANALOG_MIC_RECORD (0x11) | MADC 模拟 MIC 录音 |
| CM_MADC_DIGITAL_MIC_RECORD (0x22) | MADC 数字 MIC(PDM)录音 |
| CM_DCODEC_DIGITAL_MIC_RECORD (0x33) | DCODEC 数字 MIC(PDM)录音 |
| CM_DCODEC_DAC_PLAY (0x44) | DCODEC DAC 播放 |
7、API 参考¶
本模块接口声明于 components\codec_manager\codec_manager.h,无锁环形队列接口声明于 components\codec_manager\ringbuf.h。
底层驱动接入接口:
- MADC:
driver\ci14lp_chip_driver\inc\ci14lp_madc.h(madc_codec_init/start/config/stop/ioctl) - DCODEC:
driver\ci14lp_chip_driver\inc\ci14lp_dcodec.h(dcodec_codec_init/start/config/stop/ioctl)