录音相关应用
📎 原始文档:https://www.kdocs.cn/l/cjMmuHF6Pgsh 录音相关应用
一、内部flash 录音
- 打开相应的宏配置 打开对应的宏(FLASH_INSIDE_REC_ENABLE)即可跑相应的录音。
//*********************************************************************************//
// fat_FLASH 配置 //
//*********************************************************************************//
#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE
#define FLASH_INSIDE_REC_ENABLE 1
#if TCFG_NORFLASH_DEV_ENABLE
#define TCFG_NOR_FAT 0//ENABLE
#define TCFG_NOR_FS 1//ENABLE
#define TCFG_NOR_REC 0//ENABLE
注意:
修改TCFG_NOR_FS=1后,提示音路径跟着改变,所以会出现没有提示音的情况,修改如下:
#if (0) && TCFG_NOR_FS && (TCFG_VIRFAT_FLASH_ENABLE == 0)
#define NOR_FLASH_RES_ROOT_PATH "storage/res_nor/C/"
#define TONE_RES_ROOT_PATH NOR_FLASH_RES_ROOT_PATH //内置flash提示音根路径
#else
#define TONE_RES_ROOT_PATH SDFILE_RES_ROOT_PATH //内置flash提示音根路径
#endif//TCFG_NOR_FS
2. 录音区的大小 起始地址由工程自动分配, 大小设置如下:
具体文件如下,在 ini 配置中配置给录音的最大容量(REC_LEN)
EXIF_ADR=AUTO;
EXIF_LEN=0x1000;
EXIF_OPT=1;
#WTIF_ADR=BEGIN_END;
#WTIF_LEN=0x1000;
#WTIF_OPT=1;
REC_ADR=AUTO;
REC_LEN=64K;
REC_OPT=1;
PRCT_ADR=0;
PRCT_LEN=CODE_LEN;
PRCT_OPT=2;
apps\common\dev_manager\dev_manager.c 上设置实际需要的大小, 如果大于最大容量, 会报错。
#if FLASH_INSIDE_REC_ENABLE
set_rec_capacity(64*1024);//需要先设置容量,注意要小于Ini文件设置大小.
_sdfile_rec_init();
dev_manager_add("rec_sdfile");
#endif
内置flash录音 注意点:
- 录音时间长短 取决于 录音空间大小和录音的采样率,码率,录音格式三个因素
- 由于录音数据会存放到flash的操作中会关闭总中断,中断优先级<6的中断都会被屏蔽,这样会导致录音采集MIC信号时候,由于关闭总中断的操作,可能会出现丢帧的情况 改善方式是
1、增加一次MIC中断的数据点数大小,减少由于上述操作导致的丢帧情况。不过这样会占用非常大的RAM空间
2、减少录音的采样率和码率
处理案例:
- 1、696系列由于部分芯片是256 擦除的内置flash,所以需要修改兼容256擦除,合并补丁如下:
- 2、6081.2.2版本sdk出现由于写入方式不对,会导致写入后每一页256B,部分内容被擦除,导致卡顿问题出现,合并补丁如下: AC696N&AC608N_内置flash录音修改补丁(兼容256K擦除&&播放卡顿).rar
二、外置flash录音
- 打开相应的宏配置 打开对应的宏即可跑相应的录音。
- 打开外挂flash的宏定义
//*********************************************************************************//
// FLASH 配置 //
//*********************************************************************************//
#define TCFG_NORFLASH_DEV_ENABLE 0//DISABLE_THIS_MOUDLE //需要关闭SD0
#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2
#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTC_03
- flash分区说明: TCFG_NOR_FAT: 类似U盘,实现fat文件系统播歌
TCFG_NOR_FS:实现提示音资源放在外挂flash
TCFG_NOR_REC:实现外挂flash的录音
//*********************************************************************************//
// fat_FLASH 配置 //
//*********************************************************************************//
#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE
#define FLASH_INSIDE_REC_ENABLE 0
#if TCFG_NORFLASH_DEV_ENABLE
#define TCFG_NOR_FAT 0//ENABLE
#define TCFG_NOR_FS 0//ENABLE
#define TCFG_NOR_REC 1//ENABLE
- 录音区的大小 留意以下两个变量的设置
程序上设置实际需要的大小, 如果大于最大容量或者空间重叠, 会复位。
SDK\apps\soundbox\board\br25\板级.c
#if TCFG_NOR_FAT
NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data)
.spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM,
.spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT,
#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1)
.spi_pdata = &spi1_p_data,
#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2)
.spi_pdata = &spi2_p_data,
#endif
.start_addr = 0,
.size = 1*1024*1024,
NORFLASH_DEV_PLATFORM_DATA_END()
#endif
#if TCFG_NOR_FS
NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data)
.spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM,
.spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT,
#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1)
.spi_pdata = &spi1_p_data,
#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2)
.spi_pdata = &spi2_p_data,
#endif
/* .start_addr = 1*1024*1024, */
.start_addr = 0,
.size = 4*1024*1024,
NORFLASH_DEV_PLATFORM_DATA_END()
#endif
#if TCFG_NOR_REC
NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data)
.spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM,
.spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT,
#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1)
.spi_pdata = &spi1_p_data,
#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2)
.spi_pdata = &spi2_p_data,
#endif
.start_addr = 2*1024*1024,
.size = 2*1024*1024,
NORFLASH_DEV_PLATFORM_DATA_END()
#endif
三、录音格式选择
- MP3编码格式选择
#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE)
const int config_mp3_enc_use_layer_3 = 1; ////MP3 layer3 格式
#else
const int config_mp3_enc_use_layer_3 = 0; ////MP3 layer2 格式
#endif
补丁:
- AC695N_soundbox_sdk_release_3.1.0 需要更新 mp3_enc_lib.a 库 链接如下: [【金山文档】 mp3_layer3编码库(ac695&ac696).zip](https://kdocs.cn/l/cc1IY03D0P7K)
- WAV 编码格式选择 WAV格式常用编码说明:WAV格式中常见的压缩编码 - 眼里的圈圈 - 博客园 (cnblogs.com)
- 目前默认SDK支持 Microsoft ADPCM 格式编码。
如果客户需要 IMA ADPCM编码可以按以下方式修改。(目前只支持AC695 310SDK).
AC695N&AC696N&AC608N音箱问题整理.otl
四、长文件名录音支持
1、JL701N为例
【金山文档】 长文件录音
长文件录音.otl
使用以下函数做SD卡的文件读写测试.
长名路径必须以 '\''U' 开头做为标识。
void filename_test(void){
u8 *test_data = "filename test123"; //写入文件数据
u8 read_buf[32];//读取数据buf
int len;//文件大小
char path[256] = "storage/sd0/C";//路径
FILE* fd = NULL;//文件句柄指针
//文件名:longfilename.txt 通过字符转UTF16LE编码写入
// char file_name[128] ={'/','\\','U',0x6C,0x00,0x6F,0x00,0x6E,0x00,0x67,0x00,0x66,0x00,0x69,0x00,0x6C,0x00,0x65,0x00,0x6E,0x00,0x61,0x00,0x6D,0x00,0x65,0x00,0x2E,0x00,0x74,0x00,0x78,0x00,0x74,0x00};
//文件名:hello/测试创建长文件名测试.txt
//char file_name[128] = {'/','h', 'e','l','l','o','/','\\','U',0x4B,0x6D,0xD5,0x8B,0x1B,0x52,0xFA,0x5E,0x7F,0x95,0x87,0x65,0xF6,0x4E,0x0D,0x54,0x4B,0x6D,0xD5,0x8B,0x2E,0x00,0x74,0x00,0x78,0x00,0x74,0x00};
//文件夹名:测试创建长文件名测试
//char file_name[128] = { '/','\\','U',0x4B,0x6D,0xD5,0x8B,0x1B,0x52,0xFA,0x5E,0x7F,0x95,0x87,0x65,0xF6,0x4E,0x0D,0x54,0x4B,0x6D,0xD5,0x8B};
//测试长文件夹名测试/测试创建长文件名测试.txt
char file_name[128] = {'/','\\','U',0x4B,0x6D,0xD5,0x8B,0x7F,0x95,0x87,0x65,0xF6,0x4E,0x39,0x59,0x0D,0x54,0x4B,0x6D,0xD5,0x8B,'/',0x00,'\\','U',0x4B,0x6D,0xD5,0x8B,0x1B,0x52,0xFA,0x5E,0x7F,0x95,0x87,0x65,0xF6,0x4E,0x0D,0x54,0x4B,0x6D,0xD5,0x8B,0x2E,0x00,0x74,0x00,0x78,0x00,0x74,0x00};
// char file_name[128] = "/abdccbasbdoabioasdasdasdascz/sadklajlkjklzxcznmxczxz.txt";
printf("strlen(path)=%d,strlen file_name=%d",strlen(path),strlen(file_name));
memcpy(path+strlen(path),file_name,sizeof(file_name));//将文件名file_name复制到path路径后
printf("strlen(path)=%d,file_name=%d",strlen(path),sizeof(file_name));
put_buf(path,sizeof(path));
//创建并写文件
fd = fopen(path, "w+");//打开可 读/写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。
//FILE *fd = fopen(CONFIG_ROOT_PATH"test/test.txt", "w+");
if(fd){
// fwrite(test_data, 1, strlen(test_data), fd);//写入文件数据
fwrite(fd, test_data, strlen(test_data));//写入文件数据
fclose(fd);//关闭文件
printf("write file : %s \n", test_data);
}
//读文件
put_buf(path,sizeof(path));
fd = fopen(path, "r");//以只读方式打开文件,该文件必须存在。
printf("fd= %x",fd);
//fd = fopen(CONFIG_ROOT_PATH"test/test.txt", "r");
if(fd){
len = flen(fd);//获取整个文件大小
// fread(read_buf, 1, len, fd);//读取文件
fread(fd,read_buf,len);//读取文件
fclose(fd);//关闭文件
printf("read file : %s \n", read_buf);
}
}
五、暂停录音操作(获取录音buf处)
这里可以增加一个标志位, 如果是暂停的状态, 这个cbuf不写即cbuf_write函数不执行即可,示例如下:
备注:此处也是录音数据写入的地方,可以在此处处理写入的数据。
六、其他模式下播放录音操作
使用record_file_play函数可以做到播放最后一次录音的音频,但公版SDK只能做到在蓝牙模式和录音模式下实现,在linein和fm模式下无法做到,原因是:在linein和fm模式下本身就存在一个解码的任务,播放录音文件又是一个解码任务,冲突导致。所以需要在播放录音文件前将解码关闭,播放结束后重新打开即可,详细代码见附件程序。
【金山文档】 sdk_3.0.4_其他模式播放录音demo
https://kdocs.cn/l/cueQnM46B7wk
七、混合录音
- 功能配置 目前混合录音只适用于有音频流写法的SDK,音箱的SDK均支持该功能,耳机的SDK不支持该功能
在对应的板级头文件开启宏条件:
- 混合录音接口录音逻辑 具体可以参考发布的SDK中doc文件夹内的《recorder mix接口设计说明文档.pdf》

- AC695N_soundbox_sdk_release_3.1.0 - 混合录音 695V310由于更新新音效,混合录音会会出现混合录音录不了混响的问题
可以参考以下代码:
【金山文档】 AC695N_soundbox_sdk_release_3.1.0_混合录音 https://kdocs.cn/l/coWjEB71gqzu
问题:
较多客户反馈开混合录音蓝牙和混响的声音的时候会出现卡音,提供两种处理思路:
- 第一种是将混响算法放RAM里面跑,板子头文件里面有这个相应配置

- 第二种是混响可以关闭不需要的节点以节省算力

- 录音事件处理
static void pcm2file_enc_w_evt(void *hdl, int evt, int parm)
{
struct pcm2file_enc_hdl *enc = hdl;
printf("evt: %d ", evt);
if (evt == ENC_WRITE_FILE_EVT_WRITE_ERR) {
enc->enc_err = 1;
pcm2file_wfile_resume(enc);
pcm2file_enc_resume(enc);
audio_encoder_stop(&enc->encoder);
} else if (evt == ENC_WRITE_FILE_EVT_FILE_CLOSE) {
printf("sclust: %d ", parm);
}
}
本文档为保密信息,未经授权,请勿转发或告知第三方。非常感谢!
This electronic documentation and any attachments are confidential and may be legally privileged or otherwise protected from disclosure. If you are not the intended recipient, please do not disclose the contents to anyone。
Thank you for your cooperation!
解析权归杰理所有!
The analysis right belongs to JieLi Technology Co., Ltd.