生成代码包

This commit is contained in:
2026-08-29 11:06:52 +08:00
commit 4cb7418a02
914 changed files with 218983 additions and 0 deletions
+180
View File
@@ -0,0 +1,180 @@
/*
****************************************************************
* Amplitude Statistics
* 幅值统计模块
* File : amplitude_statistic.c
* By :
* Notes :
****************************************************************
*/
#include "amplitude_statistic.h"
#if 0
#define amplitude_log printf
#else
#define amplitude_log(...)
#endif/*log_en*/
static const unsigned short am_va_tab[] = {
32768, 29205, 26029, 23198, 20675, 18427, 16423, 14637, 13045, 11627, 10362, 9235, 8231, 7336, 6538, 5827,
5193, 4629, 4125, 3677, 3277, 2920, 2603, 2320, 2068, 1843, 1642, 1464, 1305, 1163, 1036, 0
};
static const int rms_va_tab[] = {
134217728, 106612931, 84685661, 67268212, 53433040, 42443372, 33713969, 26779957, 21272076, 16897011,
13421773, 10661293, 8468566, 6726821, 5343304, 4244337, 3371397, 2677996, 2127208, 1689701,
1342177, 1066129, 846857, 672682, 534330, 424434, 337140, 267800, 212721, 168970,
134218, 0
};
/*
*********************************************************************
* Loudness meter init
* Description: 响度计算初始化
* Arguments : loud_obj
* sr
* print_dest
* index
* Return : NULL
* Note(s) : NULL
*********************************************************************
*/
void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index)
{
memset(loud_obj, 0, sizeof(LOUDNESS_M_STRUCT));
loud_obj->countperiod = sr / 50;
loud_obj->inv_counterpreiod = 16777216 / loud_obj->countperiod;
loud_obj->print_dest = print_dest;
loud_obj->index = index;
}
/*
*********************************************************************
* Loudness meter short
* Description: 响度计算函数
* Arguments : loud_obj
* data
* len
* Return : NULL
* Note(s) : NULL
*********************************************************************
*/
void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len)
{
int i;
int loudness_val = 0;
for (i = 0; i < len; i++) {
int tmp = data[i] * 256;
loud_obj->dclevel = (loud_obj->dclevel * 511 + tmp) >> 9;
int xabs = (data[i] > 0) ? data[i] : (-data[i]);
int xabs2 = (xabs * xabs) >> 10;
loud_obj->rms += xabs2;
loud_obj->maxval = (loud_obj->maxval > xabs) ? loud_obj->maxval : xabs;
if (xabs >= 32767) {
loud_obj->errprintfcount0++;
}
loud_obj->counti++;
if (loud_obj->counti > loud_obj->countperiod) {
if (loud_obj->maxval_print < loud_obj->maxval) {
loud_obj->maxval_print = loud_obj->maxval;
}
if (loud_obj->rms_print < loud_obj->rms) {
loud_obj->rms_print = loud_obj->rms;
}
loud_obj->counti = 0;
loud_obj->maxval = 0;
loud_obj->rms = 0;
if (loud_obj->errprintfcount0 > 2) {
loud_obj->errprintfcount0 = 0;
amplitude_log("[%d]overflow occur... \n", loud_obj->index);
}
loud_obj->print_cnt++;
if (loud_obj->print_cnt >= loud_obj->print_dest) {
int rmsval = ((__int64)loud_obj->rms_print * (__int64)loud_obj->inv_counterpreiod) >> (24 - (10 - 3));
if (rmsval > 25837266) {
amplitude_log("[%d]energy high... \n", loud_obj->index);
}
{
int compi = 0, found = 0;;
while (compi < 31) {
if (rmsval >= rms_va_tab[compi]) {
// float upval = (0 - compi) * 0.5;
// float dwonval = (0 - compi - 1) * 0.5;
// amplitude_log("rms level: %f to %f dB\n", upval, dwonval);
int upval = (0 - compi);
int dwonval = (0 - compi - 1);
amplitude_log("[%d]rms level: %d to %d dB\n", loud_obj->index, upval, dwonval);
found = 1;
break;
}
compi++;
}
if (found == 0) {
amplitude_log("[%d]rms level < -30dB \n", loud_obj->index);
}
}
{
int compi = 0, found = 0;;
while (compi < 31) {
if (loud_obj->maxval_print >= am_va_tab[compi]) {
// float upval = (0 - compi) * 0.5;
// float dwonval = (0 - compi - 1) * 0.5;
// amplitude_log("peak level: %f to %f dB\n", upval, dwonval);
int upval = (0 - compi);
int dwonval = (0 - compi - 1);
loud_obj->peak_val = dwonval;
amplitude_log("[%d]peak level: %d to %d dB\n", loud_obj->index, upval, dwonval);
found = 1;
break;
}
compi++;
}
if (found == 0) {
loud_obj->peak_val = -31;
amplitude_log("[%d]peak level < -30dB \n", loud_obj->index);
}
}
loud_obj->print_cnt = 0;
loud_obj->maxval_print = 0;
loud_obj->rms_print = 0;
if (loud_obj->dclevel > (255 * 256)) {
amplitude_log("[%d] why ??? dc level : %d \n", loud_obj->index, loud_obj->dclevel >> 8);
}
amplitude_log("\n\n");
}
}
}
}
#if 0
void loudness_meter_demo(void)
{
loudness_meter_init(&loudness_adc, 16000, 1);
loudness_meter_short(&loudness_adc, datain, points);
}
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef _AMPLITUDE_STATISTIC_H_
#define _AMPLITUDE_STATISTIC_H_
#include "generic/typedef.h"
typedef struct _LOUDNESS_M_STRUCT_ {
int mutecnt;
int rms;
int counti;
int maxval;
int countperiod;
int inv_counterpreiod;
int errprintfcount0;
short print_cnt;
short print_dest;
int dclevel;
int rms_print;
int maxval_print;
int peak_val;
u8 index;
} LOUDNESS_M_STRUCT;
void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index);
void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len);
#endif /*_AMPLITUDE_STATISTIC_H_*/
+13
View File
@@ -0,0 +1,13 @@
#ifndef _AUDIO_NOISE_GATE_H_
#define _AUDIO_NOISE_GATE_H_
#include "generic/typedef.h"
u8 *audio_noise_gate_open(int attack_time, int release_time, float thr, float gain, int sr, int ch);
void audio_noise_gate_run(u8 *runbuf, void *in, void *out, u16 len);
void audio_noise_gate_close(u8 *runbuf);
#endif/*_AUDIO_NOISE_GATE_H_*/
+79
View File
@@ -0,0 +1,79 @@
#ifndef _AUDIO_DIGITAL_VOL_H_
#define _AUDIO_DIGITAL_VOL_H_
#include "generic/typedef.h"
#include "os/os_type.h"
#include "os/os_api.h"
#include "generic/list.h"
#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/
typedef struct {
u8 toggle; /*数字音量开关*/
u8 fade; /*淡入淡出标志*/
u8 vol; /*淡入淡出当前音量(level)*/
u8 vol_max; /*淡入淡出最大音量(level)*/
s16 vol_fade; /*淡入淡出对应的起始音量*/
#if BG_DVOL_FADE_ENABLE
s16 vol_bk; /*后台自动淡出前音量值*/
struct list_head entry;
#endif
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
volatile u16 fade_step; /*淡入淡出的步进*/
} dvol_handle;
int audio_digital_vol_init(void);
void audio_digital_vol_bg_fade(u8 fade_out);
dvol_handle *audio_digital_vol_open(u8 vol, u8 vol_max, u16 fade_step);
void audio_digital_vol_close(dvol_handle *dvol);
void audio_digital_vol_set(dvol_handle *dvol, u8 vol);
u8 audio_digital_vol_get(void);
int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len);
void audio_digital_vol_reset_fade(dvol_handle *dvol);
/*************************自定义支持重入的数字音量调节****************************/
void *user_audio_digital_volume_open(u8 vol, u8 vol_max, u16 fade_step);
int user_audio_digital_volume_close(void *_d_volume);
u8 user_audio_digital_volume_get(void *_d_volume);
int user_audio_digital_volume_set(void *_d_volume, u8 vol);
int user_audio_digital_volume_reset_fade(void *_d_volume);
int user_audio_digital_volume_run(void *_d_volume, void *data, u32 len, u8 ch_num);
void user_audio_digital_handler_run(void *_d_volume, void *data, u32 len);
void user_audio_digital_set_volume_tab(void *_d_volume, u16 *user_vol_tab, u8 user_vol_max);
void *user_audio_process_open(void *parm, void *priv, void (*handler)(void *priv, void *data, int len, u8 ch_num));
int user_audio_process_close(void *_uparm_hdl);
void user_audio_process_handler_run(void *_uparm_hdl, void *data, u32 len, u8 ch_num);
struct user_audio_digital_parm {
u8 en;
u8 vol;
u8 vol_max;
u16 fade_step;
};
struct digital_volume {
u8 toggle; /*数字音量开关*/
u8 fade; /*淡入淡出标志*/
u8 vol; /*淡入淡出当前音量*/
u8 vol_max; /*淡入淡出最大音量*/
s16 vol_fade; /*淡入淡出对应的起始音量*/
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
volatile u16 fade_step; /*淡入淡出的步进*/
OS_MUTEX mutex;
u8 ch_num;
void *priv;
u8 user_vol_max; /*自定义音量表级数*/
volatile s16 *user_vol_tab; /*自定义音量表*/
};
struct user_audio_parm {
void *priv;
void (*handler)(void *priv, void *data, int len, u8 ch_num);/*用户自定义回调处理*/
struct digital_volume *dvol_hdl;
};
#endif
+450
View File
@@ -0,0 +1,450 @@
/*
****************************************************************
* AUDIO DIGITAL VOLUME
* File : audio_dvol.c
* By :
* Notes : 数字音量模块,支持多通道音量控制
****************************************************************
*/
#include "audio_dvol.h"
#if 0
#define dvol_log y_printf
#else
#define dvol_log(...)
#endif
#define DIGITAL_FADE_EN 1
#define DIGITAL_FADE_STEP 4
#define BG_DVOL_MAX 14
#define BG_DVOL_MID 10
#define BG_DVOL_MIN 6
#define BG_DVOL_MAX_FADE 13 /*>= BG_DVOL_MAX:自动淡出BG_DVOL_MAX_FADE*/
#define BG_DVOL_MID_FADE 9 /*>= BG_DVOL_MID:自动淡出BG_DVOL_MID_FADE*/
#define BG_DVOL_MIN_FADE 5 /*>= BG_DVOL_MIN:自动淡出BG_DVOL_MIN_FADE*/
#define ASM_ENABLE 1
#define L_sat(b,a) __asm__ volatile("%0=sat16(%1)(s)":"=&r"(b) : "r"(a));
#define L_sat32(b,a,n) __asm__ volatile("%0=%1>>%2(s)":"=&r"(b) : "r"(a),"r"(n));
typedef struct {
u8 bg_dvol_fade_out;
u8 start;
OS_MUTEX mutex;
struct list_head dvol_head;
} dvol_t;
static dvol_t dvol_attr;
/*
*数字音量级数 DEFAULT_DIGITAL_VOL_MAX
*数组长度 DEFAULT_DIGITAL_VOL_MAX + 1
*/
#define DEFAULT_DIGITAL_VOL_MAX (31)
const u16 default_dig_vol_table[DEFAULT_DIGITAL_VOL_MAX + 1] = {
0 , //0
93 , //1
111 , //2
132 , //3
158 , //4
189 , //5
226 , //6
270 , //7
323 , //8
386 , //9
462 , //10
552 , //11
660 , //12
789 , //13
943 , //14
1127, //15
1347, //16
1610, //17
1925, //18
2301, //19
2751, //20
3288, //21
3930, //22
4698, //23
5616, //24
6713, //25
8025, //26
9592, //27
11466,//28
15200,//29
16000,//30
16384 //31
};
static u16 digital_vol_max = DEFAULT_DIGITAL_VOL_MAX;
static u16 *dig_vol_table = default_dig_vol_table;
/*
*********************************************************************
* Audio Digital Volume Init
* Description: 数字音量模块初始化
* Arguments : None.
* Return : 0 成功 其他 失败
* Note(s) : None.
*********************************************************************
*/
int audio_digital_vol_init(u16 *vol_table, u16 vol_max)
{
memset(&dvol_attr, 0, sizeof(dvol_attr));
INIT_LIST_HEAD(&dvol_attr.dvol_head);
os_mutex_create(&dvol_attr.mutex);
if (vol_table != NULL) {
dig_vol_table = vol_table;
digital_vol_max = vol_max;
}
return 0;
}
/*背景音乐淡出使能*/
void audio_digital_vol_bg_fade(u8 fade_out)
{
dvol_log("audio_digital_vol_bg_fade:%d", fade_out);
dvol_attr.bg_dvol_fade_out = fade_out;
}
/*
*********************************************************************
* Audio Digital Volume Open
* Description: 数字音量模块打开
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
* vol 当前数字音量等级
* vol_max 最大数字音量等级
* fade_step 淡入淡出步进
* vol_limit 数字音量限制,即可以给vol_max等分的最大音量
* Return : 数字音量通道句柄
* Note(s) : fade_step一般不超过两级数字音量的最小差值
* (1)通话如果用数字音量,一般步进小一点,音量调节的时候不会有杂音
* (2)淡出的时候可以快一点,尽快淡出到0
*********************************************************************
*/
dvol_handle *audio_digital_vol_open(u8 dvol_idx, u8 vol, u8 vol_max, u16 fade_step, char vol_limit)
{
dvol_log("dvol_open:%d-%d-%d-%d\n", vol, vol_max, fade_step, vol_limit);
dvol_handle *dvol = NULL;
dvol = zalloc(sizeof(dvol_handle));
if (dvol) {
u8 vol_level;
dvol->fade = DIGITAL_FADE_EN;
dvol->vol = (vol > vol_max) ? vol_max : vol;
if (vol > vol_max) {
printf("[warning]cur digital_vol(%d) > digital_vol_max(%d)!!", vol, vol_max);
}
dvol->vol_max = vol_max;
if (vol_limit == -1) {
dvol->vol_limit = digital_vol_max;
} else {
dvol->vol_limit = (vol_limit > digital_vol_max) ? digital_vol_max : vol_limit;
}
vol_level = dvol->vol * dvol->vol_limit / vol_max;
dvol->vol_target = dig_vol_table[vol_level];
dvol->vol_fade = dvol->vol_target;
dvol->fade_step = fade_step;
dvol->toggle = 1;
dvol->idx = dvol_idx;
local_irq_disable();
list_add(&dvol->entry, &dvol_attr.dvol_head);
#if BG_DVOL_FADE_ENABLE
dvol->vol_bk = -1;
if (dvol_attr.bg_dvol_fade_out) {
dvol_handle *hdl;
list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) {
if ((hdl != dvol) && (hdl->idx)) {
hdl->vol_bk = hdl->vol;
if (hdl->vol >= BG_DVOL_MAX) {
hdl->vol -= BG_DVOL_MAX_FADE;
} else if (hdl->vol >= BG_DVOL_MID) {
hdl->vol -= BG_DVOL_MID_FADE;
} else if (hdl->vol >= BG_DVOL_MIN) {
hdl->vol -= BG_DVOL_MIN_FADE;
} else {
hdl->vol_bk = -1;
continue;
}
u8 vol_level = hdl->vol * dvol->vol_limit / hdl->vol_max;
hdl->vol_target = dig_vol_table[vol_level];
//y_printf("bg_dvol fade_out:%x,vol_bk:%d,vol_set:%d,tartget:%d",hdl,hdl->vol_bk,hdl->vol,hdl->vol_target);
}
}
}
#endif/*BG_DVOL_FADE_ENABLE*/
local_irq_enable();
dvol_log("dvol_open[%x]:%x-%d-%d-%d\n", dvol_idx, dvol, dvol->vol, dvol->vol_max, fade_step);
}
return dvol;
}
/*
*********************************************************************
* Audio Digital Volume Close
* Description: 数字音量模块关闭
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_digital_vol_close(u8 dvol_idx)
{
dvol_log("dvol_close[%x]\n", dvol_idx);
dvol_handle *dvol = NULL;
u8 dvol_valid = 0;
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
if (dvol && (dvol->idx == dvol_idx)) {
dvol_log("dvol_close[%x]:%x", dvol_idx, dvol);
dvol_valid = 1;
break;
}
}
if (dvol_valid == 0) {
return;
}
if (dvol) {
local_irq_disable();
#if BG_DVOL_FADE_ENABLE
dvol_handle *hdl;
list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) {
if ((hdl != dvol) && (hdl->vol_bk >= 0)) {
//y_printf("bg_dvol fade_in:%x,%d",hdl,hdl->vol_bk);
hdl->vol = hdl->vol_bk;
u8 vol_level = hdl->vol_bk * dvol->vol_limit / hdl->vol_max;
hdl->vol_target = dig_vol_table[vol_level];
hdl->vol_bk = -1;
}
}
#endif
list_del(&dvol->entry);
free(dvol);
dvol = NULL;
local_irq_enable();
}
}
/*
*********************************************************************
* Audio Digital Volume Get
* Description: 数字音量获取
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
* Return : 对应的数字音量通道的当前音量等级.
* Note(s) : None.
*********************************************************************
*/
int audio_digital_vol_get(u8 dvol_idx)
{
dvol_handle *dvol = NULL;
u8 dvol_valid = 0;
local_irq_disable();
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
if (dvol && (dvol->idx == dvol_idx)) {
dvol_valid = 1;
break;
}
}
local_irq_enable();
if (dvol && dvol_valid) {
return dvol->vol;
}
return 0;
}
/*
*********************************************************************
* Audio Digital Volume Set
* Description: 数字音量设置
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
* vol 目标音量等级
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_digital_vol_set(u8 dvol_idx, u8 vol)
{
dvol_log("audio_digital_vol set:%d,%d\n", dvol_idx, vol);
dvol_handle *dvol = NULL;
u8 dvol_valid = 0;
local_irq_disable();
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
if (dvol && (dvol->idx == dvol_idx)) {
dvol_log("dvol_set[%x]:%x", dvol_idx, dvol);
dvol_valid = 1;
break;
}
}
local_irq_enable();
if ((dvol == NULL) || (dvol_valid == 0)) {
return;
}
if (dvol->toggle == 0) {
return;
}
dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol;
#if BG_DVOL_FADE_ENABLE
if (dvol->vol_bk != -1) {
dvol->vol_bk = vol;
}
#endif
dvol->fade = DIGITAL_FADE_EN;
u8 vol_level = dvol->vol * dvol->vol_limit / dvol->vol_max;
dvol->vol_target = dig_vol_table[vol_level];
dvol_log("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target);
}
/*********************************************************************
* Audio Digital Volume Set
* Description: 数字音量设置,设置数字音量的当前值,不用淡入淡出
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
* vol 目标音量等级
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_digital_vol_set_no_fade(u8 dvol_idx, u8 vol)
{
dvol_log("audio_digital_vol set:%d,%d\n", dvol_idx, vol);
dvol_handle *dvol = NULL;
u8 dvol_valid = 0;
local_irq_disable();
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
if (dvol && (dvol->idx == dvol_idx)) {
dvol_log("dvol_set[%x]:%x", dvol_idx, dvol);
dvol_valid = 1;
break;
}
}
local_irq_enable();
if ((dvol == NULL) || (dvol_valid == 0)) {
return;
}
if (dvol->toggle == 0) {
return;
}
dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol;
#if BG_DVOL_FADE_ENABLE
if (dvol->vol_bk != -1) {
dvol->vol_bk = vol;
}
#endif
dvol->fade = DIGITAL_FADE_EN;
u8 vol_level = dvol->vol * dvol->vol_limit / dvol->vol_max;
dvol->vol_fade = dig_vol_table[vol_level];
dvol_log("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target);
}
void audio_digital_vol_reset_fade(u8 dvol_idx)
{
dvol_handle *dvol = NULL;
u8 dvol_valid = 0;
local_irq_disable();
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
if (dvol && (dvol->idx == dvol_idx)) {
dvol_valid = 1;
break;
}
}
local_irq_enable();
if (dvol && dvol_valid) {
dvol->vol_fade = 0;
}
}
/*
*********************************************************************
* Audio Digital Volume Process
* Description: 数字音量运算核心
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
* data 待运算数据
* len 待运算数据长度
* Return : 0 成功 其他 失败
* Note(s) : None.
*********************************************************************
*/
/*rounding处理*/
#define MUL32_PSHIFT(x,y,s) (((x) * (y) + (1 << ((s)-1))) >> (s))
int audio_digital_vol_run(u8 dvol_idx, void *data, u32 len)
{
s32 valuetemp;
s16 *buf;
os_mutex_pend(&dvol_attr.mutex, 0);
dvol_handle *dvol = NULL;
u8 dvol_valid = 0;
local_irq_disable();
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
if (dvol && (dvol->idx == dvol_idx)) {
dvol_valid = 1;
#if 0
static dvol_handle *last_dvol = NULL;
if (last_dvol != dvol) {
dvol_log("dvol_run[%x]:%x", dvol_idx, dvol);
last_dvol = dvol;
}
#endif
break;
}
}
local_irq_enable();
if ((dvol->toggle == 0) || (dvol_valid == 0)) {
os_mutex_post(&dvol_attr.mutex);
return -1;
}
buf = data;
len >>= 1; //byte to point
for (u32 i = 0; i < len; i += 2) {
///left channel
if (dvol->fade) {
if (dvol->vol_fade > dvol->vol_target) {
dvol->vol_fade -= dvol->fade_step;
if (dvol->vol_fade < dvol->vol_target) {
dvol->vol_fade = dvol->vol_target;
}
} else if (dvol->vol_fade < dvol->vol_target) {
dvol->vol_fade += dvol->fade_step;
if (dvol->vol_fade > dvol->vol_target) {
dvol->vol_fade = dvol->vol_target;
}
}
} else {
dvol->vol_fade = dvol->vol_target;
}
valuetemp = buf[i];
if (valuetemp < 0) {
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
valuetemp = -valuetemp;
/*rounding处理(加入0.5),减少小信号时候的误差和谐波幅值*/
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
valuetemp = -valuetemp;
} else {
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
}
/*饱和处理*/
buf[i] = (s16)data_sat_s16(valuetemp);
///right channel
valuetemp = buf[i + 1];
if (valuetemp < 0) {
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
valuetemp = -valuetemp;
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
valuetemp = -valuetemp;
} else {
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
}
/*饱和处理*/
buf[i + 1] = (s16)data_sat_s16(valuetemp);
}
os_mutex_post(&dvol_attr.mutex);
return 0;
}
+55
View File
@@ -0,0 +1,55 @@
#ifndef _AUDIO_DVOL_H_
#define _AUDIO_DVOL_H_
#include "generic/typedef.h"
#include "os/os_type.h"
#include "os/os_api.h"
#include "generic/list.h"
#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/
/*Digital Volume Channel*/
#define MUSIC_DVOL 0xA1
#define CALL_DVOL 0xA2
#define TONE_DVOL 0xA3
#define HEARING_DVOL 0xA4
/*Digital Volume Fade Step*/
#define MUSIC_DVOL_FS 2
#define CALL_DVOL_FS 4
#define TONE_DVOL_FS 30
#define HEARING_DVOL_FS 2
/*Digital Volume Max Level*/
#define MUSIC_DVOL_MAX 16
#define CALL_DVOL_MAX 15
#define TONE_DVOL_MAX 16
#define HEARING_DVOL_MAX 16
typedef struct {
u8 toggle; /*数字音量开关*/
u8 fade; /*淡入淡出标志*/
u8 vol; /*淡入淡出当前音量(level)*/
u8 vol_max; /*淡入淡出最大音量(level)*/
char vol_limit; /*最大数字音量限制*/
u8 idx; /*数字音量通道索引*/
s16 vol_fade; /*淡入淡出对应的起始音量*/
#if BG_DVOL_FADE_ENABLE
s16 vol_bk; /*后台自动淡出前音量值*/
#endif/*BG_DVOL_FADE_ENABLE*/
struct list_head entry;
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
volatile u16 fade_step; /*淡入淡出的步进*/
} dvol_handle;
int audio_digital_vol_init(u16 *vol_table, u16 vol_max);
void audio_digital_vol_bg_fade(u8 fade_out);
dvol_handle *audio_digital_vol_open(u8 dvol_idx, u8 vol, u8 vol_max, u16 fade_step, char vol_limit);
void audio_digital_vol_close(u8 dvol_idx);
void audio_digital_vol_set(u8 dvol_idx, u8 vol);
int audio_digital_vol_get(u8 dvol_idx);
int audio_digital_vol_run(u8 dvol_idx, void *data, u32 len);
void audio_digital_vol_reset_fade(u8 dvol_idx);
void audio_digital_vol_set_no_fade(u8 dvol_idx, u8 vol);
#endif/*_AUDIO_DVOL_H_*/
+140
View File
@@ -0,0 +1,140 @@
#include "app_config.h"
#ifdef AUDIO_PCM_DEBUG
#include "uartPcmSender.h"
extern int aec_uart_init();
extern int aec_uart_fill(u8 ch, void *buf, u16 size);
extern void aec_uart_write(void);
extern int aec_uart_close(void);
/*
16k 正选波 pcm 数据
*/
static short const sin0_16k[16] = {
0x0000, 0x30fd, 0x5a83, 0x7641, 0x7fff, 0x7642, 0x5a82, 0x30fc, 0x0000, 0xcf04, 0xa57d, 0x89be, 0x8000, 0x89be, 0xa57e, 0xcf05,
};
static u16 tx1_s_cnt = 0;
static int get_sine0_data(u16 *s_cnt, s16 *data, u16 points, u8 ch)
{
while (points--) {
if (*s_cnt >= 16) {
*s_cnt = 0;
}
*data++ = sin0_16k[*s_cnt] / 2;
if (ch == 2) {
*data++ = sin0_16k[*s_cnt] / 2;
}
(*s_cnt)++;
}
return 0;
}
/*
*************************************************************
* uart data export 接口使用说明
* 1、每个通道一次只能固定发送512byte数据,数据不够会被丢弃
* 2、aec_uart_write()一次会发送3个通道的数据,没有填数的通道会发送空白数据
* 3、UART DMA发送一次数据需要约8ms时间,两次发数间隔需 > 8ms
* 4、发送波特率、发送引脚在 uartPcmSender.h 配置
* 5、该接口的接收端需使用JL的串口导出工具接收数据
*
*************************************************************
*/
void audio_export_demo_task(void *param)
{
printf("audio_export_demo_task\n");
s16 data[256];
int len = 512;
/*生成256个点的16k的正选波数据*/
get_sine0_data(&tx1_s_cnt, data, len / 2, 1);
while (1) {
putchar('.');
{
/*run code*/
}
aec_uart_fill(0, data, 512); //往通道0填数据
{
/*run code*/
}
aec_uart_fill(1, data, 512); //往通道1填数据
{
/*run code*/
}
aec_uart_fill(2, data, 512); //往通道2填数据
aec_uart_write(); //一次把3路数据发送出去
os_time_dly(2); //等待发送完成,发送一次要8ms,发完才可以进行下一次发数
}
}
/*
**********************************************************
* uart data export 接口使用示例
*********************************************************
*/
int audio_export_demo_init()
{
printf("audio_export_demo_init\n");
/* uartSendInit(); //串口初始化,已经在开机时调用初始化,这里不需调用 */
aec_uart_init(); //uart export 初始化
os_task_create(audio_export_demo_task, NULL, 1, 1024, 128, "audio_export_task");
return 0;
}
/*
*************************************************************
* 通用 uart 发数接口(uartSendData())使用说明
* 1、发数的数据长度可以根据需要修改
* 2、一般发送512byte,DMA模式需要2.7ms
* 3、发送波特率、发送引脚在 uartPcmSender.h 配置
* 4、可以使用该接口自定义发数方式、协议等
*
*************************************************************
*/
void audio_uart_transmit_demo_task(void *param)
{
printf("audio_uart_transmit_demo_task\n");
s16 data[256];
int len = 512;
/*生成256个点的16k的正选波数据*/
get_sine0_data(&tx1_s_cnt, data, len / 2, 1);
while (1) {
putchar('.');
uartSendData(data, len); //uart 发送数据接口
os_time_dly(1); //一般发送512byte,DMA模式需要2.7ms
}
}
/*
**********************************************************
* 通用uart发数使用示例
*********************************************************
*/
int audio_uart_transmit_demo_init()
{
printf("audio_uart_transmit_demo_init\n");
/* uartSendInit(); //串口初始化,已经在开机时调用初始化,这里不需调用 */
os_task_create(audio_uart_transmit_demo_task, NULL, 1, 1024, 128, "audio_uart_transmit_task");
return 0;
}
static u8 audio_export_demo_idle_query()
{
return 0;
}
REGISTER_LP_TARGET(audio_export_demo_lp_target) = {
.name = "audio_export__demo",
.is_idle = audio_export_demo_idle_query,
};
#endif /*AUDIO_PCM_DEBUG*/
+126
View File
@@ -0,0 +1,126 @@
/*
******************************************************************
* Limiter_NoiseGate Module(限幅器/噪声门限模块)
*1. Limiter:限制最大幅度
*2. NoiseGate:
*(1)启动时间
*(2)释放时间
*(3)噪声阈值
*(4)噪声增益
*3. Usage:
*(1)LIMITER_THR:限幅器参数,限制信号的最大值
*(2)LIMITER_NOISE_GATE:噪声门限的阈值,配合LIMITER_NOISE_GAIN使用
*(3)LIMITER_NOISE_GAIN:当信号小于噪声门限LIMITER_NOISE_GATE的时候
*信号增益为LIMITER_NOISE_GAIN,范围是0到1,增益0为静音,增益1为直通
*效果。噪声门限用来优化声音的底噪
******************************************************************
*/
#include "system/includes.h"
#include "os/os_api.h"
#include "limiter_noiseGate_api.h"
#include "audio_noise_gate.h"
//#define NG_LOG_ENABLE
#ifdef NG_LOG_ENABLE
#define NG_LOG y_printf
#else
#define NG_LOG(...)
#endif/*NG_LOG_ENABLE*/
/*限幅器上限*/
#define LIMITER_THR -10000 /*-12000 = -12dB,放大1000倍,(-10000参考)*/
/*小于CONST_NOISE_GATE的当成噪声处理,防止清0近端声音*/
#define LIMITER_NOISE_GATE -40000 /*-12000 = -12dB,放大1000倍,(-40000参考)*/
/*低于噪声门限阈值的增益 */
#define LIMITER_NOISE_GAIN (0 << 30) /*(0~1)*2^30*/
enum {
NG_STA_CLOSE = 0,
NG_STA_OPEN,
NG_STA_RUN,
};
typedef struct {
u8 state;
OS_MUTEX mutex;
u8 *run_buf;
} audio_noise_gate_t;
audio_noise_gate_t NoiseGate;
int audio_noise_gate_open(u16 sample_rate, int limiter_thr, int noise_gate, int noise_gain)
{
NG_LOG("audio_noise_gate_open");
NoiseGate.run_buf = malloc(need_limiter_noiseGate_buf(1));
NG_LOG("Limiter_noisegate_buf size:%d\n", need_limiter_noiseGate_buf(1));
if (NoiseGate.run_buf) {
//限幅器启动因子 int32(exp(-0.65/(16000 * 0.005))*2^30) 16000为采样率 0.005 为启动时间(s)
int limiter_attfactor = 1065053018;
//限幅器释放因子 int32(exp(-0.15/(16000 * 0.1))*2^30) 16000为采样率 0.1 为释放时间(s)
int limiter_relfactor = 1073641165;
//限幅器阈值(mdb)
//int limiter_threshold = CONST_LIMITER_THR;
//噪声门限启动因子 int32(exp(-1/(16000 * 0.1))*2^30) 16000为采样率 0.1 为启动时间(s)
/*
*import math
*int(math.exp(-1.0/(16000*0.1))*2**30)
*/
int noiseGate_attfactor = 1073070945;
//噪声门限释放因子 int32(exp(-1/(16000 * 0.005))*2^30) 16000为采样率 0.005 为释放时间(s)
int noiseGate_relfactor = 1060403589;
//噪声门限(mdb)
//int noiseGate_threshold = -25000;
//低于噪声门限阈值的增益 (0~1)*2^30
//int noise
//Gate_low_thr_gain = 0 << 30;
if (sample_rate == 8000) {
limiter_attfactor = 1056434522;
limiter_relfactor = 1073540516;
noiseGate_attfactor = 1072400485;
noiseGate_relfactor = 1047231044;
}
limiter_noiseGate_init(NoiseGate.run_buf,
limiter_attfactor,
limiter_relfactor,
noiseGate_attfactor,
noiseGate_relfactor,
limiter_thr,
noise_gate,
noise_gain,
sample_rate, 1);
os_mutex_create(&NoiseGate.mutex);
NoiseGate.state = NG_STA_OPEN;
NG_LOG("audio_noise_gate_open succ");
return 0;
}
return -ENOMEM;
}
void audio_noise_gate_run(void *in, void *out, u16 len)
{
if (NoiseGate.state == NG_STA_CLOSE) {
return;
}
os_mutex_pend(&NoiseGate.mutex, 0);
if (NoiseGate.run_buf) {
limiter_noiseGate_run(NoiseGate.run_buf, in, out, len / 2);
}
os_mutex_post(&NoiseGate.mutex);
}
void audio_noise_gate_close()
{
NG_LOG("audio_noise_gate_close");
os_mutex_pend(&NoiseGate.mutex, 0);
NoiseGate.state = NG_STA_CLOSE;
if (NoiseGate.run_buf) {
free(NoiseGate.run_buf);
}
os_mutex_post(&NoiseGate.mutex);
NG_LOG("audio_noise_gate_close succ");
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef _AUDIO_LIMITER_NOISE_GATE_H_
#define _AUDIO_LIMITER_NOISE_GATE_H_
#include "generic/typedef.h"
int audio_noise_gate_open(u16 sample_rate, int limiter_thr, int noise_gate, int noise_gain);
void audio_noise_gate_run(void *in, void *out, u16 len);
void audio_noise_gate_close();
#endif/*_AUDIO_NOISE_GATE_H_*/
+112
View File
@@ -0,0 +1,112 @@
/*
******************************************************************
* Noise Suppress Module(降噪模块)
*Notes:
*(1)支持降噪的数据采样率:8k/16k
*(2)增加多5k左右代码
*(3)内存消耗跟数据采样率有关,具体可通过以下接口查询:
* int ns_mem_size = noise_suppress_mem_query(&ans->ns_para);
******************************************************************
*/
#include "audio_ns.h"
#ifdef CONFIG_MEDIA_NEW_ENABLE
/*
*********************************************************************
* NoiseSuppress Process
* Description: 降噪处理主函数
* Arguments : ns 降噪句柄
* in 输入数据
* out 输出数据
* len 输入数据长度
* Return : 降噪输出长度
* Note(s) : 由于降噪是固定处理帧长的,所以如果输入数据长度不是降噪
* 帧长整数倍,则某一次会输出0长度,即没有输出
*********************************************************************
*/
int audio_ns_run(audio_ns_t *ns, short *in, short *out, u16 len)
{
if (ns == NULL) {
return len;
}
#if 0
int wlen = cbuf_write(&ns->cbuf, in, len);
if (wlen != len) {
printf("ns_cbuf full\n");
}
if (ns->cbuf.data_len >= NS_FRAME_SIZE) {
cbuf_read(&ns->cbuf, out, NS_FRAME_SIZE);
putchar('.');
noise_suppress_run(out, out, NS_FRAME_POINTS);
return NS_FRAME_SIZE;
} else {
return 0;
}
#else
//putchar('.');
int nOut = noise_suppress_run(in, out, (len / 2));
return (nOut << 1);
#endif
}
/*
*********************************************************************
* Noise Suppress Open
* Description: 初始化降噪模块
* Arguments : sr 数据采样率
* mode 降噪模式(0,1,2:越大越耗资源,效果越好)
* NoiseLevel 初始噪声水平(评估初始噪声,加快收敛)
* AggressFactor 降噪强度(越大越强:1~2)
* MinSuppress 降噪最小压制(越小越强:0~1)
* Return : 降噪模块句柄
* Note(s) : (1)采样率只支持8k、16k
* (2)如果内存不足,可以考虑wideband强制为0,即只做窄带降噪
* ans-ns_para.wideband = 0;
*********************************************************************
*/
audio_ns_t *audio_ns_open(u16 sr, u8 mode, float NoiseLevel, float AggressFactor, float MinSuppress)
{
audio_ns_t *ans = zalloc(sizeof(audio_ns_t));
//cbuf_init(&ans->cbuf, ans->in, sizeof(ans->in));
ans->ns_para.wideband = (sr == 16000) ? 1 : 0;
ans->ns_para.mode = mode;
ans->ns_para.NoiseLevel = NoiseLevel;
ans->ns_para.AggressFactor = AggressFactor;
ans->ns_para.MinSuppress = MinSuppress;
printf("ns wideband:%d\n", ans->ns_para.wideband);
//int ns_mem_size = noise_suppress_mem_query(&ans->ns_para);
//printf("ns mem_size:%d\n", ns_mem_size);
noise_suppress_open(&ans->ns_para);
float lowcut = -60.f;
noise_suppress_config(NS_CMD_LOWCUTTHR, 0, &lowcut);
float noise_floor = -60.f;
noise_suppress_config(NS_CMD_NOISE_FLOOR, 0, &noise_floor);
printf("audio_ns_open ok\n");
return ans;
}
/*
*********************************************************************
* Noise Suppress Close
* Description: 关闭降噪模块
* Arguments : ns 降噪模块句柄
* Return : 0 成功 其他 失败
* Note(s) : None.
*********************************************************************
*/
int audio_ns_close(audio_ns_t *ns)
{
noise_suppress_close();
if (ns) {
free(ns);
ns = NULL;
}
printf("esco_ans_close ok\n");
return 0;
}
#endif /*CONFIG_MEDIA_NEW_ENABLE*/
+61
View File
@@ -0,0 +1,61 @@
#ifndef _AUDIO_NOISE_SUPPRESS_H_
#define _AUDIO_NOISE_SUPPRESS_H_
#include "generic/typedef.h"
#include "generic/circular_buf.h"
#include "commproc_ns.h"
/*降噪数据帧长(单位:点数)*/
#define NS_FRAME_POINTS 160
#define NS_FRAME_SIZE (NS_FRAME_POINTS << 1)
/*降噪输出buf长度*/
#define NS_OUT_POINTS_MAX (NS_FRAME_POINTS << 1)
typedef struct {
//s16 in[512];
//cbuffer_t cbuf;
noise_suppress_param ns_para;
} audio_ns_t;
/*
*********************************************************************
* Noise Suppress Open
* Description: 初始化降噪模块
* Arguments : sr 数据采样率
* mode 降噪模式(0,1,2:越大越耗资源,效果越好)
* NoiseLevel 初始噪声水平(评估初始噪声,加快收敛)
* AggressFactor 降噪强度(越大越强:1~2)
* MinSuppress 降噪最小压制(越小越强:0~1)
* Return : 降噪模块句柄
* Note(s) : 采样率只支持8k、16k
*********************************************************************
*/
audio_ns_t *audio_ns_open(u16 sr, u8 mode, float NoiseLevel, float AggressFactor, float MinSuppress);
/*
*********************************************************************
* NoiseSuppress Process
* Description: 降噪处理主函数
* Arguments : ns 降噪句柄
* in 输入数据
* out 输出数据
* len 输入数据长度
* Return : 降噪输出长度
* Note(s) : 由于降噪是固定处理帧长的,所以如果输入数据长度不是降噪
* 帧长整数倍,则某一次会输出0长度,即没有输出
*********************************************************************
*/
int audio_ns_run(audio_ns_t *ns, short *in, short *out, u16 len);
/*
*********************************************************************
* Noise Suppress Close
* Description: 关闭降噪模块
* Arguments : ns 降噪模块句柄
* Return : 0 成功 其他 失败
* Note(s) : None.
*********************************************************************
*/
int audio_ns_close(audio_ns_t *ns);
#endif/*_AUDIO_NOISE_SUPPRESS_H_*/
+138
View File
@@ -0,0 +1,138 @@
/*
************************************************************
*
*
*
************************************************************
*/
#include "system/includes.h"
#include "PLC.h"
#include "os/os_api.h"
#include "app_config.h"
#include "audio_config.h"
#if TCFG_ESCO_PLC
//#define AUDIO_PLC_LOG_ENABLE
#ifdef AUDIO_PLC_LOG_ENABLE
#define PLC_LOG y_printf
#else
#define PLC_LOG(...)
#endif/*AUDIO_PLC_LOG_ENABLE*/
enum {
PLC_STA_CLOSE = 0,
PLC_STA_OPEN,
PLC_STA_RUN,
};
#define PLC_FRAME_LEN 120
typedef struct {
u8 state;
u8 repair;
u8 wideband;
OS_MUTEX mutex;
s16 *run_buf;
} audio_plc_t;
static audio_plc_t plc;
int audio_plc_open(u16 sr)
{
PLC_LOG("audio_plc_open:%d\n", sr);
memset((u8 *)&plc, 0, sizeof(audio_plc_t));
plc.run_buf = malloc(PLC_query()); /*buf_size:1040*/
PLC_LOG("PLC_buf:%x,size:%d\n", plc.run_buf, PLC_query());
if (plc.run_buf) {
s8 err = PLC_init(plc.run_buf);
if (err) {
PLC_LOG("PLC_init err:%d", err);
free(plc.run_buf);
return -EINVAL;
}
os_mutex_create(&plc.mutex);
if (sr == 16000) {
plc.wideband = 1;
}
plc.state = PLC_STA_OPEN;
}
PLC_LOG("audio_plc_open succ\n");
return 0;
}
void audio_plc_run(s16 *data, u16 len, u8 repair)
{
u16 repair_point, tmp_point;
s16 *p_in, *p_out;
p_in = data;
p_out = data;
tmp_point = len / 2;
u8 repair_flag = 0;
os_mutex_pend(&plc.mutex, 0);
if (plc.state == PLC_STA_CLOSE) {
os_mutex_post(&plc.mutex);
return;
}
#if 0 //debug
static u16 repair_cnt = 0;
if (repair) {
repair_cnt++;
y_printf("[E%d]", repair_cnt);
} else {
repair_cnt = 0;
}
//printf("[%d]",point);
#endif/*debug*/
repair_flag = repair;
if (plc.wideband) {
/*
*msbc plc deal
*如果上一帧是错误,则当前帧也要修复
*/
if (plc.repair) {
repair_flag = 1;
}
plc.repair = repair;
}
while (tmp_point) {
repair_point = (tmp_point > PLC_FRAME_LEN) ? PLC_FRAME_LEN : tmp_point;
tmp_point = tmp_point - repair_point;
PLC_run(p_in, p_out, repair_point, repair_flag);
p_in += repair_point;
p_out += repair_point;
}
os_mutex_post(&plc.mutex);
}
int audio_plc_close(void)
{
PLC_LOG("audio_plc_close\n");
os_mutex_pend(&plc.mutex, 0);
plc.state = PLC_STA_CLOSE;
if (plc.run_buf) {
free(plc.run_buf);
plc.run_buf = NULL;
}
os_mutex_post(&plc.mutex);
PLC_LOG("audio_plc_close succ\n");
return 0;
}
#else
int audio_plc_open(void)
{
return 0;
}
void audio_plc_run(s16 *dat, u16 len, u8 repair_flag)
{
}
int audio_plc_close()
{
return 0;
}
#endif/*TCFG_ESCO_PLC*/
+10
View File
@@ -0,0 +1,10 @@
#ifndef _AUDIO_PLC_H_
#define _AUDIO_PLC_H_
#include "generic/typedef.h"
int audio_plc_open(u16 sr);
void audio_plc_run(s16 *dat, u16 len, u8 repair_flag);
int audio_plc_close(void);
#endif/*_AUDIO_PLC_H_*/
+28
View File
@@ -0,0 +1,28 @@
/*
************************************************************
* Audio Utils
*Brief:数字信号处理常用模块合集
*Notes:
************************************************************
*/
#include "audio_utils.h"
/*
*********************************************************************
* Audio Digital Phase Inverter
* Description: 数字反相器,用来反转数字音频信号的相位
* Arguments : dat 数据buf地址
* len 数据长度(unit:byte)
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void digital_phase_inverter_s16(s16 *dat, int len)
{
int data_size = len / 2;
for (int i = 0; i < data_size; i++) {
dat[i] = (dat[i] == -32768) ? 32767 : -dat[i];
}
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef _AUDIO_UTILS_H_
#define _AUDIO_UTILS_H_
#include "generic/typedef.h"
/*
*********************************************************************
* Audio Digital Phase Inverter
* Description: 数字反相器,用来反转数字音频信号的相位
* Arguments : dat 数据buf地址
* len 数据长度(unit:byte)
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void digital_phase_inverter_s16(s16 *dat, int len);
#endif/*_AUDIO_UTILS_H_*/
+707
View File
@@ -0,0 +1,707 @@
#include "asm/includes.h"
#include "media/includes.h"
#include "system/includes.h"
#include "app_config.h"
#include "audio_config.h"
/* #include "audio_dec.h" */
#include "application/audio_dec_app.h"
#include "tone_player.h"
#include "sine_make.h"
#if TCFG_KEY_TONE_EN
// 按键提示音任务名
#define AUDIO_KEY_TONE_TASK_NAME "key_tone"
// 按键提示音数字音量控制
#if (SYS_DIGVOL_GROUP_EN && defined(CONFIG_MEDIA_DEVELOP_ENABLE))
#define AUDIO_KEY_TONE_DIGVOL_EN 0
#define AUDIO_KEY_TONE_DIGVOL_NAME "key_tone"
#else
#define AUDIO_KEY_TONE_DIGVOL_EN 0
#endif
//////////////////////////////////////////////////////////////////////////////
/*
* 使用audio_dec_app.h里面的接口,可以实现普通文件、正弦波文件、正弦波数组播放
*/
// 参数
struct __key_tone_play_info {
const char *file_name; // 文件名
struct audio_sin_param *sin; // 正弦波数组
u8 sin_num; // 正弦波数组长度
u8 preemption; // 1-抢占,0-叠加
void (*evt_handler)(void *priv, int flag); // 事件回调
void *evt_priv; // 事件回调私有句柄
};
// 按键提示音
struct __key_tone {
volatile u8 busy; // 任务工作中
volatile u8 start; // 运行标志
volatile u8 play;
#if AUDIO_KEY_TONE_DIGVOL_EN
u8 volume; // 音量
#endif
struct __key_tone_play_info play_info; // 输入参数
struct audio_dec_sine_app_hdl *dec_sin; // 文件播放句柄
struct audio_dec_file_app_hdl *dec_file; // sine播放句柄
void (*evt_handler)(void *priv, int flag); // 事件回调
void *evt_priv; // 事件回调私有句柄
const char *evt_owner; // 事件回调所在任务
};
//////////////////////////////////////////////////////////////////////////////
extern struct audio_mixer mixer;
static struct __key_tone *key_tone = NULL;
//////////////////////////////////////////////////////////////////////////////
/*
*********************************************************************
* Audio Key Tone Get File Ext Name
* Description: 获取文件名后缀
* Arguments : *name 文件名
* Return : 后缀
* Note(s) : None.
*********************************************************************
*/
static char *get_file_ext_name(char *name)
{
int len = strlen(name);
char *ext = (char *)name;
while (len--) {
if (*ext++ == '.') {
break;
}
}
if (len <= 0) {
ext = name + (strlen(name) - 3);
}
return ext;
}
/*
*********************************************************************
* Audio Key Tone Post Event
* Description: 解码事件
* Arguments : *ktone 按键提示音解码句柄
* end_flag 结束标志
* Return : true 成功
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_event_handler(struct __key_tone *ktone, u8 end_flag)
{
int argv[4];
if (!ktone->evt_handler) {
log_i("evt_handler null\n");
return false;
}
argv[0] = (int)ktone->evt_handler;
argv[1] = 2;
argv[2] = (int)ktone->evt_priv;
argv[3] = (int)end_flag; //0正常关闭,1被打断关闭
int ret = os_taskq_post_type(ktone->evt_owner, Q_CALLBACK, 4, argv);
if (ret) {
return false;
}
return true;
}
/*
*********************************************************************
* Audio Key Tone Reelease
* Description: 提示音解码器释放
* Arguments : *ktone 按键提示音解码句柄
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_dec_hdl_release(struct __key_tone *ktone)
{
if (ktone->dec_file) {
audio_dec_file_app_close(ktone->dec_file);
ktone->dec_file = NULL;
}
if (ktone->dec_sin) {
audio_dec_sine_app_close(ktone->dec_sin);
ktone->dec_sin = NULL;
}
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
app_audio_state_exit(APP_AUDIO_STATE_WTONE);
#endif
/* clock_remove_set(DEC_TONE_CLK); */
}
/*
*********************************************************************
* Audio Key Tone Init OK
* Description: 解码初始化完成
* Arguments : *ktone 按键提示音解码句柄
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_dec_hdl_init_ok(struct __key_tone *ktone)
{
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
if (audio_mixer_get_ch_num(&mixer) <= 1) {
#ifdef TCFG_WTONT_ONCE_VOL
extern u8 get_tone_once_vol(void);
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol());
#else
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol());
#endif
}
#endif
/* clock_add_set(DEC_TONE_CLK); */
}
/*
*********************************************************************
* Audio Key Tone Close
* Description: 关闭提示音解码
* Arguments : *ktone 按键提示音解码句柄
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_play_close(struct __key_tone *ktone)
{
/* log_i("ktone:0x%x, sin:0x%x, file:0x%x \n", ktone, ktone->dec_file, ktone->dec_file); */
if (ktone->dec_file || ktone->dec_sin) {
key_tone_dec_hdl_release(ktone);
key_tone_dec_event_handler(ktone, 1);
}
}
/*
*********************************************************************
* Audio Key Tone Event Callback
* Description: 解码回调处理
* Arguments : *ktone 按键提示音解码句柄
* event 事件
* *param 事件参数
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_app_evt_cb(struct __key_tone *ktone, enum audio_dec_app_event event, int *param)
{
switch (event) {
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
log_i("key_tone start init ok\n");
key_tone_dec_hdl_init_ok(ktone);
break;
case AUDIO_DEC_APP_EVENT_PLAY_END:
log_i("key_tone play end\n");
key_tone_dec_hdl_release(ktone);
key_tone_dec_event_handler(ktone, 0);
break;
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
case AUDIO_DEC_APP_EVENT_STREAM_OPEN: {
#if AUDIO_KEY_TONE_DIGVOL_EN
struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param;
void *dvol_entry = NULL;
audio_dig_vol_param temp_digvol_param = {
.vol_start = ktone->volume,//get_max_sys_vol(),
.vol_max = get_max_sys_vol(),
.ch_total = audio_output_channel_num(),
.fade_en = 0,
.fade_points_step = 5,
.fade_gain_step = 10,
.vol_list = NULL,
};
dvol_entry = sys_digvol_group_ch_open(AUDIO_KEY_TONE_DIGVOL_NAME, -1, &temp_digvol_param);
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry;
#endif // SYS_DIGVOL_GROUP_EN
}
break;
case AUDIO_DEC_APP_EVENT_STREAM_CLOSE: {
}
break;
#endif /*#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)*/
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
#if AUDIO_KEY_TONE_DIGVOL_EN
sys_digvol_group_ch_close(AUDIO_KEY_TONE_DIGVOL_NAME);
#endif // SYS_DIGVOL_GROUP_EN
break;
default :
break;
}
return 0;
}
/*
*********************************************************************
* Audio Key Tone Sin Event Callback
* Description: sine提示音解码回调
* Arguments : *priv 私有句柄
* event 事件
* *param 事件参数
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
{
struct audio_dec_sine_app_hdl *sine_dec = priv;
struct __key_tone *ktone = sine_dec->priv;
switch (event) {
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
if (sine_dec->sin_maker) {
break;
}
audio_dec_sine_app_probe(sine_dec);
if (!sine_dec->sin_maker) {
return -ENOENT;
}
break;
default :
return key_tone_dec_app_evt_cb(ktone, event, param);
}
return 0;
}
/*
*********************************************************************
* Audio Key Tone File Event Callback
* Description: file提示音解码回调
* Arguments : *priv 私有句柄
* event 事件
* *param 事件参数
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
static int key_tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
{
struct audio_dec_file_app_hdl *file_dec = priv;
struct __key_tone *ktone = file_dec->priv;
switch (event) {
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
break;
default :
return key_tone_dec_app_evt_cb(ktone, event, param);
}
return 0;
}
/*
*********************************************************************
* Audio Key Tone Run
* Description: 按键提示音运行
* Arguments : *ktone 按键提示音解码句柄
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
static int key_tone_play_run(struct __key_tone *ktone)
{
if (!ktone->start) {
return -1;
}
struct __key_tone_play_info info = {0};
local_irq_disable();
if (!ktone->play) {
local_irq_enable();
return 0;
}
// 保存播放参数
memcpy(&info, &ktone->play_info, sizeof(struct __key_tone_play_info));
ktone->play = 0;
local_irq_enable();
// 关闭现有play
key_tone_play_close(ktone);
// 设置参数
ktone->evt_handler = info.evt_handler;
ktone->evt_priv = info.evt_priv;
ktone->evt_owner = "app_core";
// 正弦波数组播放
if (info.sin && info.sin_num) {
ktone->dec_sin = audio_dec_sine_app_create_by_parm(info.sin, info.sin_num, !info.preemption);
if (ktone->dec_sin == NULL) {
return -1;
}
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
ktone->dec_sin->priv = ktone;
/* audio_dec_sine_app_open(ktone->dec_sin); */
ktone->dec_sin->dec->wait.only_del = 1;
audio_dec_app_start(ktone->dec_sin->dec);
return 0;
}
// 判断文件名后缀
u8 file_name[16];
char *format = NULL;
FILE *file = fopen(info.file_name, "r");
if (!file) {
return -1;
}
fget_name(file, file_name, 16);
format = get_file_ext_name((char *)file_name);
fclose(file);
// 正弦波文件播放
if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) {
ktone->dec_sin = audio_dec_sine_app_create(info.file_name, !info.preemption);
if (ktone->dec_sin == NULL) {
return -1;
}
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
ktone->dec_sin->priv = ktone;
/* audio_dec_sine_app_open(ktone->dec_sin); */
ktone->dec_sin->dec->wait.only_del = 1;
audio_dec_app_start(ktone->dec_sin->dec);
return 0;
}
// 普通文件播放
ktone->dec_file = audio_dec_file_app_create(info.file_name, !info.preemption);
if (ktone->dec_file == NULL) {
return -1;
}
if (ktone->dec_file->dec->dec_type == AUDIO_CODING_SBC) {
audio_dec_app_set_frame_info(ktone->dec_file->dec, 0x4e, ktone->dec_file->dec->dec_type);
}
ktone->dec_file->dec->evt_cb = key_tone_dec_file_app_evt_cb;
ktone->dec_file->priv = ktone;
/* audio_dec_file_app_open(ktone->dec_file); */
ktone->dec_file->dec->wait.only_del = 1;
audio_dec_app_start(ktone->dec_file->dec);
return 0;
}
/*
*********************************************************************
* Audio Key Tone Task Run
* Description: 按键提示音任务处理
* Arguments : *p 按键提示音解码句柄
* Return : None.
* Note(s) : None.
*********************************************************************
*/
static void key_tone_task_deal(void *p)
{
int res = 0;
int msg[16];
struct __key_tone *ktone = (struct __key_tone *)p;
ktone->start = 1;
ktone->busy = 1;
while (1) {
os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
res = key_tone_play_run(ktone);
if (res) {
///等待删除线程
key_tone_play_close(ktone);
ktone->busy = 0;
while (1) {
os_time_dly(10000);
}
}
}
}
/*
*********************************************************************
* Audio Key Tone Destroy
* Description: 注销按键提示音播放
* Arguments : None.
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_key_tone_destroy(void)
{
if (!key_tone) {
return ;
}
key_tone->start = 0;
while (key_tone->busy) {
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
os_time_dly(1);
}
task_kill(AUDIO_KEY_TONE_TASK_NAME);
local_irq_disable();
free(key_tone);
key_tone = NULL;
local_irq_enable();
}
/*
*********************************************************************
* Audio Key Tone Init
* Description: 按键提示音初始化
* Arguments : None.
* Return : true 成功
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_init(void)
{
int err = 0;
if (key_tone) {
return true;
}
struct __key_tone *ktone = zalloc(sizeof(struct __key_tone));
err = task_create(key_tone_task_deal, (void *)ktone, AUDIO_KEY_TONE_TASK_NAME);
if (err != OS_NO_ERR) {
log_e("%s creat fail %x\n", __FUNCTION__, err);
free(ktone);
return false;
}
#if AUDIO_KEY_TONE_DIGVOL_EN
ktone->volume = get_max_sys_vol();
#endif
key_tone = ktone;
return true;
}
//////////////////////////////////////////////////////////////////////////////
// 正弦波序号
#define KTONE_SINE_NORAML 0
// 按键提示音序号
enum {
KTONE_IDEX_NORAML = 0,
KTONE_IDEX_NUM_0,
KTONE_IDEX_NUM_1,
KTONE_IDEX_MAX,
};
// 序号对应表
static const char *const key_tone_index[] = {
[KTONE_IDEX_NORAML] = DEFAULT_SINE_TONE(KTONE_SINE_NORAML),
[KTONE_IDEX_NUM_0] = SDFILE_RES_ROOT_PATH"tone/0.*",
[KTONE_IDEX_NUM_1] = SDFILE_RES_ROOT_PATH"tone/1.*",
};
/*
* 正弦波参数配置:
* freq : 实际频率 * 512
* points : 正弦波点数
* win : 正弦窗
* decay : 衰减系数(百分比), 正弦窗模式下为频率设置:频率*512
*/
static const struct sin_param sine_16k_normal[] = {
/*{0, 1000, 0, 100},*/
{200 << 9, 4000, 0, 100},
};
//////////////////////////////////////////////////////////////////////////////
/*
*********************************************************************
* Audio Key Tone Get Sine Param Data
* Description: 获取正弦波数组
* Arguments : id 正弦波序号
* *num 正弦波数组长度
* Return : 正弦波数组
* Note(s) : None.
*********************************************************************
*/
static const struct sin_param *get_sine_param_data(u8 id, u8 *num)
{
const struct sin_param *param_data = NULL;
switch (id) {
case KTONE_SINE_NORAML:
param_data = sine_16k_normal;
*num = ARRAY_SIZE(sine_16k_normal);
break;
default:
return NULL;
}
return param_data;
};
/*
*********************************************************************
* Audio Key Tone Open With Callback
* Description: 打开文件播放
* Arguments : *file_name 文件名
* *sin 正弦波数组
* sin_num 正弦波数组长度
* preemption 1-抢断播放;0-叠加播放
* evt_handler 事件回调
* evt_priv 事件回调参数
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
static int ktone_play_open_with_callback_base(const char *file_name, struct audio_sin_param *sin, u8 sin_num, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv)
{
struct __key_tone *ktone = key_tone;
if ((!ktone) || (!ktone->start)) {
return -1;
}
struct __key_tone_play_info info = {0};
info.preemption = preemption;
info.evt_handler = evt_handler;
info.evt_priv = evt_priv;
if (sin && sin_num) {
info.sin = sin;
info.sin_num = sin_num;
} else {
info.file_name = file_name;
if (IS_DEFAULT_SINE(file_name)) {
info.sin = get_sine_param_data(DEFAULT_SINE_ID(file_name), &info.sin_num);
}
}
local_irq_disable();
memcpy(&ktone->play_info, &info, sizeof(struct __key_tone_play_info));
ktone->play = 1;
local_irq_enable();
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
return 0;
}
/*
*********************************************************************
* Audio Key Tone Play Sine
* Description: 播放正弦波数组
* Arguments : *sin 正弦波数组
* sin_num 正弦波数组长度
* preemption 1-抢断播放;0-叠加播放
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_play_sin(struct audio_sin_param *sin, u8 sin_num, u8 preemption)
{
/* y_printf("n:0x%x \n", name); */
return ktone_play_open_with_callback_base(NULL, sin, sin_num, preemption, NULL, NULL);
}
/*
*********************************************************************
* Audio Key Tone Play File
* Description: 播放文件
* Arguments : *name 文件名
* preemption 1-抢断播放;0-叠加播放
* Return : 0 正常
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_play_name(const char *name, u8 preemption)
{
/* y_printf("n:0x%x \n", name); */
return ktone_play_open_with_callback_base(name, NULL, 0, preemption, NULL, NULL);
}
/*
*********************************************************************
* Audio Key Tone Play Index
* Description: 按序号播放文件
* Arguments : index 序号
* preemption 1-抢断播放;0-叠加播放
* Return : 0 正常
* Note(s) : 使用key_tone_index[]数组
*********************************************************************
*/
int audio_key_tone_play_index(u8 index, u8 preemption)
{
if (index >= KTONE_IDEX_MAX) {
return -1;
}
return audio_key_tone_play_name(key_tone_index[index], preemption);
}
/*
*********************************************************************
* Audio Key Tone Play
* Description: 按键提示音播放
* Arguments : None.
* Return : None.
* Note(s) : 默认播放
*********************************************************************
*/
void audio_key_tone_play(void)
{
audio_key_tone_play_index(KTONE_IDEX_NORAML, 0);
/* audio_key_tone_play_index(KTONE_IDEX_NUM_0, 0); */
/* audio_key_tone_play_sin(sine_16k_normal, ARRAY_SIZE(sine_16k_normal), 0); */
}
/*
*********************************************************************
* Audio Key Tone Check Play
* Description: 检测按键提示音是否在播放
* Arguments : None.
* Return : true 正在播放
* Note(s) : None.
*********************************************************************
*/
int audio_key_tone_is_play(void)
{
if ((!key_tone) || (!key_tone->start)) {
return false;
}
if (key_tone->dec_file || key_tone->dec_sin) {
return true;
}
return false;
}
/*
*********************************************************************
* Audio Key Tone Set Digvol
* Description: 设置按键提示音的音量
* Arguments : volume 音量
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void audio_key_tone_digvol_set(u8 volume)
{
#if AUDIO_KEY_TONE_DIGVOL_EN
log_i("vol:%d \n", volume);
if (!key_tone) {
return ;
}
key_tone->volume = volume;
void *vol_hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, AUDIO_KEY_TONE_DIGVOL_NAME);
if (vol_hdl == NULL) {
return;
}
audio_dig_vol_set(vol_hdl, AUDIO_DIG_VOL_ALL_CH, volume);
#endif
}
#endif
+325
View File
@@ -0,0 +1,325 @@
#include "application/audio_dec_app.h"
#include "app_config.h"
#include "audio_config.h"
#include "app_main.h"
//////////////////////////////////////////////////////////////////////////////
extern struct audio_decoder_task decode_task;
extern struct audio_mixer mixer;
extern struct audio_dac_hdl dac_hdl;
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
extern struct audio_dac_channel default_dac;
#endif
extern const int audio_dec_app_mix_en;
extern u32 audio_output_channel_num(void);
//////////////////////////////////////////////////////////////////////////////
struct audio_dec_app_audio_state_hdl {
struct audio_mixer *p_mixer;
u32 dec_mix : 1; // 1:叠加模式
u32 flag;
};
//////////////////////////////////////////////////////////////////////////////
const struct audio_dec_format_hdl decode_format_list[] = {
{"wtg", AUDIO_CODING_G729},
{"msbc", AUDIO_CODING_MSBC},
{"msb", AUDIO_CODING_MSBC},
{"sbc", AUDIO_CODING_SBC},
{"mty", AUDIO_CODING_MTY},
{"aac", AUDIO_CODING_AAC},
{"mp3", AUDIO_CODING_MP3},
{"wma", AUDIO_CODING_WMA},
{"wav", AUDIO_CODING_WAV},
#if (defined(TCFG_DEC_MIDI_ENABLE) && TCFG_DEC_MIDI_ENABLE)
//midi 文件播放,需要对应音色文件配合
{"midi", AUDIO_CODING_MIDI},
{"mid", AUDIO_CODING_MIDI},
#endif //TCFG_DEC_MIDI_ENABLE
#if TCFG_DEC_WTGV2_ENABLE
{"wts", AUDIO_CODING_WTGV2},
#endif
{"speex", AUDIO_CODING_SPEEX},
{"opus", AUDIO_CODING_OPUS},
{0, 0},
};
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
static struct audio_stream_entry *audio_dec_app_entries[2] = {NULL};
#endif
//////////////////////////////////////////////////////////////////////////////
/*----------------------------------------------------------------------------*/
/**@brief 解码创建参数初始化
@param *dec: 解码句柄
@return 0-正常
@note 弱函数重定义
*/
/*----------------------------------------------------------------------------*/
int audio_dec_app_create_param_init(struct audio_dec_app_hdl *dec)
{
dec->p_decode_task = &decode_task;
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
if (!audio_dec_app_mix_en) {
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
audio_dec_app_entries[0] = &default_dac.entry;
#else
audio_dec_app_entries[0] = &dac_hdl.entry;
#endif
dec->entries = audio_dec_app_entries;
} else
#endif
{
dec->p_mixer = &mixer;
}
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
u8 dac_connect_mode = app_audio_output_mode_get();
if (dac_connect_mode == DAC_OUTPUT_FRONT_LR_REAR_LR) {
dec->out_ch_num = 4;
} else {
dec->out_ch_num = audio_output_channel_num();
}
#else
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
switch (dac_connect_mode) {
/* case DAC_OUTPUT_DUAL_LR_DIFF: */
case DAC_OUTPUT_LR:
dec->out_ch_num = 2;
break;
/* case DAC_OUTPUT_FRONT_LR_REAR_LR: */
/* dec->out_ch_num = 4; */
/* break; */
default :
dec->out_ch_num = 1;
break;
}
#endif
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 文件解码创建参数初始化
@param *file_dec: 文件解码句柄
@return 0-正常
@note 弱函数重定义
*/
/*----------------------------------------------------------------------------*/
int audio_dec_file_app_create_param_init(struct audio_dec_file_app_hdl *file_dec)
{
file_dec->format = (struct audio_dec_format_hdl *)decode_format_list;
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 解码输出状态设置
@param *dec: 解码句柄
@param flag: 解码标签
@return 0-正常
@note
*/
/*----------------------------------------------------------------------------*/
int audio_dec_app_audio_state_switch(struct audio_dec_app_hdl *dec, u32 flag)
{
u8 need_set_audio = 1;
/* if ((dec->dec_mix) && (audio_mixer_get_ch_num(dec->p_mixer) > 1)) { */
/* need_set_audio = 0; */
/* } */
if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) {
need_set_audio = 1;
}
if (need_set_audio) {
if (flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) {
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
} else {
#ifdef TCFG_WTONT_ONCE_VOL
extern u8 get_tone_once_vol(void);
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol());
#else
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol());
#endif
}
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 解码输出状态退出
@param *p_aud_state: 输出状态
@return 0-正常
@note
*/
/*----------------------------------------------------------------------------*/
int audio_dec_app_audio_state_exit(struct audio_dec_app_audio_state_hdl *p_aud_state)
{
u8 need_set_audio = 1;
/* if ((p_aud_state->dec_mix) && (audio_mixer_get_ch_num(p_aud_state->p_mixer) > 1)) { */
/* need_set_audio = 0; */
/* } */
/* if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) { */
/* need_set_audio = 1; */
/* } */
if (need_set_audio) {
if (p_aud_state->flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) {
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
} else {
app_audio_state_exit(APP_AUDIO_STATE_WTONE);
}
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 文件解码初始化完成
@param *file_dec: 文件解码句柄
@return 0-正常
@note 弱函数重定义
*/
/*----------------------------------------------------------------------------*/
int audio_dec_file_app_init_ok(struct audio_dec_file_app_hdl *file_dec)
{
audio_dec_app_audio_state_switch(file_dec->dec, file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK);
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 文件解码结束
@param *file_dec: 文件解码句柄
@return 0-正常
@note 弱函数重定义
*/
/*----------------------------------------------------------------------------*/
int audio_dec_file_app_play_end(struct audio_dec_file_app_hdl *file_dec)
{
struct audio_dec_app_audio_state_hdl aud_state = {0};
aud_state.p_mixer = file_dec->dec->p_mixer;
aud_state.dec_mix = file_dec->dec->dec_mix;
aud_state.flag = file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK;
audio_dec_file_app_close(file_dec);
audio_dec_app_audio_state_exit(&aud_state);
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 正弦波解码初始化完成
@param *sine_dec: 正弦波解码句柄
@return 0-正常
@note 弱函数重定义
*/
/*----------------------------------------------------------------------------*/
int audio_dec_sine_app_init_ok(struct audio_dec_sine_app_hdl *sine_dec)
{
audio_dec_app_audio_state_switch(sine_dec->dec, sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK);
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 正弦波解码结束
@param *sine_dec: 正弦波解码句柄
@return 0-正常
@note 弱函数重定义
*/
/*----------------------------------------------------------------------------*/
int audio_dec_sine_app_play_end(struct audio_dec_sine_app_hdl *sine_dec)
{
struct audio_dec_app_audio_state_hdl aud_state = {0};
aud_state.p_mixer = sine_dec->dec->p_mixer;
aud_state.dec_mix = sine_dec->dec->dec_mix;
aud_state.flag = sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK;
audio_dec_sine_app_close(sine_dec);
audio_dec_app_audio_state_exit(&aud_state);
return 0;
}
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
void audio_dec_app_output_sr_set(struct audio_dec_app_hdl *dec)
{
/* #if defined(CONFIG_CPU_BR23) */
/* extern u32 audio_output_rate(int input_rate); */
/* dec->src_out_sr = audio_output_rate(dec->src_out_sr); */
/* #endif */
if (dec->src_out_sr == 0) {
dec->src_out_sr = audio_dac_get_sample_rate(&dac_hdl);
if (dec->src_out_sr == 0) {
dec->src_out_sr = 16000;
log_w("src out is zero \n");
}
}
if (dec->sample_rate == 0) {
dec->sample_rate = dec->src_out_sr;
}
}
#endif
//////////////////////////////////////////////////////////////////////////////
// test
#if 0
#include "tone_player.h"
void audio_dec_file_test(void)
{
struct audio_dec_file_app_hdl *hdl;
hdl = audio_dec_file_app_create(TONE_POWER_ON, 1);
if (hdl) {
audio_dec_file_app_open(hdl);
}
os_time_dly(2);
hdl = audio_dec_file_app_create(TONE_POWER_OFF, 1);
if (hdl) {
audio_dec_file_app_open(hdl);
}
os_time_dly(300);
}
static const struct audio_sin_param sine_test[] = {
/*{0, 1000, 0, 100},*/
{200 << 9, 4000, 0, 100},
};
static const struct audio_sin_param sine_test1[] = {
{450 << 9, 24960, 1, 16.667 * 512},
{0, 16000, 0, 100},
};
void audio_dec_sine_test(void)
{
struct audio_dec_sine_app_hdl *hdl;
/* hdl = audio_dec_sine_app_create(SDFILE_RES_ROOT_PATH"tone/vol_max.sin", 1); */
hdl = audio_dec_sine_app_create_by_parm(sine_test1, ARRAY_SIZE(sine_test1), 1);
if (hdl) {
audio_dec_sine_app_open(hdl);
}
os_time_dly(2);
hdl = audio_dec_sine_app_create_by_parm(sine_test, ARRAY_SIZE(sine_test), 1);
if (hdl) {
audio_dec_sine_app_open(hdl);
}
/* os_time_dly(300); */
}
void audio_dec_usb_file_test(void)
{
tone_play_stop();
clk_set("sys", 192 * 1000000L);
struct audio_dec_file_app_hdl *hdl;
/* hdl = audio_dec_file_app_create("storage/udisk/C/1.mp3", 1); */
hdl = audio_dec_file_app_create("storage/udisk/C/1.wav", 1);
if (hdl) {
audio_dec_file_app_open(hdl);
}
os_time_dly(2);
/* hdl = audio_dec_file_app_create("storage/udisk/C/2.mp3", 1); */
hdl = audio_dec_file_app_create("storage/udisk/C/2.wav", 1);
if (hdl) {
audio_dec_file_app_open(hdl);
}
os_time_dly(300);
}
#endif /*test*/
+410
View File
@@ -0,0 +1,410 @@
/*****************************************************************
>file name : apps/common/sine_make.c
>author : lichao
>create time : Sun 05 May 2019 08:37:35 PM CST
*****************************************************************/
#include "system/includes.h"
#include "sine_make.h"
#define SINE_USE_MALLOC 1
struct audio_sin_maker {
u8 open;
u8 id;
u8 sin_num;
u8 channel;
u8 repeat;
u8 next_param;
u16 fade_points;
/*int sample_rate;*/
int volume;
int points;
int sin_index;
int win_sin_index;
const struct sin_param *sin;
};
#ifndef SINE_USE_MALLOC
static struct audio_sin_maker sin_maker_handle;
#endif
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat)
{
if (!param || !num) {
return NULL;
}
#ifdef SINE_USE_MALLOC
struct audio_sin_maker *sin = zalloc(sizeof(struct audio_sin_maker));
#else
struct audio_sin_maker *sin = &sin_maker_handle;
#endif
if (!sin) {
return NULL;
}
if (sin->open) {
return NULL;
}
sin->sin = param;
sin->sin_num = num;
sin->open = 1;
sin->points = param[0].points;
sin->id = 0;
sin->channel = channel;
sin->repeat = repeat;
#if (defined CONFIG_CPU_BR18 || \
defined CONFIG_CPU_BR21)
/*这里如果加多fade points,会导致结束的时候有噪声,不是在淡出尾部*/
sin->fade_points = 0;
#else
sin->fade_points = 480;
#endif
sin->next_param = 1;
return (void *)sin;
}
#if !defined(SINE_MAKE_IN_MASK)
const int sf_sin_tab1[513] = {
0x00000000, 0x0000c910, 0x0001921f, 0x00025b2d, 0x0003243a, 0x0003ed45, 0x0004b64e, 0x00057f53,
0x00064855, 0x00071154, 0x0007da4e, 0x0008a343, 0x00096c33, 0x000a351d, 0x000afe00, 0x000bc6dd,
0x000c8fb3, 0x000d5881, 0x000e2147, 0x000eea03, 0x000fb2b7, 0x00107b61, 0x00114401, 0x00120c96,
0x0012d521, 0x00139d9f, 0x00146611, 0x00152e77, 0x0015f6d0, 0x0016bf1b, 0x00178758, 0x00184f87,
0x001917a7, 0x0019dfb7, 0x001aa7b7, 0x001b6fa7, 0x001c3786, 0x001cff53, 0x001dc70f, 0x001e8eb8,
0x001f564e, 0x00201dd1, 0x0020e541, 0x0021ac9b, 0x002273e2, 0x00233b13, 0x0024022e, 0x0024c933,
0x00259021, 0x002656f8, 0x00271db7, 0x0027e45f, 0x0028aaed, 0x00297163, 0x002a37bf, 0x002afe01,
0x002bc429, 0x002c8a35, 0x002d5026, 0x002e15fb, 0x002edbb4, 0x002fa14f, 0x003066ce, 0x00312c2e,
0x0031f170, 0x0032b694, 0x00337b98, 0x0034407c, 0x00350540, 0x0035c9e4, 0x00368e66, 0x003752c6,
0x00381705, 0x0038db21, 0x00399f19, 0x003a62ef, 0x003b26a0, 0x003bea2c, 0x003cad94, 0x003d70d7,
0x003e33f3, 0x003ef6e9, 0x003fb9b8, 0x00407c60, 0x00413ee0, 0x00420138, 0x0042c367, 0x0043856d,
0x0044474a, 0x004508fc, 0x0045ca83, 0x00468be0, 0x00474d11, 0x00480e16, 0x0048ceef, 0x00498f9a,
0x004a5019, 0x004b1069, 0x004bd08b, 0x004c907f, 0x004d5043, 0x004e0fd8, 0x004ecf3c, 0x004f8e70,
0x00504d72, 0x00510c43, 0x0051cae3, 0x0052894f, 0x00534789, 0x0054058f, 0x0054c362, 0x00558100,
0x00563e6a, 0x0056fb9e, 0x0057b89d, 0x00587565, 0x005931f7, 0x0059ee52, 0x005aaa76, 0x005b6662,
0x005c2215, 0x005cdd8f, 0x005d98d0, 0x005e53d8, 0x005f0ea5, 0x005fc937, 0x0060838f, 0x00613dab,
0x0061f78b, 0x0062b12e, 0x00636a95, 0x006423be, 0x0064dcaa, 0x00659557, 0x00664dc6, 0x006705f5,
0x0067bde5, 0x00687595, 0x00692d05, 0x0069e433, 0x006a9b21, 0x006b51cc, 0x006c0836, 0x006cbe5c,
0x006d7440, 0x006e29e0, 0x006edf3d, 0x006f9454, 0x00704927, 0x0070fdb5, 0x0071b1fd, 0x007265ff,
0x007319ba, 0x0073cd2f, 0x0074805c, 0x00753341, 0x0075e5dd, 0x00769831, 0x00774a3c, 0x0077fbfe,
0x0078ad75, 0x00795ea2, 0x007a0f84, 0x007ac01a, 0x007b7065, 0x007c2064, 0x007cd016, 0x007d7f7c,
0x007e2e93, 0x007edd5d, 0x007f8bd9, 0x00803a06, 0x0080e7e4, 0x00819573, 0x008242b1, 0x0082ef9f,
0x00839c3d, 0x00844889, 0x0084f484, 0x0085a02c, 0x00864b82, 0x0086f686, 0x0087a136, 0x00884b92,
0x0088f59b, 0x00899f4e, 0x008a48ad, 0x008af1b7, 0x008b9a6b, 0x008c42c9, 0x008cead0, 0x008d9281,
0x008e39da, 0x008ee0db, 0x008f8784, 0x00902dd5, 0x0090d3cd, 0x0091796b, 0x00921eb0, 0x0092c39a,
0x0093682a, 0x00940c5f, 0x0094b039, 0x009553b7, 0x0095f6d9, 0x0096999f, 0x00973c07, 0x0097de12,
0x00987fc0, 0x0099210f, 0x0099c200, 0x009a6293, 0x009b02c6, 0x009ba299, 0x009c420c, 0x009ce11f,
0x009d7fd1, 0x009e1e22, 0x009ebc12, 0x009f599f, 0x009ff6cb, 0x00a09393, 0x00a12ff9, 0x00a1cbfb,
0x00a26799, 0x00a302d3, 0x00a39da9, 0x00a4381a, 0x00a4d225, 0x00a56bcb, 0x00a6050a, 0x00a69de3,
0x00a73656, 0x00a7ce61, 0x00a86605, 0x00a8fd41, 0x00a99415, 0x00aa2a80, 0x00aac082, 0x00ab561b,
0x00abeb4a, 0x00ac800f, 0x00ad1469, 0x00ada859, 0x00ae3bde, 0x00aecef7, 0x00af61a5, 0x00aff3e6,
0x00b085bb, 0x00b11722, 0x00b1a81d, 0x00b238aa, 0x00b2c8c9, 0x00b3587a, 0x00b3e7bc, 0x00b4768f,
0x00b504f3, 0x00b592e7, 0x00b6206c, 0x00b6ad7f, 0x00b73a23, 0x00b7c655, 0x00b85216, 0x00b8dd65,
0x00b96842, 0x00b9f2ac, 0x00ba7ca4, 0x00bb0629, 0x00bb8f3b, 0x00bc17d9, 0x00bca003, 0x00bd27b8,
0x00bdaef9, 0x00be35c5, 0x00bebc1b, 0x00bf41fc, 0x00bfc767, 0x00c04c5c, 0x00c0d0da, 0x00c154e1,
0x00c1d870, 0x00c25b89, 0x00c2de29, 0x00c36051, 0x00c3e200, 0x00c46337, 0x00c4e3f5, 0x00c56439,
0x00c5e403, 0x00c66354, 0x00c6e22a, 0x00c76085, 0x00c7de65, 0x00c85bca, 0x00c8d8b3, 0x00c95521,
0x00c9d112, 0x00ca4c87, 0x00cac77f, 0x00cb41fa, 0x00cbbbf8, 0x00cc3578, 0x00ccae79, 0x00cd26fd,
0x00cd9f02, 0x00ce1689, 0x00ce8d90, 0x00cf0417, 0x00cf7a1f, 0x00cfefa8, 0x00d064af, 0x00d0d937,
0x00d14d3d, 0x00d1c0c2, 0x00d233c6, 0x00d2a649, 0x00d31849, 0x00d389c7, 0x00d3fac3, 0x00d46b3b,
0x00d4db31, 0x00d54aa4, 0x00d5b993, 0x00d627fe, 0x00d695e5, 0x00d70348, 0x00d77026, 0x00d7dc7f,
0x00d84853, 0x00d8b3a1, 0x00d91e6a, 0x00d988ad, 0x00d9f26a, 0x00da5ba0, 0x00dac450, 0x00db2c79,
0x00db941a, 0x00dbfb34, 0x00dc61c7, 0x00dcc7d1, 0x00dd2d53, 0x00dd924d, 0x00ddf6be, 0x00de5aa6,
0x00debe05, 0x00df20db, 0x00df8327, 0x00dfe4e9, 0x00e04621, 0x00e0a6cf, 0x00e106f2, 0x00e1668a,
0x00e1c598, 0x00e2241a, 0x00e28210, 0x00e2df7b, 0x00e33c5a, 0x00e398ac, 0x00e3f473, 0x00e44fac,
0x00e4aa59, 0x00e50479, 0x00e55e0b, 0x00e5b710, 0x00e60f88, 0x00e66771, 0x00e6becc, 0x00e71599,
0x00e76bd8, 0x00e7c187, 0x00e816a8, 0x00e86b39, 0x00e8bf3c, 0x00e912ae, 0x00e96591, 0x00e9b7e4,
0x00ea09a7, 0x00ea5ad9, 0x00eaab7b, 0x00eafb8c, 0x00eb4b0c, 0x00eb99fb, 0x00ebe858, 0x00ec3624,
0x00ec835e, 0x00ecd007, 0x00ed1c1d, 0x00ed67a1, 0x00edb293, 0x00edfcf2, 0x00ee46be, 0x00ee8ff8,
0x00eed89e, 0x00ef20b0, 0x00ef6830, 0x00efaf1b, 0x00eff573, 0x00f03b37, 0x00f08066, 0x00f0c501,
0x00f10908, 0x00f14c7a, 0x00f18f57, 0x00f1d19f, 0x00f21352, 0x00f25470, 0x00f294f8, 0x00f2d4eb,
0x00f31447, 0x00f3530e, 0x00f3913f, 0x00f3ced9, 0x00f40bdd, 0x00f4484b, 0x00f48422, 0x00f4bf62,
0x00f4fa0b, 0x00f5341d, 0x00f56d97, 0x00f5a67b, 0x00f5dec6, 0x00f6167a, 0x00f64d97, 0x00f6841b,
0x00f6ba07, 0x00f6ef5b, 0x00f72417, 0x00f7583a, 0x00f78bc5, 0x00f7beb7, 0x00f7f110, 0x00f822d1,
0x00f853f8, 0x00f88486, 0x00f8b47b, 0x00f8e3d6, 0x00f91298, 0x00f940c0, 0x00f96e4e, 0x00f99b43,
0x00f9c79d, 0x00f9f35e, 0x00fa1e84, 0x00fa4910, 0x00fa7302, 0x00fa9c59, 0x00fac516, 0x00faed37,
0x00fb14be, 0x00fb3bab, 0x00fb61fc, 0x00fb87b2, 0x00fbaccd, 0x00fbd14d, 0x00fbf531, 0x00fc187a,
0x00fc3b28, 0x00fc5d3a, 0x00fc7eb0, 0x00fc9f8a, 0x00fcbfc9, 0x00fcdf6c, 0x00fcfe73, 0x00fd1cdd,
0x00fd3aac, 0x00fd57de, 0x00fd7474, 0x00fd906e, 0x00fdabcc, 0x00fdc68c, 0x00fde0b1, 0x00fdfa38,
0x00fe1324, 0x00fe2b72, 0x00fe4323, 0x00fe5a38, 0x00fe70b0, 0x00fe868b, 0x00fe9bc9, 0x00feb069,
0x00fec46d, 0x00fed7d4, 0x00feea9d, 0x00fefcc9, 0x00ff0e58, 0x00ff1f49, 0x00ff2f9d, 0x00ff3f54,
0x00ff4e6d, 0x00ff5ce9, 0x00ff6ac7, 0x00ff7808, 0x00ff84ab, 0x00ff90b1, 0x00ff9c18, 0x00ffa6e3,
0x00ffb10f, 0x00ffba9e, 0x00ffc38f, 0x00ffcbe2, 0x00ffd397, 0x00ffdaaf, 0x00ffe129, 0x00ffe705,
0x00ffec43, 0x00fff0e3, 0x00fff4e6, 0x00fff84a, 0x00fffb11, 0x00fffd39, 0x00fffec4, 0x00ffffb1,
0x00ffffff,
};
#else
extern const int sf_sin_tab1[513] ;
#endif
#define SINE_INT_ZOOM 16384
#define SINE_INT_ZBIT 14
#define __int64 long long
/*软件索引实现sin生成*/
static int get_sine_value(int mx_idx)
{
int ret = 0;
int idx = 0;
int tm_idx = mx_idx & 0x1FFFFFF; //2^25
int phase = tm_idx & 0x3FFF;
int tp_idx0 = tm_idx >> 14;
int tp_idx1 = tp_idx0 + 1;
int sign = 1, dt0, dt1;
if (tp_idx0 > 1024) {
sign = -1;
tp_idx0 = 2048 - tp_idx0;
}
if (tp_idx0 < 513) {
dt0 = sf_sin_tab1[tp_idx0];
} else {
dt0 = sf_sin_tab1[1024 - tp_idx0];
}
if (tp_idx1 > 1024) {
sign = -1;
tp_idx1 = 2048 - tp_idx1;
}
if (tp_idx1 < 513) {
dt1 = sf_sin_tab1[tp_idx1];
} else {
dt1 = sf_sin_tab1[1024 - tp_idx1];
}
ret = ((__int64)dt0 * (SINE_INT_ZOOM - phase) + (__int64)dt1 * phase) >> SINE_INT_ZBIT;
ret *= sign;
return ret;
}
static void hw_sin_value(int a, int *sin_res, u8 precision)
{
u64 s64 = a;
*sin_res = __asm_sine(s64, precision);
}
int sin_tone_make(void *_maker, void *data, int len)
{
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
s16 *pcm = (s16 *)data;
int sin_value = 0;
int win_sin_value = 0;
int add_idx = 0, sub_vol = 0, win_add_idx = 0;
int offset = 0;
u8 id = maker->id;
u8 sin_num = maker->sin_num;
u8 repeat = maker->repeat;
u8 channel = maker->channel;
int sin_index;
int win_sin_index;
int volume;
u32 reamin_points = len / 2 / channel;
do {
if (maker->next_param) {
maker->volume = SINE_TOTAL_VOLUME;
maker->sin_index = 0;
maker->win_sin_index = 0;
maker->next_param = 0;
}
u8 win = maker->sin[id].win;
add_idx = ((u64)(1 << 25) * maker->sin[id].freq / DEFAULT_SINE_SAMPLE_RATE) >> 9;
if (win) {
win_add_idx = ((u64)(1 << 25) * maker->sin[id].decay / DEFAULT_SINE_SAMPLE_RATE) >> 9;
/*sub_vol = 0;*/
} else {
sub_vol = maker->sin[id].decay;
}
sin_index = maker->sin_index;
win_sin_index = maker->win_sin_index;
volume = maker->volume;
u32 points = 0;
if (maker->fade_points) {
points = maker->fade_points > reamin_points ? reamin_points : maker->fade_points;
sub_vol = 0;
maker->fade_points -= points;
} else {
points = maker->points > reamin_points ? reamin_points : maker->points;
maker->points -= points;
}
reamin_points -= points;
while (points--) {
/*hw_sin_value(sin_index, &sin_value, 0);*/
sin_value = __asm_sine((s64)sin_index, 2);
if (win) {
/*hw_sin_value(win_sin_index, &win_sin_value, 0);*/
win_sin_value = __asm_sine((s64)win_sin_index, 2);
#if ((defined CONFIG_CPU_BR36) || (defined CONFIG_CPU_BR28))
sin_value = ((s64)sin_value * (s64)win_sin_value) >> 44;
#else
sin_value = ((s64)sin_value * (s64)win_sin_value) >> 34;
#endif
win_sin_index += win_add_idx;
win_sin_index &= 0x1ffffff;
} else {
#if ((defined CONFIG_CPU_BR36) || (defined CONFIG_CPU_BR28))
sin_value = ((s64)volume * sin_value) >> 39;
#else
sin_value = ((s64)volume * sin_value) >> 34;
#endif
}
sin_index += add_idx;
sin_index &= 0x1ffffff;
volume -= sub_vol;
if (volume < 0) {
volume = 0;
}
*pcm++ = sin_value;
if (channel == 2) {
*pcm++ = sin_value;
} else if (channel == 4) {
*pcm++ = sin_value;
*pcm++ = sin_value;
*pcm++ = sin_value;
}
}
maker->volume = volume;
maker->sin_index = sin_index;
maker->win_sin_index = win_sin_index;
if (!maker->points) {
if (++id >= sin_num) {
if (!repeat) {
break;
}
id = 0;
}
maker->points = maker->sin[id].points;
maker->id = id;
maker->next_param = 1;
}
if (!reamin_points) {
break;
}
} while (1);
return len - (reamin_points * 2 * channel);
}
int sin_tone_points(void *_maker)
{
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
int points = 0;
u8 i = 0;
for (i = 0; i < maker->sin_num; i++) {
points += maker->sin[i].points;
}
return points;
}
void sin_tone_close(void *_maker)
{
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
#ifdef SINE_USE_MALLOC
if (maker) {
free(maker);
}
#else
if (sin_maker_handle.open) {
sin_maker_handle.open = 0;
}
#endif
}
#include "asm/math_fast_function.h"
#ifndef DATA16
#define DATA16 32767
#endif
/*********************************
* fc : 正弦波中心频率
* fs : 采样频率
* FrameSize :每次计算输出点数
* idx :当前计算起始indix
* rst :结果存放地址
* *******************************/
void SinWave_Generator(int fc, int fs, int FrameSize, int idx, short *rst)
{
float tmp0, tmp1, tmp2;
tmp0 = (float)fc / fs;
for (int i = 0; i < FrameSize; i++) {
tmp1 = (i + idx) * tmp0 * 2;
tmp2 = sin_float(tmp1);
*rst = (short)(tmp2 * DATA16);
rst++;
}
}
/*********************************
* fs : 采样频率
* FrameSize :每次计算输出点数
* idx :当前计算起始indix
* ts :期望一次扫频所持续时间
* rst :结果存放地址
* *******************************/
void SweepSin_Generator(int fs, int FrameSize, int idx, float ts, short *rst)
{
float fp, fc, tmp1, tmp2;
int Ncnt, NPoint, DPoint;
NPoint = fs * ts;
// fp = (fs/2)/(fs*ts);
fp = 1 / (2 * 2 * ts);
for (int i = 0; i < FrameSize; i++) {
Ncnt = (i + idx) / NPoint;
DPoint = (i + idx) - Ncnt * NPoint;
//printf("idx:%d \n",DPoint);
tmp1 = ((DPoint * fp) / fs) * DPoint * 2;
tmp2 = sin_float(tmp1);
//printf("Sin[%d]:%d",i,(int)(tmp2*1000));
*rst = (short)(tmp2 * DATA16);
rst++;
}
}
/*
*********************************************************************
* Description: 正弦信号生成
* Arguments : fc 信号中心频率
* fs 信号采样率
* buf 数据输出地址
* len 数据生成长度,单位是bytes
* Return : None.
* Note(s) : None.
*********************************************************************
*/
int sin_idx = 0;
void sin_pcm_fill(int fc, int fs, void *buf, u32 len)
{
SinWave_Generator(fc, fs, len / 2, sin_idx, buf);
sin_idx += len / 2;
}
/*
*********************************************************************
* Description: 扫频信号生成
* Arguments : fs 信号采样率
* buf 数据输出地址
* len 数据生成长度,单位是bytes
* Return : None.
* Note(s) : None.
*********************************************************************
*/
int sweep_sin_idx = 0;
void sweepsin_pcm_fill(int fs, void *buf, u32 len)
{
SweepSin_Generator(fs, len / 2, sweep_sin_idx, 25, buf);
sweep_sin_idx += len / 2;
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef __SINE_MAKE_H_
#define __SINE_MAKE_H_
#include "generic/typedef.h"
#define DEFAULT_SINE_SAMPLE_RATE 16000
#define SINE_TOTAL_VOLUME 26843546//16106128//20132660 //26843546
struct sin_param {
//int idx_increment;
int freq;
int points;
int win;
int decay;
};
int sin_tone_make(void *_maker, void *data, int len);
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat);
int sin_tone_points(void *_maker);
void sin_tone_close(void *_maker);
/*
*********************************************************************
* Description: 正弦信号生成
* Arguments : fc 信号中心频率
* fs 信号采样率
* buf 数据输出地址
* len 数据生成长度,单位是bytes
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void sin_pcm_fill(int fc, int fs, void *buf, u32 len);
/*
*********************************************************************
* Description: 扫频信号生成
* Arguments : fs 信号采样率
* buf 数据输出地址
* len 数据生成长度,单位是bytes
* Return : None.
* Note(s) : None.
*********************************************************************
*/
void sweepsin_pcm_fill(int fs, void *buf, u32 len);
#endif/*__SINE_MAKE_H_*/
+20
View File
@@ -0,0 +1,20 @@
#ifndef __STREAM_ENTRY_H__
#define __STREAM_ENTRY_H__
#include "system/includes.h"
#include "media/includes.h"
// struct __stream_entry;
struct __stream_entry {
u8 is_end;
void *data_priv;
int (*data_callback)(void *priv, struct audio_data_frame *in);
struct audio_stream_entry entry;
};
struct __stream_entry *stream_entry_open(void *priv, int (*data_callback)(void *priv, struct audio_data_frame *in), u8 is_end);
void stream_entry_close(struct __stream_entry **hdl);
void stream_entry_resume(struct __stream_entry *hdl);
#endif// __STREAM_ENTRY_H__
+129
View File
@@ -0,0 +1,129 @@
#include "app_config.h"
#ifdef AUDIO_PCM_DEBUG
#include "system/includes.h"
#include "asm/uart_dev.h"
#include "uartPcmSender.h"
static u8 uart_cbuf[32] __attribute__((aligned(4)));
const uart_bus_t *uart_bus = NULL;
//设备事件响应demo
void uart_event_handler(struct sys_event *e)
{
u8 uart_rxbuf[12] = {0};
u8 uart_txbuf[12] = {0};
const uart_bus_t *_uart_bus;
u32 uart_rxcnt = 0;
u8 i = 0;
if (0) {//!strcmp(e->arg, "uart_rx_overflow")) {
if (e->u.dev.event == DEVICE_EVENT_CHANGE) {
printf("uart event: %s\n", e->arg);
_uart_bus = (const uart_bus_t *)e->u.dev.value;
uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
if (uart_rxcnt) {
g_printf("rx:%s", uart_rxbuf);
}
}
}
if (0) { //(!strcmp(e->arg, "uart_rx_outtime")) {
if (e->u.dev.event == DEVICE_EVENT_CHANGE) {
printf("uart event: %s\n", e->arg);
_uart_bus = (const uart_bus_t *)e->u.dev.value;
uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
if (uart_rxcnt) {
printf("get_buffer:\n");
for (int i = 0; i < uart_rxcnt; i++) {
putbyte(uart_rxbuf[i]);
if (i % 16 == 15) {
putchar('\n');
}
}
if (uart_rxcnt % 16) {
putchar('\n');
}
_uart_bus->write(uart_rxbuf, uart_rxcnt);
}
printf("uart out\n");
}
}
}
SYS_EVENT_HANDLER(SYS_DEVICE_EVENT, uart_event_handler, 0);
void gpio_change(void *priv);
static void uart_isr_hook(void *arg, u32 status)
{
const uart_bus_t *ubus = arg;
struct sys_event e;
//当CONFIG_UARTx_ENABLE_TX_DMAx = 0, 1)为1时,不要在中断里面调用ubus->write(),因为中断不能pend信号量
if (status == UT_RX) {
printf("uart_rx_isr\n");
#if 1//(UART_DEV_USAGE_TEST_SEL == 1)
e.type = SYS_DEVICE_EVENT;
e.arg = "uart_rx_overflow";
e.u.dev.event = DEVICE_EVENT_CHANGE;
e.u.dev.value = (int)ubus;
sys_event_notify(&e);
#endif
}
if (status == UT_RX_OT) {
printf("uart_rx_ot_isr\n");
#if 1//(UART_DEV_USAGE_TEST_SEL == 1)
e.type = SYS_DEVICE_EVENT;
e.arg = "uart_rx_outtime";
e.u.dev.event = DEVICE_EVENT_CHANGE;
e.u.dev.value = (int)ubus;
sys_event_notify(&e);
#endif
}
if (status == UT_TX) {
/* putchar('T'); */
/* gpio_change(0); */
}
}
void uartSendData(void *buf, u16 len) //发送数据的接口。
{
if (uart_bus) {
uart_bus->write(buf, len); //把数据写到DMA
}
}
/* char *TickPage = "uart online"; */
/* void uartTickSend(void *priv){ */
/* if(uartTickSendFlag){ */
/* r_printf("sizeof:%d\n", sizeof(TickPage)); */
/* uartSendData(TickPage, sizeof(TickPage)); */
/* } */
/* } */
void uartSendInit()
{
struct uart_platform_data_t u_arg = {0};
u_arg.tx_pin = PCM_UART1_TX_PORT;
u_arg.rx_pin = PCM_UART1_RX_PORT;
u_arg.rx_cbuf = uart_cbuf;
u_arg.rx_cbuf_size = 32;
u_arg.frame_length = 6;
u_arg.rx_timeout = 100;
u_arg.isr_cbfun = uart_isr_hook;
u_arg.baud = PCM_UART1_BAUDRATE;
u_arg.is_9bit = 0;
r_printf("uart_dev_open() ...\n");
uart_bus = uart_dev_open(&u_arg);
r_printf("comming %s,%d\n", __func__, __LINE__);
if (uart_bus != NULL) {
r_printf("success\n");
gpio_set_hd(PCM_UART1_TX_PORT, 1);
gpio_set_hd0(PCM_UART1_TX_PORT, 1);
//os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task");
} else {
r_printf("false\n");
}
}
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef _UARTPCMSENDER_H_
#define _UARTPCMSENDER_H_
#include "system/includes.h"
#include "app_config.h"
/*
*串口导出数据配置
*注意IO口设置不要和普通log输出uart冲突
*/
#define PCM_UART1_TX_PORT IO_PORT_DM /*数据导出发送IO*/
#define PCM_UART1_RX_PORT -1
#define PCM_UART1_BAUDRATE 2000000 /*数据导出波特率,不用修改,和接收端设置一直*/
#if ((TCFG_UART0_ENABLE == ENABLE_THIS_MOUDLE) && (PCM_UART1_TX_PORT == TCFG_UART0_TX_PORT))
//IO口配置冲突,请检查修改
#error "PCM_UART1_TX_PORT conflict with TCFG_UART0_TX_PORT"
#endif/*PCM_UART1_TX_PORT*/
void uartSendInit(); //串口发数初始化
void uartSendData(void *buf, u16 len); //发送数据的接口
#endif /*_UARTPCMSENDER_H_*/