9.8. 音频解码AUDIO_DEC

概述

提供音频解码的使用流程

9.8.1. 使用流程

  • 1.打开解码服务

struct server *enc_server = server_open("audio_server", "dec"); //打开解码服务
    1. 注册解码服务事件回调

注意:服务事件回调是通过任务的队列消息传递的,此消息是不允许丢失的,使用者需要做好相应的异步处理,哪个线程注册该回调函数就是该线程负责接收,特别需要注意不能出现消息队列填满引起的死锁问题,调用的任务需要通过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);//注册解码服务事件回调
  • 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. API参考

音频编解码请求操作类型

AUDIO_REQ_DEC

解码请求

AUDIO_REQ_ENC

编码请求

AUDIO_REQ_GET_INFO

信息获取

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_GAIN_SET

设置当前解码的数字增益

AUDIO_DEC_PS_PARM_SET

设置变速变调的参数

AUDIO_DEC_GET_STATUS

获取当前解码器状态

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]

解码器控制命令

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

获取毫秒级时间

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检测到停止说话

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解码

struct audio_cbuf_t
#include <audio_server.h>

解码虚拟输出时的cbuf读写参数结构体

Public Members

void *cbuf

cbuf句柄

void *wr_sem

写信号量指针

void *rd_sem

读信号量指针

volatile int end

读写结束

struct audio_dec_breakpoint
#include <audio_server.h>

解码断点播放信息结构体

Public Members

int len

buf长度

u32 fptr

断点位置偏移量

u8 *data

断点数据指针 ape格式断点最大2036字节

struct audio_finfo
#include <audio_server.h>

获取audio解码器信息

Public Members

u8 channel

通道

u8 name_code

名称编码 0:ansi, 1:unicode_le, 2:unicode_be

int sample_rate

采样率

int bit_rate

比特率

int total_time

总时间

struct audio_ioctl
#include <audio_server.h>

audio命令控制

Public Members

u32 cmd

请求操作类型

void *priv

传入指针

struct audio_dest_time_play_param
#include <audio_server.h>

指定位置播放参数

Public Members

u32 start_time

要跳转过去播放的起始时间。单位:ms。设置后跳到start_time开始播放

u32 dest_time

要跳转过去播放的目标时间。单位:ms。播放到dest_time后如果callback_func存在,则调用callback_func

u32 (*callback_func)(void *priv)

到达目标时间后回调

void *callback_priv

回调参数,可以在callback_func回调中实现对应需要的动作

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)

关闭文件

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 pitchV

>32768是音调变高,<32768音调变低,建议范围20000到50000

u16 attr

解码附加属性

u8 digital_gain_mul

数字增益乘值

u8 digital_gain_div

数字增益除值

u32 output_buf_len

解码buffer大小

u32 orig_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)

解码对端采样率同步,常用于蓝牙解码

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 reserve

保留位

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消息

FILE *file

编码输出文件句柄

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回声消除算法配置参数

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

音频信息