388 lines
20 KiB
C
388 lines
20 KiB
C
#ifndef AUDIO_SERVER_H
|
||
#define AUDIO_SERVER_H
|
||
|
||
#include "fs/fs.h"
|
||
#include "server/audio_dev.h"
|
||
|
||
/**
|
||
* @brief enum AUDIO_SERVER事件回调
|
||
*/
|
||
enum {
|
||
AUDIO_SERVER_EVENT_CURR_TIME = 0x20, /*!< AUDIO_SERVER编/解码当前时间 */
|
||
AUDIO_SERVER_EVENT_END, /*!< AUDIO_SERVER编/解码结束 */
|
||
AUDIO_SERVER_EVENT_ERR, /*!< AUDIO_SERVER编/解码错误 */
|
||
AUDIO_SERVER_EVENT_SPEAK_START, /*!< VAD检测到开始说话 */
|
||
AUDIO_SERVER_EVENT_SPEAK_STOP, /*!< VAD检测到停止说话 */
|
||
};
|
||
|
||
/**
|
||
* @brief 解码附加属性
|
||
*/
|
||
enum {
|
||
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使能 */
|
||
AUDIO_ATTR_UNLIMITED_REPEAT = BIT(11), /*!< 当前解码无限循环播放使能 */
|
||
AUDIO_ATTR_DEC_SOLO = BIT(12), /*!< 当前解码强制不走叠音流程 */
|
||
AUDIO_ATTR_DIGITAL_FADE_INOUT = BIT(13), /*!< 数字音量淡入淡出,解码开始时使用 */
|
||
AUDIO_ATTR_SDRAM_PROMPT = BIT(14), /*!< 播放存储在sdram的提示音 */
|
||
AUDIO_ATTR_NO_WAIT_READY = BIT(15), /*!< 当前解码开始时不需等待解码数据缓存 */
|
||
};
|
||
|
||
/**
|
||
* @brief 音效附加属性
|
||
*/
|
||
enum {
|
||
AUDIO_EFFECT_SPECTRUM_FFT = BIT(0), /*!< 对音频解码数据进行频谱运算 */
|
||
AUDIO_EFFECT_DIGITAL_VOL = BIT(1), /*!< 对音频解码数据进行数字音量调整 */
|
||
AUDIO_EFFECT_VIRTUAL_BASS = BIT(2), /*!< 对音频解码数据进行虚拟低音 */
|
||
};
|
||
|
||
/**
|
||
* \name 音频编解码请求操作类型
|
||
* \{
|
||
*/
|
||
#define AUDIO_REQ_DEC 0 /*!< 解码请求 */
|
||
#define AUDIO_REQ_ENC 1 /*!< 编码请求 */
|
||
#define AUDIO_REQ_IOCTL 2 /*!< 命令控制 */
|
||
|
||
#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点复读播放 */
|
||
#define AUDIO_DEC_GET_EFFECT_HANDLE 14 /*!< 获取对应音效算法的句柄 */
|
||
#define AUDIO_DEC_REPEAT_SET 15 /*!< 设置循环播放 */
|
||
|
||
#define AUDIO_ENC_OPEN 4 /*!< 打开编码 */
|
||
#define AUDIO_ENC_START 5 /*!< 开始编码 */
|
||
#define AUDIO_ENC_PAUSE 6 /*!< 暂停编码 */
|
||
#define AUDIO_ENC_STOP 7 /*!< 停止编码 */
|
||
#define AUDIO_ENC_CLOSE 8 /*!< 关闭解码 */
|
||
#define AUDIO_ENC_SET_VOLUME 9 /*!< 设置编码模拟增益 */
|
||
#define AUDIO_ENC_GET_STATUS 10 /*!< 获取当前编码器状态 */
|
||
#define AUDIO_ENC_PP 11 /*!< 暂停/编码 */
|
||
/* \} name */
|
||
|
||
/**
|
||
* @brief 解码虚拟输出时的cbuf读写参数结构体
|
||
*/
|
||
struct audio_cbuf_t {
|
||
void *cbuf; /*!< cbuf句柄 */
|
||
void *wr_sem; /*!< 写信号量指针 */
|
||
void *rd_sem; /*!< 读信号量指针 */
|
||
volatile u16 end; /*!< 读写结束 */
|
||
volatile u8 state;/*!< 是否正在解码状态 */
|
||
};
|
||
|
||
/// \cond DO_NOT_DOCUMENT
|
||
/**
|
||
* @brief 数据流解码信息
|
||
*/
|
||
struct stream_codec_info {
|
||
int time; /*!< 时间 */
|
||
int frame_num; /*!< 帧数 */
|
||
u32 frame_len; /*!< 帧长度 */
|
||
int frame_points; /*!< 帧采样点 */
|
||
int sequence_number; /*!< 序列号 */
|
||
u32 sample_rate; /*!< 采样率 */
|
||
u8 channel; /*!< 通道 */
|
||
};
|
||
/// \endcond
|
||
|
||
/**
|
||
* @brief 解码断点播放信息结构体
|
||
*/
|
||
struct audio_dec_breakpoint {
|
||
int len; /*!< buf长度 */
|
||
u32 fptr; /*!< 断点位置偏移量 */
|
||
u8 *data; /*!< 断点数据指针 ape格式断点最大2036字节 */
|
||
};
|
||
|
||
/**
|
||
* @brief 获取audio解码器信息
|
||
*/
|
||
struct audio_finfo {
|
||
u8 channel; /*!< 通道 */
|
||
u8 name_code; /*!< 名称编码 0:ansi, 1:unicode_le, 2:unicode_be */
|
||
int sample_rate; /*!< 采样率 */
|
||
int bit_rate; /*!< 比特率 */
|
||
int total_time; /*!< 总时间 */
|
||
};
|
||
|
||
/**
|
||
* @brief audio命令控制
|
||
*/
|
||
struct audio_ioctl {
|
||
u32 cmd; /*!< 请求操作类型 */
|
||
void *priv; /*!< 传入指针 */
|
||
};
|
||
|
||
/**
|
||
* @brief 指定位置播放参数
|
||
*/
|
||
struct audio_dest_time_play_param {
|
||
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回调中实现对应需要的动作 */
|
||
};
|
||
|
||
/**
|
||
* @brief 音频虚拟文件操作句柄
|
||
*/
|
||
struct audio_vfs_ops {
|
||
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); /*!< 关闭文件 */
|
||
};
|
||
|
||
/// \cond DO_NOT_DOCUMENT
|
||
/**
|
||
* @brief 解码输出句柄
|
||
*/
|
||
struct audio_dec_output_ops {
|
||
void *(*get_buf)(void *priv, u32 *len); /*!< 获取buf空间 */
|
||
void (*put_buf)(void *priv, void *buf, u32 len); /*!< 推送buf空间 */
|
||
const struct audio_vfs_ops *vfs_ops; /*!< 音频虚拟文件操作句柄指针 */
|
||
};
|
||
|
||
/**
|
||
* @brief audio解码句柄
|
||
*/
|
||
struct audio_decoder_ops {
|
||
const char *name;/*!< 解码文件名称 */
|
||
void *(*open)(FILE *file, void *priv,
|
||
const struct audio_dec_output_ops *ops, struct audio_dec_breakpoint *); /*!< 打开文件 */
|
||
void *(*try_open)(FILE *file, void *priv,
|
||
const struct audio_dec_output_ops *ops, struct audio_dec_breakpoint *); /*!< 再次尝试打开 */
|
||
int (*get_audio_info)(void *, struct audio_finfo *info); /*!< 获取音频信息 */
|
||
int (*get_play_time)(void *); /*!< 获取播放时间 */
|
||
int (*fast_forward)(void *, int step_s); /*!< 快进 */
|
||
int (*fast_rewind)(void *, int step_s); /*!< 快退 */
|
||
int (*get_breakpoint)(void *, struct audio_dec_breakpoint *); /*!< 获取断点 */
|
||
int (*start)(void *); /*!< 解码开始 */
|
||
int (*close)(void *); /*!< 解码结束 */
|
||
int (*channel_switch)(void *, u8); /*!< 通道选择 */
|
||
int (*stream_info_scan)(void *, struct stream_codec_info *info, void *data, int len); /*!< 扫描数据流信息 */
|
||
int (*stop)(void *); /*!< 解码停止 */
|
||
int (*ioctl)(void *, u32 cmd, void *parm); /*!< 解码命令控制 */
|
||
};
|
||
/// \endcond
|
||
|
||
/**
|
||
* @brief AB点复读设置状态
|
||
*/
|
||
enum {
|
||
AB_REPEAT_STA_NON = 0x00, /*!< 未设置AB点 */
|
||
AB_REPEAT_STA_ASTA, /*!< 已设置A点 */
|
||
AB_REPEAT_STA_BSTA, /*!< 已设置B点 */
|
||
};
|
||
|
||
/**
|
||
* @brief AB点复读模式
|
||
*/
|
||
enum {
|
||
AB_REPEAT_MODE_BP_A = 0x01, /*!< 设置A点参数 */
|
||
AB_REPEAT_MODE_BP_B, /*!< 设置B点参数 */
|
||
AB_REPEAT_MODE_CUR, /*!< 设置取消AB点参数 */
|
||
};
|
||
|
||
/*
|
||
* @brief 循环播放fifo
|
||
*/
|
||
struct fixphase_repair_obj {
|
||
short fifo_buf[18 + 12][32][2]; /*!< 相位修复buf */
|
||
};
|
||
|
||
/*
|
||
* @brief 循环播放结构体
|
||
*
|
||
* @param 每次播放会根据headcut_frame和tailcut_frame来砍掉一些不需要的帧
|
||
* @param 在repeat_callback()回调中可以自主控制播放次数,返回非0即结束循环
|
||
*/
|
||
struct audio_repeat_mode_param {
|
||
int flag; /*!< 置1使能 */
|
||
int headcut_frame; /*!< 砍掉前面几帧,仅mp3格式有效 */
|
||
int tailcut_frame; /*!< 砍掉后面几帧,仅mp3格式有效 */
|
||
int (*repeat_callback)(void *); /*!< 循环播放回调,返回0-正常循环;返回非0-结束循环 */
|
||
void *callback_priv; /*!< 回调参数指针 */
|
||
struct fixphase_repair_obj *repair_buf; /*!< 相位修复buf指针 */
|
||
};
|
||
|
||
/**
|
||
* @brief 解码器控制命令
|
||
*/
|
||
enum {
|
||
AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A = 0x08, /*!< 设置复读A点 */
|
||
AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, /*!< 设置复读B点 */
|
||
AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, /*!< 设置AB点取消复读模式 */
|
||
|
||
AUDIO_IOCTRL_CMD_REPEAT_PLAY = 0x90, /*!< 设置循环播放 */
|
||
AUDIO_IOCTRL_CMD_SET_DEC_SR = 0x91, /*!< 设置采样率或者码率 */
|
||
AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS = 0x93, /*!< 设置指定位置播放 */
|
||
AUDIO_IOCTRL_CMD_GET_PLAYPOS = 0x94, /*!< 获取毫秒级时间 */
|
||
};
|
||
|
||
/**
|
||
* @brief 解码请求参数
|
||
*/
|
||
struct audio_dec_req {
|
||
u8 cmd; /*!< 请求操作类型 */
|
||
u8 status; /*!< 请求后返回的解码状态 */
|
||
u8 channel; /*!< 解码通道数 */
|
||
u8 volume; /*!< 模拟音量(0-100) */
|
||
u8 digital_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,由解码器自己实现分配和释放 */
|
||
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); /*!< 解码对端采样率同步,常用于蓝牙解码 */
|
||
void *get_hdl; /*!< 获取私有句柄 */
|
||
void *sync_priv; /*!< 解码对端采样率同步私有指针 */
|
||
};
|
||
|
||
/**
|
||
* @brief 编码请求参数
|
||
*/
|
||
struct audio_enc_req {
|
||
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 : 2; /*!< 0:关闭vad功能 1:使用旧vad算法 2:使用JL新vad算法 */
|
||
u8 vad_auto_refresh : 1; /*!< 是否自动刷新VAD状态,赋值1表示SPEAK_START->SPEAK_STOP- >SPEAK_START->SPEAK_STOP->....循环 */
|
||
u8 direct2dac : 1; /*!< AUDIO_AD直通DAC功能 */
|
||
u8 high_gain : 1; /*!< 直通DAC时是否打开模拟增益调整 */
|
||
u8 amr_src : 1; /*!< amr编码时的强制16k变采样为8kpcm数据,因为amr编码器暂时只支持8k编码 */
|
||
u8 aec_enable : 1; /*!< AEC回声消除功能开关,常用于蓝牙通话 */
|
||
u8 ch_data_exchange : 1; /*!< 用于AEC差分回采时和MIC的通道数据交换 */
|
||
|
||
u8 no_header : 1; /*!< 用于opus编码时是否需要添加头部格式 */
|
||
u8 vir_data_wait : 1; /*!< 虚拟编码时是否允许丢失数据 */
|
||
u8 no_auto_start : 1; /*!< 请求AUDIO_ENC_OPEN时不自动运行编码器,需要主动调用AUDIO_ENC_START */
|
||
u8 sample_depth : 3; /*!< 采样深度16bit或者24bit */
|
||
u8 dns_enable : 1; /*!< dns降噪算法 0:不使用 1:使用 */
|
||
u8 wait_sem : 1; /*!< 编码器数据输出时如果缓存已满即等待信号量 */
|
||
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; /*!< 虚拟文件操作句柄 */
|
||
int(*read_input)(u8 *buf, u32 len); /*!< 用于虚拟采样源"virtual"编码时的数据读取操作读输入buf及其长度,返回负值自动停止编码并回调编码结束的事件 */
|
||
void *aec_attr; /*!< AEC回声消除算法配置参数 */
|
||
};
|
||
|
||
/**
|
||
* @brief audio服务请求参数
|
||
*/
|
||
union audio_req {
|
||
struct audio_dec_req dec; /*!< 解码请求 */
|
||
struct audio_enc_req enc; /*!< 编码请求 */
|
||
struct audio_ioctl ioctl; /*!< 命令控制 */
|
||
struct audio_finfo info; /*!< 音频信息 */
|
||
};
|
||
|
||
/// \cond DO_NOT_DOCUMENT
|
||
struct audio_package_ops {
|
||
const char *name; /*!< 文件名称 */
|
||
const char *data_fmt; /*!< 数据格式 */
|
||
void *(*open)(void *file, const struct audio_vfs_ops *, struct audio_enc_req *); /*!< 打开文件编码 */
|
||
int (*start)(void *file, const struct audio_vfs_ops *vfs_ops); /*!< 开始数据包处理 */
|
||
int (*input)(void *file, u8 *data, int len, const struct audio_vfs_ops *vfs_ops); /*!< 输入数据 */
|
||
int (*close)(void *file, const struct audio_vfs_ops *vfs_ops); /*!< 关闭数据处理 */
|
||
};
|
||
|
||
struct audio_effect_ops {
|
||
u16 effect;
|
||
u8 pretreatment;
|
||
void *(*open)(void *priv, void *param);
|
||
int (*run)(void *priv, s16 *data, int len, int sample_rate);
|
||
int (*close)(void *priv);
|
||
};
|
||
|
||
|
||
#define REGISTER_AUDIO_EFFECT(ops) \
|
||
const struct audio_effect_ops ops SEC_USED(.audio_effect)
|
||
|
||
extern const struct audio_effect_ops audio_effect_begin[];
|
||
extern const struct audio_effect_ops audio_effect_end[];
|
||
|
||
#define list_for_each_audio_effect(p) \
|
||
for (p = audio_effect_begin; p < audio_effect_end; p++)
|
||
|
||
|
||
#define REGISTER_AUDIO_DECODER(ops) \
|
||
const struct audio_decoder_ops ops SEC_USED(.audio_decoder)
|
||
|
||
extern const struct audio_decoder_ops audio_decoder_begin[];
|
||
extern const struct audio_decoder_ops audio_decoder_end[];
|
||
|
||
#define list_for_each_audio_decoder(p) \
|
||
for (p = audio_decoder_begin; p < audio_decoder_end; p++)
|
||
|
||
|
||
#define REGISTER_AUDIO_PACKAGE(ops) \
|
||
const struct audio_package_ops ops SEC_USED(.audio_package)
|
||
|
||
extern const struct audio_package_ops audio_package_begin[];
|
||
extern const struct audio_package_ops audio_package_end[];
|
||
|
||
#define list_for_each_audio_package(p) \
|
||
for (p = audio_package_begin; p < audio_package_end; p++)
|
||
/// \endcond
|
||
|
||
#endif
|
||
|