9.8. 音频解码AUDIO_DEC
概述
提供音频解码的使用流程
9.8.1. 使用流程
1.打开解码服务
struct server *enc_server = server_open("audio_server", "dec"); //打开解码服务
注册解码服务事件回调
注意:服务事件回调是通过任务的队列消息传递的,此消息是不允许丢失的,使用者需要做好相应的异步处理,哪个线程注册该回调函数就是该线程负责接收,特别需要注意不能出现消息队列填满引起的死锁问题,调用的任务需要通过os_taskq_pend接收消息回调。
static void dec_server_event_handler(void *priv, int argc, int *argv)
{
switch (argv[0])
{
case AUDIO_SERVER_EVENT_END: //解码结束 //建议在解码结束时加上暂停操作,避免出现死锁问题
union audio_req r = {0}; r.dec.cmd = AUDIO_DEC_PAUSE;
server_request(dec_server, AUDIO_REQ_DEC, &r);
break;
case AUDIO_SERVER_EVENT_CURR_TIME: //当前播放时间
log_d("play_time: %d\n", argv[1]);
break;
}
}
server_register_event_handler(dec_server, priv, dec_server_event_handler);//注册解码服务事件回调
通常将解码服务事件回调注册到app_core中接收队列消息server_register_event_handler_to_task(dec_server, priv, dec_server_event_handler,”app_core”); 也可以注册到创建的线程中,可参考: virtual_enc虚拟源编码 中注册编码服务事件回调函数的方式
3.解码请求参数解析
struct audio_dec_req {
u8 cmd; /*!< 请求操作类型 */
u8 status; /*!< 请求后返回的解码状态 */
u8 channel; /*!< 解码通道数 */
u8 volume; /*!< 解码音量(0-100) */
u8 priority; /*!< 解码优先级,暂时没用到 */
u8 speedV; /*!< >80是变快,<80是变慢,建议范围:30到130 */
u16 pitchV; /*!< >32768是音调变高,<32768音调变低,建议范围20000到50000 */
u16 attr; /*!< 解码附加属性 */
u8 digital_gain_mul; /*!< 数字增益乘值 */
u8 digital_gain_div; /*!< 数字增益除值 */
u32 output_buf_len; /*!< 解码buffer大小 */
u32 orig_sr; /*!< 原始采样率,当使能强制变采样时才使用 */
u32 force_sr; /*!< 强制变采样的目标采样率,当使能强制变采样时才使用 */
u32 sample_rate; /*!< 实际的解码采样率 */
u32 ff_fr_step; /*!< 快进快退级数 */
u32 total_time; /*!< 解码的总共时长 */
u32 play_time; /*!< 断点恢复时的当前播放时间 */
void *output_buf; /*!< 解码缓存buffer,默认填NULL,由解码器自己实现分配和释放 */
FILE *file; /*!< 需要解码的文件句柄 */
const char *dec_type; /*!< 解码格式 */
const char *sample_source; /*!< 播放源,支持"dac","iis0","iis1" */
struct audio_dec_breakpoint *bp; /*!< 断点播放信息句柄 */
const struct audio_vfs_ops *vfs_ops; /*!< 虚拟文件操作句柄 */
void *eq_attr; /*!< eq属性设置 */
void *eq_hdl; /*!< 预先申请好的的eq句柄 */
struct audio_cbuf_t *virtual_audio; /*!< 虚拟解码句柄,供外部读写使用 */
int (*dec_callback)(u8 *buf, u32 len, u32 sample_rate, u8 ch_num); /*!< 解码后的PCM数据回调 */
int (*dec_sync)(void *priv, u32 data_size, u16 *in_rate, u16 *out_rate); /*!< 解码对端采样率同步,常用于蓝牙解码 */
};
3.1 cmd
完整的解码命令使用流程应该是AUDIO_DEC_OPEN->AUDIO_DEC_START->AUDIO_DEC_PAUSE- >AUDIO_DEC_STOP,每一次解码结束后一定要主动调用AUDIO_DEC_STOP释放当前的解码资源,才能再次调 用AUDIO_DEC_OPEN,其他指令除了AUDIO_DEC_GET_STATUS外,使用提前是已经调用AUDIO_DEC_OPEN。
#define AUDIO_DEC_OPEN 0 //打开解码
#define AUDIO_DEC_START 1 //开始解码
#define AUDIO_DEC_PAUSE 2 //暂停解码
#define AUDIO_DEC_STOP 3 //停止解码
#define AUDIO_DEC_FF 4 //快进
#define AUDIO_DEC_FR 5 //快退
#define AUDIO_DEC_GET_BREAKPOINT 6 //获取断点数据
#define AUDIO_DEC_PP 7 //暂停/播放
#define AUDIO_DEC_SET_VOLUME 8 //设置解码音量值
#define AUDIO_DEC_DIGITAL_MUTE_SET 9 //设置当前解码的MUTE状态
#define AUDIO_DEC_PS_PARM_SET 10 //设置变速变调的参数
#define AUDIO_DEC_GET_STATUS 11 //获取当前的解码器状态
#define AUDIO_DEC_AB_REPEAT_SET 12 //设置AB点复读播放
#define AUDIO_DEC_AB_REPEAT_CLOSE 13 //关闭AB点复读播放
- 3.2 status
返回当前的解码状态
#define AUDIO_DEC_OPEN 0 //解码已打开
#define AUDIO_DEC_START 1 //解码已开始
#define AUDIO_DEC_PAUSE 2 //解码已暂停
#define AUDIO_DEC_STOP 3 //解码已停止
- 3.3 channel
解码通道数 0: 从解码器的格式检查中自动获取 1:单通道 2:双通道
- 3.4 volume
音量取值范围为0-100,使用命令->AUDIO_DEC_OPEN或AUDIO_DEC_SET_VOLUME
3.5 attr
AUDIO_ATTR_REAL_TIME = BIT(0), //保证解码的实时性,解码读数不能堵塞,仅限于蓝牙播歌时时钟同步使用
AUDIO_ATTR_LR_SUB = BIT(1), //伴奏功能,只支持双声道
AUDIO_ATTR_PS_EN = BIT(2), //变速变声功能开关
AUDIO_ATTR_LR_ADD = BIT(3), //左右通道数据叠加
AUDIO_ATTR_DECRYPT_DEC = BIT(4), //文件解密播放,需要配合对应的加密工具
AUDIO_ATTR_FADE_INOUT = BIT(5), //模拟音量淡入淡出,解码开始和暂停时使用
AUDIO_ATTR_EQ_EN = BIT(6), //EQ功能开关
AUDIO_ATTR_DRC_EN = BIT(7), //DRC功能开关,使能时需要打开EQ功能
AUDIO_ATTR_EQ32BIT_EN = BIT(8), //EQ 32bit输出
AUDIO_ATTR_BT_AAC_EN = BIT(9), //蓝牙AAC解码
AUDIO_ATTR_DEC_MUTE_EN = BIT(10),//当前解码输出mute使能
- 3.6 effect
解码输出后的音效处理
- 3.7 output_buf_len和output_buf
output_buf_len必须填非0值,output_buf默认填NULL,由解码器自己实现分配和释放资源,使用命令->AUDIO_DEC_OPEN
- 3.8 orig_sr、force_sr和sample_rate
orig_sr和force_sr为非0值时,启用强制变采样解码,orig_sr为原始采样率,force_sr为变采样后的采样率,目前仅用于叠音功能上,使用命令->AUDIO_DEC_OPEN
- 3.9 total_time和play_time
当请求打开解码后,该参数保存当前解码的播放总时长和断点恢复时的当前播放时间,一般是从解码器的格式检查中获取,使用命令->AUDIO_DEC_OPEN
- 3.10 vfs_ops和file
当vfs_ops为空时,默认为解码文件操作,此时file不能为空,file需要赋值为fopen操作成功后返回的文件句柄,当解码结束后用户自己需要调用fclose关闭文件。
当vfs_ops非空时,解码器的解码数据源读取操作都通过该虚拟文件操作句柄获取,此时file参数可传入用户的私有数据指针,具体例子如下代码的net_audio_dec_vfs_ops。
当有使用到jltar打包文件时,需要播放打包中文件,可参考apps/demo/demo_audio/demo/local_music.c中vfs_sd_test部分例子中进行参考使用vfs_ops
static const struct audio_vfs_ops net_audio_dec_vfs_ops
{
.fread = net_download_read,
.fseek = net_download_seek,
.flen = net_download_get_file_len,
};
- 3.11 dec_type
当前解码格式支持mp2、mp3、m4a、ape、flac、wav、amr、pcm、adpcm、wma、aac、spx、sbc、cvsd、msbc、opus、dts,使用命令->AUDIO_DEC_OPEN
- 3.12 sample_source
播放源默认为”dac”,还支持”IIS0”和”IIS1”硬件输出,使用命令->AUDIO_DEC_OPEN
- 3.13 bp
使用命令->AUDIO_DEC_OPEN,bp非空时作用是恢复该断点播放。
使用命令->AUDIO_DEC_GET_BREAKPOINT,bp保存下当前解码的断点数据,获取后的bp->data需要用户自行释放内存
- 3.14 eq_attr和eq_hdl
eq_attr为空时,启用eq功能,用户需要配置好合适的eq参数,请求后eq_hdl返回唯一的eq句柄,所有解码器都是共用同一个eq句柄,使用命令->AUDIO_DEC_OPEN
注意:这两个函数仅限于AC790X旧EQ工具使用,新EQ工具无效
- 3.15 pitchV和speedV
变速变调参数设置,使用命令->AUDIO_DEC_OPEN和AUDIO_DEC_PS_PARM_SET
- 3.16 ff_fr_step
设置快进快退时的秒数,使用命令->AUDIO_DEC_FF或者AUDIO_DEC_FR
4.关闭编码服务
server_close(dec_server);
9.8.2. 常见问题
- 打印[Info]: [SERVER_CORE]server_event_handler wait_send_event: app_core, 这是啥原因造成的?
- 这是消息事件推送不出去的打印, 导致这个情况的原因大概率是由于app_core这个线程中做了一些延时的操作导致这个线程卡住, 没有及时获取最新的事件, 事件池占满。解决方法是不能在app_core这个线程中做延时或其他能够让这个线程卡住的操作。
9.8.3. API参考
音频编解码请求操作类型
-
AUDIO_REQ_DEC
解码请求
-
AUDIO_REQ_ENC
编码请求
-
AUDIO_REQ_IOCTL
命令控制
-
AUDIO_DEC_OPEN
打开解码
-
AUDIO_DEC_START
开始解码
-
AUDIO_DEC_PAUSE
暂停解码
-
AUDIO_DEC_STOP
停止解码
-
AUDIO_DEC_FF
快进
-
AUDIO_DEC_FR
快退
-
AUDIO_DEC_GET_BREAKPOINT
获取断点数据
-
AUDIO_DEC_PP
暂停/播放
-
AUDIO_DEC_SET_VOLUME
设置解码音量
-
AUDIO_DEC_DIGITAL_MUTE_SET
设置当前解码的MUTE状态
-
AUDIO_DEC_PS_PARM_SET
设置变速变调的参数
-
AUDIO_DEC_GET_STATUS
获取当前解码器状态
-
AUDIO_DEC_AB_REPEAT_SET
设置AB点复读播放
-
AUDIO_DEC_AB_REPEAT_CLOSE
关闭AB点复读播放
-
AUDIO_DEC_GET_EFFECT_HANDLE
获取对应音效算法的句柄
-
AUDIO_DEC_REPEAT_SET
设置循环播放
-
AUDIO_ENC_OPEN
打开编码
-
AUDIO_ENC_START
开始编码
-
AUDIO_ENC_PAUSE
暂停编码
-
AUDIO_ENC_STOP
停止编码
-
AUDIO_ENC_CLOSE
关闭解码
-
AUDIO_ENC_SET_VOLUME
设置编码模拟增益
-
AUDIO_ENC_GET_STATUS
获取当前编码器状态
-
AUDIO_ENC_PP
暂停/编码
-
enum [anonymous]
AB点复读设置状态
Values:
-
enumerator AB_REPEAT_STA_NON
未设置AB点
-
enumerator AB_REPEAT_STA_ASTA
已设置A点
-
enumerator AB_REPEAT_STA_BSTA
已设置B点
-
enumerator AB_REPEAT_STA_NON
-
enum [anonymous]
AB点复读模式
Values:
-
enumerator AB_REPEAT_MODE_BP_A
设置A点参数
-
enumerator AB_REPEAT_MODE_BP_B
设置B点参数
-
enumerator AB_REPEAT_MODE_CUR
设置取消AB点参数
-
enumerator AB_REPEAT_MODE_BP_A
-
enum [anonymous]
解码器控制命令
Values:
-
enumerator AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A
设置复读A点
-
enumerator AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B
设置复读B点
-
enumerator AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE
设置AB点取消复读模式
-
enumerator AUDIO_IOCTRL_CMD_REPEAT_PLAY
设置循环播放
-
enumerator AUDIO_IOCTRL_CMD_SET_DEC_SR
设置采样率或者码率
-
enumerator AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS
设置指定位置播放
-
enumerator AUDIO_IOCTRL_CMD_GET_PLAYPOS
获取毫秒级时间
-
enumerator AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A
Enums
-
enum [anonymous]
enum AUDIO_SERVER事件回调
Values:
-
enumerator AUDIO_SERVER_EVENT_CURR_TIME
AUDIO_SERVER编/解码当前时间
-
enumerator AUDIO_SERVER_EVENT_END
AUDIO_SERVER编/解码结束
-
enumerator AUDIO_SERVER_EVENT_ERR
AUDIO_SERVER编/解码错误
-
enumerator AUDIO_SERVER_EVENT_SPEAK_START
VAD检测到开始说话
-
enumerator AUDIO_SERVER_EVENT_SPEAK_STOP
VAD检测到停止说话
-
enumerator AUDIO_SERVER_EVENT_CURR_TIME
-
enum [anonymous]
解码附加属性
Values:
-
enumerator AUDIO_ATTR_REAL_TIME
保证解码的实时性,解码读数不能堵塞,仅限于蓝牙播歌时时钟同步使用
-
enumerator AUDIO_ATTR_LR_SUB
伴奏功能,只支持双声道
-
enumerator AUDIO_ATTR_PS_EN
变速变声功能开关
-
enumerator AUDIO_ATTR_LR_ADD
解码器左右通道数据叠加
-
enumerator AUDIO_ATTR_DECRYPT_DEC
文件解密播放,需要配合对应的加密工具
-
enumerator AUDIO_ATTR_FADE_INOUT
模拟音量淡入淡出,解码开始和暂停时使用
-
enumerator AUDIO_ATTR_EQ_EN
EQ功能开关
-
enumerator AUDIO_ATTR_DRC_EN
DRC功能开关,使能时需要打开EQ功能
-
enumerator AUDIO_ATTR_EQ32BIT_EN
EQ 32bit输出
-
enumerator AUDIO_ATTR_BT_AAC_EN
蓝牙AAC解码
-
enumerator AUDIO_ATTR_DEC_MUTE_EN
当前解码输出mute使能
-
enumerator AUDIO_ATTR_UNLIMITED_REPEAT
当前解码无限循环播放使能
-
enumerator AUDIO_ATTR_DEC_SOLO
当前解码强制不走叠音流程
-
enumerator AUDIO_ATTR_REAL_TIME
-
struct audio_cbuf_t
- #include <audio_server.h>
解码虚拟输出时的cbuf读写参数结构体
-
struct audio_dec_breakpoint
- #include <audio_server.h>
解码断点播放信息结构体
-
struct audio_finfo
- #include <audio_server.h>
获取audio解码器信息
-
struct audio_ioctl
- #include <audio_server.h>
audio命令控制
-
struct audio_dest_time_play_param
- #include <audio_server.h>
指定位置播放参数
-
struct audio_vfs_ops
- #include <audio_server.h>
音频虚拟文件操作句柄
Public Members
-
void *(*fopen)(const char *path, const char *mode)
打开创建路径文件
-
int (*fread)(void *file, void *buf, u32 len)
读文件
-
int (*fwrite)(void *file, void *buf, u32 len)
写文件
-
int (*fseek)(void *file, u32 offset, int seek_mode)
寻址文件
-
int (*ftell)(void *file)
返回给定流stream的当前文件位置
-
int (*flen)(void *file)
获取文件长度
-
int (*fclose)(void *file)
关闭文件
-
void *(*fopen)(const char *path, const char *mode)
-
struct audio_repeat_mode_param
-
struct audio_dec_req
- #include <audio_server.h>
解码请求参数
Public Members
-
u8 cmd
请求操作类型
-
u8 status
请求后返回的解码状态
-
u8 channel
解码通道数
-
u8 volume
解码音量(0-100)
-
u8 priority
解码优先级,暂时没用到
-
u8 speedV
>80是变快,<80是变慢,建议范围:30到130
-
u16 repeat_num
循环播放次数
-
u16 pitchV
>32768是音调变高,<32768音调变低,建议范围20000到50000
-
u16 attr
解码附加属性
-
u16 effect
音效附加属性
-
u32 output_buf_len
解码buffer大小
-
u32 orig_sr
强制变采样前的原始采样率,当混响使能强制变采样时才使用
-
u32 force_sr
强制变采样的目标采样率
-
u32 sample_rate
实际的解码采样率
-
u32 ff_fr_step
快进快退级数
-
u32 total_time
解码的总共时长
-
u32 play_time
断点恢复时的当前播放时间
-
void *output_buf
解码缓存buffer,默认填NULL,由解码器自己实现分配和释放
-
const char *dec_type
解码格式
-
const char *sample_source
播放源,支持”dac”,”iis0”,”iis1”
-
struct audio_dec_breakpoint *bp
断点播放信息句柄
-
const struct audio_vfs_ops *vfs_ops
虚拟文件操作句柄
-
void *eq_attr
eq属性设置
-
void *eq_hdl
预先申请好的的eq句柄
-
struct audio_cbuf_t *virtual_audio
虚拟解码句柄,供外部读写使用
-
int (*dec_callback)(u8 *buf, u32 len, u32 sample_rate, u8 ch_num)
解码后的PCM数据回调
-
int (*dec_sync)(void *priv, u32 data_size, u16 *in_rate, u16 *out_rate)
解码对端采样率同步,常用于蓝牙解码
-
void *get_hdl
获取私有句柄
-
u8 cmd
-
struct audio_enc_req
- #include <audio_server.h>
编码请求参数
Public Members
-
u8 cmd
请求操作类型
-
u8 status
编码器状态
-
u8 channel
同时编码的通道数
-
u8 channel_bit_map
ADC通道选择
-
u8 volume
ADC增益(0-100),编码过程中可以通过AUDIO_ENC_SET_VOLUME动态调整增益
-
u8 priority
编码优先级,暂时没用到
-
u8 use_vad
0:关闭vad功能 1:使用旧vad算法 2:使用JL新vad算法
-
u8 vad_auto_refresh
是否自动刷新VAD状态,赋值1表示SPEAK_START->SPEAK_STOP- >SPEAK_START->SPEAK_STOP->….循环
-
u8 direct2dac
AUDIO_AD直通DAC功能
-
u8 high_gain
直通DAC时是否打开模拟增益调整
-
u8 amr_src
amr编码时的强制16k变采样为8kpcm数据,因为amr编码器暂时只支持8k编码
-
u8 aec_enable
AEC回声消除功能开关,常用于蓝牙通话
-
u8 ch_data_exchange
用于AEC差分回采时和MIC的通道数据交换
-
u8 no_header
用于opus编码时是否需要添加头部格式
-
u8 vir_data_wait
虚拟编码时是否允许丢失数据
-
u8 no_auto_start
请求AUDIO_ENC_OPEN时不自动运行编码器,需要主动调用AUDIO_ENC_START
-
u8 sample_depth
采样深度16bit或者24bit
-
u8 dns_enable
dns降噪算法 0:不使用 1:使用
-
u8 wait_sem
编码器数据输出时如果缓存已满即等待信号量
-
u16 vad_start_threshold
VAD连续检测到声音的阈值,表示开始说话,回调AUDIO_SERVER_EVENT_SPEAK_START,单位ms,填0使用库内默认值
-
u16 vad_stop_threshold
VAD连续检测到静音的阈值, 表示停止说话,回调AUDIO_SERVER_EVENT_SPEAK_STOP,单位ms,填0使用库内默认值
-
u16 frame_size
编码器输出的每一帧帧长大小,只有pcm格式编码时才有效
-
u16 frame_head_reserve_len
编码输出的帧预留头部的大小
-
u32 bitrate
编码码率大小
-
u32 delay_ms
当编码器读写不到数据后的延时等待
-
u32 output_buf_len
编码buffer大小
-
u32 sample_rate
编码采样率
-
u32 msec
编码时长,填0表示一直编码,单位ms,编码结束会回调AUDIO_SERVER_EVENT_END消息
-
u8 *output_buf
编码buffer,默认填NULL,由编码器自动分配和释放资源
-
const char *format
编码格式
-
const char *sample_source
采样源,支持”mic”,”linein”,”plnk0”,”plnk1”,”virtual”,”iis0”,”iis1”,”spdif”
-
const struct audio_vfs_ops *vfs_ops
虚拟文件操作句柄
-
u32 (*read_input)(u8 *buf, u32 len)
用于虚拟采样源”virtual”编码时的数据读取操作读输入buf及其长度
-
void *aec_attr
AEC回声消除算法配置参数
-
u8 cmd
-
union audio_req
- #include <audio_server.h>
audio服务请求参数
Public Members
-
struct audio_dec_req dec
解码请求
-
struct audio_enc_req enc
编码请求
-
struct audio_ioctl ioctl
命令控制
-
struct audio_finfo info
音频信息
-
struct audio_dec_req dec