生成代码包
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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_*/
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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*/
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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*/
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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*/
|
||||
@@ -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_*/
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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_*/
|
||||
@@ -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
|
||||
|
||||
@@ -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*/
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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_*/
|
||||
@@ -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__
|
||||
|
||||
@@ -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_DMA(x = 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
|
||||
@@ -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_*/
|
||||
Reference in New Issue
Block a user