first
This commit is contained in:
180
apps/common/audio/amplitude_statistic.c
Normal file
180
apps/common/audio/amplitude_statistic.c
Normal file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
****************************************************************
|
||||
* Amplitude Statistics
|
||||
* 幅值统计模块
|
||||
* File : amplitude_statistic.c
|
||||
* By :
|
||||
* Notes :
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
#include "amplitude_statistic.h"
|
||||
|
||||
#if 0
|
||||
#define amplitude_log printf
|
||||
#else
|
||||
#define amplitude_log(...)
|
||||
#endif/*log_en*/
|
||||
|
||||
static const unsigned short am_va_tab[] = {
|
||||
32768, 29205, 26029, 23198, 20675, 18427, 16423, 14637, 13045, 11627, 10362, 9235, 8231, 7336, 6538, 5827,
|
||||
5193, 4629, 4125, 3677, 3277, 2920, 2603, 2320, 2068, 1843, 1642, 1464, 1305, 1163, 1036, 0
|
||||
};
|
||||
|
||||
static const int rms_va_tab[] = {
|
||||
134217728, 106612931, 84685661, 67268212, 53433040, 42443372, 33713969, 26779957, 21272076, 16897011,
|
||||
13421773, 10661293, 8468566, 6726821, 5343304, 4244337, 3371397, 2677996, 2127208, 1689701,
|
||||
1342177, 1066129, 846857, 672682, 534330, 424434, 337140, 267800, 212721, 168970,
|
||||
134218, 0
|
||||
};
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Loudness meter init
|
||||
* Description: 响度计算初始化
|
||||
* Arguments : loud_obj
|
||||
* sr
|
||||
* print_dest
|
||||
* index
|
||||
* Return : NULL
|
||||
* Note(s) : NULL
|
||||
*********************************************************************
|
||||
*/
|
||||
void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index)
|
||||
{
|
||||
memset(loud_obj, 0, sizeof(LOUDNESS_M_STRUCT));
|
||||
loud_obj->countperiod = sr / 50;
|
||||
loud_obj->inv_counterpreiod = 16777216 / loud_obj->countperiod;
|
||||
loud_obj->print_dest = print_dest;
|
||||
loud_obj->index = index;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Loudness meter short
|
||||
* Description: 响度计算函数
|
||||
* Arguments : loud_obj
|
||||
* data
|
||||
* len
|
||||
* Return : NULL
|
||||
* Note(s) : NULL
|
||||
*********************************************************************
|
||||
*/
|
||||
void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len)
|
||||
{
|
||||
int i;
|
||||
int loudness_val = 0;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
int tmp = data[i] * 256;
|
||||
loud_obj->dclevel = (loud_obj->dclevel * 511 + tmp) >> 9;
|
||||
|
||||
int xabs = (data[i] > 0) ? data[i] : (-data[i]);
|
||||
int xabs2 = (xabs * xabs) >> 10;
|
||||
loud_obj->rms += xabs2;
|
||||
loud_obj->maxval = (loud_obj->maxval > xabs) ? loud_obj->maxval : xabs;
|
||||
|
||||
if (xabs >= 32767) {
|
||||
loud_obj->errprintfcount0++;
|
||||
}
|
||||
|
||||
loud_obj->counti++;
|
||||
if (loud_obj->counti > loud_obj->countperiod) {
|
||||
if (loud_obj->maxval_print < loud_obj->maxval) {
|
||||
loud_obj->maxval_print = loud_obj->maxval;
|
||||
}
|
||||
|
||||
if (loud_obj->rms_print < loud_obj->rms) {
|
||||
loud_obj->rms_print = loud_obj->rms;
|
||||
}
|
||||
|
||||
loud_obj->counti = 0;
|
||||
loud_obj->maxval = 0;
|
||||
loud_obj->rms = 0;
|
||||
|
||||
if (loud_obj->errprintfcount0 > 2) {
|
||||
loud_obj->errprintfcount0 = 0;
|
||||
amplitude_log("[%d]overflow occur... \n", loud_obj->index);
|
||||
}
|
||||
|
||||
loud_obj->print_cnt++;
|
||||
|
||||
if (loud_obj->print_cnt >= loud_obj->print_dest) {
|
||||
|
||||
int rmsval = ((__int64)loud_obj->rms_print * (__int64)loud_obj->inv_counterpreiod) >> (24 - (10 - 3));
|
||||
|
||||
if (rmsval > 25837266) {
|
||||
amplitude_log("[%d]energy high... \n", loud_obj->index);
|
||||
}
|
||||
|
||||
{
|
||||
int compi = 0, found = 0;;
|
||||
while (compi < 31) {
|
||||
if (rmsval >= rms_va_tab[compi]) {
|
||||
// float upval = (0 - compi) * 0.5;
|
||||
// float dwonval = (0 - compi - 1) * 0.5;
|
||||
// amplitude_log("rms level: %f to %f dB\n", upval, dwonval);
|
||||
|
||||
int upval = (0 - compi);
|
||||
int dwonval = (0 - compi - 1);
|
||||
|
||||
amplitude_log("[%d]rms level: %d to %d dB\n", loud_obj->index, upval, dwonval);
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
compi++;
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
amplitude_log("[%d]rms level < -30dB \n", loud_obj->index);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
int compi = 0, found = 0;;
|
||||
while (compi < 31) {
|
||||
if (loud_obj->maxval_print >= am_va_tab[compi]) {
|
||||
// float upval = (0 - compi) * 0.5;
|
||||
// float dwonval = (0 - compi - 1) * 0.5;
|
||||
// amplitude_log("peak level: %f to %f dB\n", upval, dwonval);
|
||||
int upval = (0 - compi);
|
||||
int dwonval = (0 - compi - 1);
|
||||
loud_obj->peak_val = dwonval;
|
||||
amplitude_log("[%d]peak level: %d to %d dB\n", loud_obj->index, upval, dwonval);
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
compi++;
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
loud_obj->peak_val = -31;
|
||||
amplitude_log("[%d]peak level < -30dB \n", loud_obj->index);
|
||||
}
|
||||
}
|
||||
|
||||
loud_obj->print_cnt = 0;
|
||||
loud_obj->maxval_print = 0;
|
||||
loud_obj->rms_print = 0;
|
||||
|
||||
if (loud_obj->dclevel > (255 * 256)) {
|
||||
amplitude_log("[%d] why ??? dc level : %d \n", loud_obj->index, loud_obj->dclevel >> 8);
|
||||
}
|
||||
amplitude_log("\n\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
void loudness_meter_demo(void)
|
||||
{
|
||||
loudness_meter_init(&loudness_adc, 16000, 1);
|
||||
loudness_meter_short(&loudness_adc, datain, points);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
26
apps/common/audio/amplitude_statistic.h
Normal file
26
apps/common/audio/amplitude_statistic.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef _AMPLITUDE_STATISTIC_H_
|
||||
#define _AMPLITUDE_STATISTIC_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
typedef struct _LOUDNESS_M_STRUCT_ {
|
||||
int mutecnt;
|
||||
int rms;
|
||||
int counti;
|
||||
int maxval;
|
||||
int countperiod;
|
||||
int inv_counterpreiod;
|
||||
int errprintfcount0;
|
||||
short print_cnt;
|
||||
short print_dest;
|
||||
int dclevel;
|
||||
int rms_print;
|
||||
int maxval_print;
|
||||
int peak_val;
|
||||
u8 index;
|
||||
} LOUDNESS_M_STRUCT;
|
||||
|
||||
void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index);
|
||||
void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len);
|
||||
|
||||
#endif /*_AMPLITUDE_STATISTIC_H_*/
|
||||
13
apps/common/audio/audio_NoiseGate.h
Normal file
13
apps/common/audio/audio_NoiseGate.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _AUDIO_NOISE_GATE_H_
|
||||
#define _AUDIO_NOISE_GATE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
|
||||
u8 *audio_noise_gate_open(int attack_time, int release_time, float thr, float gain, int sr, int ch);
|
||||
|
||||
void audio_noise_gate_run(u8 *runbuf, void *in, void *out, u16 len);
|
||||
|
||||
void audio_noise_gate_close(u8 *runbuf);
|
||||
|
||||
#endif/*_AUDIO_NOISE_GATE_H_*/
|
||||
79
apps/common/audio/audio_digital_vol.h
Normal file
79
apps/common/audio/audio_digital_vol.h
Normal file
@ -0,0 +1,79 @@
|
||||
#ifndef _AUDIO_DIGITAL_VOL_H_
|
||||
#define _AUDIO_DIGITAL_VOL_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "os/os_type.h"
|
||||
#include "os/os_api.h"
|
||||
#include "generic/list.h"
|
||||
|
||||
#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/
|
||||
|
||||
typedef struct {
|
||||
u8 toggle; /*数字音量开关*/
|
||||
u8 fade; /*淡入淡出标志*/
|
||||
u8 vol; /*淡入淡出当前音量(level)*/
|
||||
u8 vol_max; /*淡入淡出最大音量(level)*/
|
||||
s16 vol_fade; /*淡入淡出对应的起始音量*/
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
s16 vol_bk; /*后台自动淡出前音量值*/
|
||||
struct list_head entry;
|
||||
#endif
|
||||
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
|
||||
volatile u16 fade_step; /*淡入淡出的步进*/
|
||||
} dvol_handle;
|
||||
|
||||
|
||||
int audio_digital_vol_init(void);
|
||||
void audio_digital_vol_bg_fade(u8 fade_out);
|
||||
dvol_handle *audio_digital_vol_open(u8 vol, u8 vol_max, u16 fade_step);
|
||||
void audio_digital_vol_close(dvol_handle *dvol);
|
||||
void audio_digital_vol_set(dvol_handle *dvol, u8 vol);
|
||||
u8 audio_digital_vol_get(void);
|
||||
int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len);
|
||||
void audio_digital_vol_reset_fade(dvol_handle *dvol);
|
||||
|
||||
/*************************自定义支持重入的数字音量调节****************************/
|
||||
void *user_audio_digital_volume_open(u8 vol, u8 vol_max, u16 fade_step);
|
||||
int user_audio_digital_volume_close(void *_d_volume);
|
||||
u8 user_audio_digital_volume_get(void *_d_volume);
|
||||
int user_audio_digital_volume_set(void *_d_volume, u8 vol);
|
||||
int user_audio_digital_volume_reset_fade(void *_d_volume);
|
||||
int user_audio_digital_volume_run(void *_d_volume, void *data, u32 len, u8 ch_num);
|
||||
void user_audio_digital_handler_run(void *_d_volume, void *data, u32 len);
|
||||
void user_audio_digital_set_volume_tab(void *_d_volume, u16 *user_vol_tab, u8 user_vol_max);
|
||||
|
||||
void *user_audio_process_open(void *parm, void *priv, void (*handler)(void *priv, void *data, int len, u8 ch_num));
|
||||
int user_audio_process_close(void *_uparm_hdl);
|
||||
void user_audio_process_handler_run(void *_uparm_hdl, void *data, u32 len, u8 ch_num);
|
||||
|
||||
struct user_audio_digital_parm {
|
||||
u8 en;
|
||||
u8 vol;
|
||||
u8 vol_max;
|
||||
u16 fade_step;
|
||||
};
|
||||
|
||||
struct digital_volume {
|
||||
u8 toggle; /*数字音量开关*/
|
||||
u8 fade; /*淡入淡出标志*/
|
||||
u8 vol; /*淡入淡出当前音量*/
|
||||
u8 vol_max; /*淡入淡出最大音量*/
|
||||
s16 vol_fade; /*淡入淡出对应的起始音量*/
|
||||
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
|
||||
volatile u16 fade_step; /*淡入淡出的步进*/
|
||||
|
||||
OS_MUTEX mutex;
|
||||
u8 ch_num;
|
||||
void *priv;
|
||||
u8 user_vol_max; /*自定义音量表级数*/
|
||||
volatile s16 *user_vol_tab; /*自定义音量表*/
|
||||
|
||||
};
|
||||
|
||||
struct user_audio_parm {
|
||||
void *priv;
|
||||
void (*handler)(void *priv, void *data, int len, u8 ch_num);/*用户自定义回调处理*/
|
||||
struct digital_volume *dvol_hdl;
|
||||
};
|
||||
|
||||
#endif
|
||||
450
apps/common/audio/audio_dvol.c
Normal file
450
apps/common/audio/audio_dvol.c
Normal file
@ -0,0 +1,450 @@
|
||||
/*
|
||||
****************************************************************
|
||||
* AUDIO DIGITAL VOLUME
|
||||
* File : audio_dvol.c
|
||||
* By :
|
||||
* Notes : 数字音量模块,支持多通道音量控制
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
#include "audio_dvol.h"
|
||||
|
||||
#if 0
|
||||
#define dvol_log y_printf
|
||||
#else
|
||||
#define dvol_log(...)
|
||||
#endif
|
||||
|
||||
#define DIGITAL_FADE_EN 1
|
||||
#define DIGITAL_FADE_STEP 4
|
||||
|
||||
#define BG_DVOL_MAX 14
|
||||
#define BG_DVOL_MID 10
|
||||
#define BG_DVOL_MIN 6
|
||||
#define BG_DVOL_MAX_FADE 13 /*>= BG_DVOL_MAX:自动淡出BG_DVOL_MAX_FADE*/
|
||||
#define BG_DVOL_MID_FADE 9 /*>= BG_DVOL_MID:自动淡出BG_DVOL_MID_FADE*/
|
||||
#define BG_DVOL_MIN_FADE 5 /*>= BG_DVOL_MIN:自动淡出BG_DVOL_MIN_FADE*/
|
||||
|
||||
#define ASM_ENABLE 1
|
||||
#define L_sat(b,a) __asm__ volatile("%0=sat16(%1)(s)":"=&r"(b) : "r"(a));
|
||||
#define L_sat32(b,a,n) __asm__ volatile("%0=%1>>%2(s)":"=&r"(b) : "r"(a),"r"(n));
|
||||
|
||||
typedef struct {
|
||||
u8 bg_dvol_fade_out;
|
||||
u8 start;
|
||||
OS_MUTEX mutex;
|
||||
struct list_head dvol_head;
|
||||
} dvol_t;
|
||||
static dvol_t dvol_attr;
|
||||
|
||||
/*
|
||||
*数字音量级数 DEFAULT_DIGITAL_VOL_MAX
|
||||
*数组长度 DEFAULT_DIGITAL_VOL_MAX + 1
|
||||
*/
|
||||
#define DEFAULT_DIGITAL_VOL_MAX (31)
|
||||
const u16 default_dig_vol_table[DEFAULT_DIGITAL_VOL_MAX + 1] = {
|
||||
0 , //0
|
||||
93 , //1
|
||||
111 , //2
|
||||
132 , //3
|
||||
158 , //4
|
||||
189 , //5
|
||||
226 , //6
|
||||
270 , //7
|
||||
323 , //8
|
||||
386 , //9
|
||||
462 , //10
|
||||
552 , //11
|
||||
660 , //12
|
||||
789 , //13
|
||||
943 , //14
|
||||
1127, //15
|
||||
1347, //16
|
||||
1610, //17
|
||||
1925, //18
|
||||
2301, //19
|
||||
2751, //20
|
||||
3288, //21
|
||||
3930, //22
|
||||
4698, //23
|
||||
5616, //24
|
||||
6713, //25
|
||||
8025, //26
|
||||
9592, //27
|
||||
11466,//28
|
||||
15200,//29
|
||||
16000,//30
|
||||
16384 //31
|
||||
};
|
||||
|
||||
static u16 digital_vol_max = DEFAULT_DIGITAL_VOL_MAX;
|
||||
static u16 *dig_vol_table = default_dig_vol_table;
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Init
|
||||
* Description: 数字音量模块初始化
|
||||
* Arguments : None.
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_digital_vol_init(u16 *vol_table, u16 vol_max)
|
||||
{
|
||||
memset(&dvol_attr, 0, sizeof(dvol_attr));
|
||||
INIT_LIST_HEAD(&dvol_attr.dvol_head);
|
||||
os_mutex_create(&dvol_attr.mutex);
|
||||
|
||||
if (vol_table != NULL) {
|
||||
dig_vol_table = vol_table;
|
||||
digital_vol_max = vol_max;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*背景音乐淡出使能*/
|
||||
void audio_digital_vol_bg_fade(u8 fade_out)
|
||||
{
|
||||
dvol_log("audio_digital_vol_bg_fade:%d", fade_out);
|
||||
dvol_attr.bg_dvol_fade_out = fade_out;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Open
|
||||
* Description: 数字音量模块打开
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* vol 当前数字音量等级
|
||||
* vol_max 最大数字音量等级
|
||||
* fade_step 淡入淡出步进
|
||||
* vol_limit 数字音量限制,即可以给vol_max等分的最大音量
|
||||
* Return : 数字音量通道句柄
|
||||
* Note(s) : fade_step一般不超过两级数字音量的最小差值
|
||||
* (1)通话如果用数字音量,一般步进小一点,音量调节的时候不会有杂音
|
||||
* (2)淡出的时候可以快一点,尽快淡出到0
|
||||
*********************************************************************
|
||||
*/
|
||||
dvol_handle *audio_digital_vol_open(u8 dvol_idx, u8 vol, u8 vol_max, u16 fade_step, char vol_limit)
|
||||
{
|
||||
dvol_log("dvol_open:%d-%d-%d-%d\n", vol, vol_max, fade_step, vol_limit);
|
||||
dvol_handle *dvol = NULL;
|
||||
dvol = zalloc(sizeof(dvol_handle));
|
||||
if (dvol) {
|
||||
u8 vol_level;
|
||||
dvol->fade = DIGITAL_FADE_EN;
|
||||
dvol->vol = (vol > vol_max) ? vol_max : vol;
|
||||
if (vol > vol_max) {
|
||||
printf("[warning]cur digital_vol(%d) > digital_vol_max(%d)!!", vol, vol_max);
|
||||
}
|
||||
dvol->vol_max = vol_max;
|
||||
if (vol_limit == -1) {
|
||||
dvol->vol_limit = digital_vol_max;
|
||||
} else {
|
||||
dvol->vol_limit = (vol_limit > digital_vol_max) ? digital_vol_max : vol_limit;
|
||||
}
|
||||
vol_level = dvol->vol * dvol->vol_limit / vol_max;
|
||||
dvol->vol_target = dig_vol_table[vol_level];
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
dvol->fade_step = fade_step;
|
||||
dvol->toggle = 1;
|
||||
dvol->idx = dvol_idx;
|
||||
local_irq_disable();
|
||||
list_add(&dvol->entry, &dvol_attr.dvol_head);
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
dvol->vol_bk = -1;
|
||||
if (dvol_attr.bg_dvol_fade_out) {
|
||||
dvol_handle *hdl;
|
||||
list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) {
|
||||
if ((hdl != dvol) && (hdl->idx)) {
|
||||
hdl->vol_bk = hdl->vol;
|
||||
if (hdl->vol >= BG_DVOL_MAX) {
|
||||
hdl->vol -= BG_DVOL_MAX_FADE;
|
||||
} else if (hdl->vol >= BG_DVOL_MID) {
|
||||
hdl->vol -= BG_DVOL_MID_FADE;
|
||||
} else if (hdl->vol >= BG_DVOL_MIN) {
|
||||
hdl->vol -= BG_DVOL_MIN_FADE;
|
||||
} else {
|
||||
hdl->vol_bk = -1;
|
||||
continue;
|
||||
}
|
||||
u8 vol_level = hdl->vol * dvol->vol_limit / hdl->vol_max;
|
||||
hdl->vol_target = dig_vol_table[vol_level];
|
||||
//y_printf("bg_dvol fade_out:%x,vol_bk:%d,vol_set:%d,tartget:%d",hdl,hdl->vol_bk,hdl->vol,hdl->vol_target);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif/*BG_DVOL_FADE_ENABLE*/
|
||||
local_irq_enable();
|
||||
dvol_log("dvol_open[%x]:%x-%d-%d-%d\n", dvol_idx, dvol, dvol->vol, dvol->vol_max, fade_step);
|
||||
}
|
||||
return dvol;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Close
|
||||
* Description: 数字音量模块关闭
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_digital_vol_close(u8 dvol_idx)
|
||||
{
|
||||
dvol_log("dvol_close[%x]\n", dvol_idx);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_log("dvol_close[%x]:%x", dvol_idx, dvol);
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dvol_valid == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dvol) {
|
||||
local_irq_disable();
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
dvol_handle *hdl;
|
||||
list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) {
|
||||
if ((hdl != dvol) && (hdl->vol_bk >= 0)) {
|
||||
//y_printf("bg_dvol fade_in:%x,%d",hdl,hdl->vol_bk);
|
||||
hdl->vol = hdl->vol_bk;
|
||||
u8 vol_level = hdl->vol_bk * dvol->vol_limit / hdl->vol_max;
|
||||
hdl->vol_target = dig_vol_table[vol_level];
|
||||
hdl->vol_bk = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
list_del(&dvol->entry);
|
||||
free(dvol);
|
||||
dvol = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Get
|
||||
* Description: 数字音量获取
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* Return : 对应的数字音量通道的当前音量等级.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_digital_vol_get(u8 dvol_idx)
|
||||
{
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if (dvol && dvol_valid) {
|
||||
return dvol->vol;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Set
|
||||
* Description: 数字音量设置
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* vol 目标音量等级
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_digital_vol_set(u8 dvol_idx, u8 vol)
|
||||
{
|
||||
dvol_log("audio_digital_vol set:%d,%d\n", dvol_idx, vol);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_log("dvol_set[%x]:%x", dvol_idx, dvol);
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if ((dvol == NULL) || (dvol_valid == 0)) {
|
||||
return;
|
||||
}
|
||||
if (dvol->toggle == 0) {
|
||||
return;
|
||||
}
|
||||
dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol;
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
if (dvol->vol_bk != -1) {
|
||||
dvol->vol_bk = vol;
|
||||
}
|
||||
#endif
|
||||
dvol->fade = DIGITAL_FADE_EN;
|
||||
u8 vol_level = dvol->vol * dvol->vol_limit / dvol->vol_max;
|
||||
dvol->vol_target = dig_vol_table[vol_level];
|
||||
dvol_log("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target);
|
||||
}
|
||||
/*********************************************************************
|
||||
* Audio Digital Volume Set
|
||||
* Description: 数字音量设置,设置数字音量的当前值,不用淡入淡出
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* vol 目标音量等级
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
|
||||
void audio_digital_vol_set_no_fade(u8 dvol_idx, u8 vol)
|
||||
{
|
||||
dvol_log("audio_digital_vol set:%d,%d\n", dvol_idx, vol);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_log("dvol_set[%x]:%x", dvol_idx, dvol);
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if ((dvol == NULL) || (dvol_valid == 0)) {
|
||||
return;
|
||||
}
|
||||
if (dvol->toggle == 0) {
|
||||
return;
|
||||
}
|
||||
dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol;
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
if (dvol->vol_bk != -1) {
|
||||
dvol->vol_bk = vol;
|
||||
}
|
||||
#endif
|
||||
dvol->fade = DIGITAL_FADE_EN;
|
||||
u8 vol_level = dvol->vol * dvol->vol_limit / dvol->vol_max;
|
||||
dvol->vol_fade = dig_vol_table[vol_level];
|
||||
dvol_log("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target);
|
||||
}
|
||||
|
||||
void audio_digital_vol_reset_fade(u8 dvol_idx)
|
||||
{
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_valid = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
if (dvol && dvol_valid) {
|
||||
dvol->vol_fade = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Volume Process
|
||||
* Description: 数字音量运算核心
|
||||
* Arguments : dvol_idx 数字音量通道索引,详见audio_dvol.h宏定义
|
||||
* data 待运算数据
|
||||
* len 待运算数据长度
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
/*rounding处理*/
|
||||
#define MUL32_PSHIFT(x,y,s) (((x) * (y) + (1 << ((s)-1))) >> (s))
|
||||
|
||||
int audio_digital_vol_run(u8 dvol_idx, void *data, u32 len)
|
||||
{
|
||||
s32 valuetemp;
|
||||
s16 *buf;
|
||||
|
||||
os_mutex_pend(&dvol_attr.mutex, 0);
|
||||
dvol_handle *dvol = NULL;
|
||||
u8 dvol_valid = 0;
|
||||
local_irq_disable();
|
||||
list_for_each_entry(dvol, &dvol_attr.dvol_head, entry) {
|
||||
if (dvol && (dvol->idx == dvol_idx)) {
|
||||
dvol_valid = 1;
|
||||
#if 0
|
||||
static dvol_handle *last_dvol = NULL;
|
||||
if (last_dvol != dvol) {
|
||||
dvol_log("dvol_run[%x]:%x", dvol_idx, dvol);
|
||||
last_dvol = dvol;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
local_irq_enable();
|
||||
|
||||
if ((dvol->toggle == 0) || (dvol_valid == 0)) {
|
||||
os_mutex_post(&dvol_attr.mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buf = data;
|
||||
len >>= 1; //byte to point
|
||||
|
||||
for (u32 i = 0; i < len; i += 2) {
|
||||
///left channel
|
||||
if (dvol->fade) {
|
||||
if (dvol->vol_fade > dvol->vol_target) {
|
||||
dvol->vol_fade -= dvol->fade_step;
|
||||
if (dvol->vol_fade < dvol->vol_target) {
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
}
|
||||
} else if (dvol->vol_fade < dvol->vol_target) {
|
||||
dvol->vol_fade += dvol->fade_step;
|
||||
if (dvol->vol_fade > dvol->vol_target) {
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dvol->vol_fade = dvol->vol_target;
|
||||
}
|
||||
|
||||
valuetemp = buf[i];
|
||||
if (valuetemp < 0) {
|
||||
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
|
||||
valuetemp = -valuetemp;
|
||||
/*rounding处理(加入0.5),减少小信号时候的误差和谐波幅值*/
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
valuetemp = -valuetemp;
|
||||
} else {
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
}
|
||||
/*饱和处理*/
|
||||
buf[i] = (s16)data_sat_s16(valuetemp);
|
||||
|
||||
///right channel
|
||||
valuetemp = buf[i + 1];
|
||||
if (valuetemp < 0) {
|
||||
/*负数先转换成正数,运算完再转换回去,是为了避免负数右移位引入1的误差,增加底噪*/
|
||||
valuetemp = -valuetemp;
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
valuetemp = -valuetemp;
|
||||
} else {
|
||||
valuetemp = (valuetemp * dvol->vol_fade + (1 << 13)) >> 14 ;
|
||||
}
|
||||
/*饱和处理*/
|
||||
buf[i + 1] = (s16)data_sat_s16(valuetemp);
|
||||
}
|
||||
os_mutex_post(&dvol_attr.mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
55
apps/common/audio/audio_dvol.h
Normal file
55
apps/common/audio/audio_dvol.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef _AUDIO_DVOL_H_
|
||||
#define _AUDIO_DVOL_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "os/os_type.h"
|
||||
#include "os/os_api.h"
|
||||
#include "generic/list.h"
|
||||
|
||||
#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/
|
||||
|
||||
/*Digital Volume Channel*/
|
||||
#define MUSIC_DVOL 0xA1
|
||||
#define CALL_DVOL 0xA2
|
||||
#define TONE_DVOL 0xA3
|
||||
#define HEARING_DVOL 0xA4
|
||||
|
||||
/*Digital Volume Fade Step*/
|
||||
#define MUSIC_DVOL_FS 2
|
||||
#define CALL_DVOL_FS 4
|
||||
#define TONE_DVOL_FS 30
|
||||
#define HEARING_DVOL_FS 2
|
||||
|
||||
/*Digital Volume Max Level*/
|
||||
#define MUSIC_DVOL_MAX 16
|
||||
#define CALL_DVOL_MAX 15
|
||||
#define TONE_DVOL_MAX 16
|
||||
#define HEARING_DVOL_MAX 16
|
||||
|
||||
typedef struct {
|
||||
u8 toggle; /*数字音量开关*/
|
||||
u8 fade; /*淡入淡出标志*/
|
||||
u8 vol; /*淡入淡出当前音量(level)*/
|
||||
u8 vol_max; /*淡入淡出最大音量(level)*/
|
||||
char vol_limit; /*最大数字音量限制*/
|
||||
u8 idx; /*数字音量通道索引*/
|
||||
s16 vol_fade; /*淡入淡出对应的起始音量*/
|
||||
#if BG_DVOL_FADE_ENABLE
|
||||
s16 vol_bk; /*后台自动淡出前音量值*/
|
||||
#endif/*BG_DVOL_FADE_ENABLE*/
|
||||
struct list_head entry;
|
||||
volatile s16 vol_target; /*淡入淡出对应的目标音量*/
|
||||
volatile u16 fade_step; /*淡入淡出的步进*/
|
||||
} dvol_handle;
|
||||
|
||||
int audio_digital_vol_init(u16 *vol_table, u16 vol_max);
|
||||
void audio_digital_vol_bg_fade(u8 fade_out);
|
||||
dvol_handle *audio_digital_vol_open(u8 dvol_idx, u8 vol, u8 vol_max, u16 fade_step, char vol_limit);
|
||||
void audio_digital_vol_close(u8 dvol_idx);
|
||||
void audio_digital_vol_set(u8 dvol_idx, u8 vol);
|
||||
int audio_digital_vol_get(u8 dvol_idx);
|
||||
int audio_digital_vol_run(u8 dvol_idx, void *data, u32 len);
|
||||
void audio_digital_vol_reset_fade(u8 dvol_idx);
|
||||
void audio_digital_vol_set_no_fade(u8 dvol_idx, u8 vol);
|
||||
|
||||
#endif/*_AUDIO_DVOL_H_*/
|
||||
140
apps/common/audio/audio_export_demo.c
Normal file
140
apps/common/audio/audio_export_demo.c
Normal file
@ -0,0 +1,140 @@
|
||||
#include "app_config.h"
|
||||
#ifdef AUDIO_PCM_DEBUG
|
||||
#include "uartPcmSender.h"
|
||||
|
||||
extern int aec_uart_init();
|
||||
extern int aec_uart_fill(u8 ch, void *buf, u16 size);
|
||||
extern void aec_uart_write(void);
|
||||
extern int aec_uart_close(void);
|
||||
|
||||
/*
|
||||
16k 正选波 pcm 数据
|
||||
*/
|
||||
static short const sin0_16k[16] = {
|
||||
0x0000, 0x30fd, 0x5a83, 0x7641, 0x7fff, 0x7642, 0x5a82, 0x30fc, 0x0000, 0xcf04, 0xa57d, 0x89be, 0x8000, 0x89be, 0xa57e, 0xcf05,
|
||||
};
|
||||
static u16 tx1_s_cnt = 0;
|
||||
static int get_sine0_data(u16 *s_cnt, s16 *data, u16 points, u8 ch)
|
||||
{
|
||||
while (points--) {
|
||||
if (*s_cnt >= 16) {
|
||||
*s_cnt = 0;
|
||||
}
|
||||
*data++ = sin0_16k[*s_cnt] / 2;
|
||||
if (ch == 2) {
|
||||
*data++ = sin0_16k[*s_cnt] / 2;
|
||||
}
|
||||
(*s_cnt)++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*************************************************************
|
||||
* uart data export 接口使用说明
|
||||
* 1、每个通道一次只能固定发送512byte数据,数据不够会被丢弃
|
||||
* 2、aec_uart_write()一次会发送3个通道的数据,没有填数的通道会发送空白数据
|
||||
* 3、UART DMA发送一次数据需要约8ms时间,两次发数间隔需 > 8ms
|
||||
* 4、发送波特率、发送引脚在 uartPcmSender.h 配置
|
||||
* 5、该接口的接收端需使用JL的串口导出工具接收数据
|
||||
*
|
||||
*************************************************************
|
||||
*/
|
||||
void audio_export_demo_task(void *param)
|
||||
{
|
||||
printf("audio_export_demo_task\n");
|
||||
s16 data[256];
|
||||
int len = 512;
|
||||
/*生成256个点的16k的正选波数据*/
|
||||
get_sine0_data(&tx1_s_cnt, data, len / 2, 1);
|
||||
|
||||
while (1) {
|
||||
putchar('.');
|
||||
|
||||
{
|
||||
/*run code*/
|
||||
}
|
||||
|
||||
aec_uart_fill(0, data, 512); //往通道0填数据
|
||||
|
||||
{
|
||||
/*run code*/
|
||||
}
|
||||
|
||||
aec_uart_fill(1, data, 512); //往通道1填数据
|
||||
|
||||
{
|
||||
/*run code*/
|
||||
}
|
||||
|
||||
aec_uart_fill(2, data, 512); //往通道2填数据
|
||||
aec_uart_write(); //一次把3路数据发送出去
|
||||
os_time_dly(2); //等待发送完成,发送一次要8ms,发完才可以进行下一次发数
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
**********************************************************
|
||||
* uart data export 接口使用示例
|
||||
*********************************************************
|
||||
*/
|
||||
int audio_export_demo_init()
|
||||
{
|
||||
printf("audio_export_demo_init\n");
|
||||
/* uartSendInit(); //串口初始化,已经在开机时调用初始化,这里不需调用 */
|
||||
aec_uart_init(); //uart export 初始化
|
||||
os_task_create(audio_export_demo_task, NULL, 1, 1024, 128, "audio_export_task");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*************************************************************
|
||||
* 通用 uart 发数接口(uartSendData())使用说明
|
||||
* 1、发数的数据长度可以根据需要修改
|
||||
* 2、一般发送512byte,DMA模式需要2.7ms
|
||||
* 3、发送波特率、发送引脚在 uartPcmSender.h 配置
|
||||
* 4、可以使用该接口自定义发数方式、协议等
|
||||
*
|
||||
*************************************************************
|
||||
*/
|
||||
void audio_uart_transmit_demo_task(void *param)
|
||||
{
|
||||
printf("audio_uart_transmit_demo_task\n");
|
||||
s16 data[256];
|
||||
int len = 512;
|
||||
/*生成256个点的16k的正选波数据*/
|
||||
get_sine0_data(&tx1_s_cnt, data, len / 2, 1);
|
||||
|
||||
while (1) {
|
||||
putchar('.');
|
||||
uartSendData(data, len); //uart 发送数据接口
|
||||
os_time_dly(1); //一般发送512byte,DMA模式需要2.7ms
|
||||
}
|
||||
}
|
||||
/*
|
||||
**********************************************************
|
||||
* 通用uart发数使用示例
|
||||
*********************************************************
|
||||
*/
|
||||
int audio_uart_transmit_demo_init()
|
||||
{
|
||||
printf("audio_uart_transmit_demo_init\n");
|
||||
/* uartSendInit(); //串口初始化,已经在开机时调用初始化,这里不需调用 */
|
||||
os_task_create(audio_uart_transmit_demo_task, NULL, 1, 1024, 128, "audio_uart_transmit_task");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 audio_export_demo_idle_query()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
REGISTER_LP_TARGET(audio_export_demo_lp_target) = {
|
||||
.name = "audio_export__demo",
|
||||
.is_idle = audio_export_demo_idle_query,
|
||||
};
|
||||
|
||||
#endif /*AUDIO_PCM_DEBUG*/
|
||||
|
||||
126
apps/common/audio/audio_noise_gate.c
Normal file
126
apps/common/audio/audio_noise_gate.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
******************************************************************
|
||||
* Limiter_NoiseGate Module(限幅器/噪声门限模块)
|
||||
*1. Limiter:限制最大幅度
|
||||
*2. NoiseGate:
|
||||
*(1)启动时间
|
||||
*(2)释放时间
|
||||
*(3)噪声阈值
|
||||
*(4)噪声增益
|
||||
*3. Usage:
|
||||
*(1)LIMITER_THR:限幅器参数,限制信号的最大值
|
||||
*(2)LIMITER_NOISE_GATE:噪声门限的阈值,配合LIMITER_NOISE_GAIN使用
|
||||
*(3)LIMITER_NOISE_GAIN:当信号小于噪声门限LIMITER_NOISE_GATE的时候
|
||||
*信号增益为LIMITER_NOISE_GAIN,范围是0到1,增益0为静音,增益1为直通
|
||||
*效果。噪声门限用来优化声音的底噪
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "os/os_api.h"
|
||||
#include "limiter_noiseGate_api.h"
|
||||
#include "audio_noise_gate.h"
|
||||
|
||||
|
||||
//#define NG_LOG_ENABLE
|
||||
#ifdef NG_LOG_ENABLE
|
||||
#define NG_LOG y_printf
|
||||
#else
|
||||
#define NG_LOG(...)
|
||||
#endif/*NG_LOG_ENABLE*/
|
||||
|
||||
/*限幅器上限*/
|
||||
#define LIMITER_THR -10000 /*-12000 = -12dB,放大1000倍,(-10000参考)*/
|
||||
/*小于CONST_NOISE_GATE的当成噪声处理,防止清0近端声音*/
|
||||
#define LIMITER_NOISE_GATE -40000 /*-12000 = -12dB,放大1000倍,(-40000参考)*/
|
||||
/*低于噪声门限阈值的增益 */
|
||||
#define LIMITER_NOISE_GAIN (0 << 30) /*(0~1)*2^30*/
|
||||
|
||||
enum {
|
||||
NG_STA_CLOSE = 0,
|
||||
NG_STA_OPEN,
|
||||
NG_STA_RUN,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u8 state;
|
||||
OS_MUTEX mutex;
|
||||
u8 *run_buf;
|
||||
} audio_noise_gate_t;
|
||||
audio_noise_gate_t NoiseGate;
|
||||
|
||||
int audio_noise_gate_open(u16 sample_rate, int limiter_thr, int noise_gate, int noise_gain)
|
||||
{
|
||||
NG_LOG("audio_noise_gate_open");
|
||||
NoiseGate.run_buf = malloc(need_limiter_noiseGate_buf(1));
|
||||
NG_LOG("Limiter_noisegate_buf size:%d\n", need_limiter_noiseGate_buf(1));
|
||||
if (NoiseGate.run_buf) {
|
||||
//限幅器启动因子 int32(exp(-0.65/(16000 * 0.005))*2^30) 16000为采样率 0.005 为启动时间(s)
|
||||
int limiter_attfactor = 1065053018;
|
||||
//限幅器释放因子 int32(exp(-0.15/(16000 * 0.1))*2^30) 16000为采样率 0.1 为释放时间(s)
|
||||
int limiter_relfactor = 1073641165;
|
||||
//限幅器阈值(mdb)
|
||||
//int limiter_threshold = CONST_LIMITER_THR;
|
||||
|
||||
//噪声门限启动因子 int32(exp(-1/(16000 * 0.1))*2^30) 16000为采样率 0.1 为启动时间(s)
|
||||
/*
|
||||
*import math
|
||||
*int(math.exp(-1.0/(16000*0.1))*2**30)
|
||||
*/
|
||||
int noiseGate_attfactor = 1073070945;
|
||||
//噪声门限释放因子 int32(exp(-1/(16000 * 0.005))*2^30) 16000为采样率 0.005 为释放时间(s)
|
||||
int noiseGate_relfactor = 1060403589;
|
||||
//噪声门限(mdb)
|
||||
//int noiseGate_threshold = -25000;
|
||||
//低于噪声门限阈值的增益 (0~1)*2^30
|
||||
//int noise
|
||||
//Gate_low_thr_gain = 0 << 30;
|
||||
|
||||
if (sample_rate == 8000) {
|
||||
limiter_attfactor = 1056434522;
|
||||
limiter_relfactor = 1073540516;
|
||||
noiseGate_attfactor = 1072400485;
|
||||
noiseGate_relfactor = 1047231044;
|
||||
}
|
||||
|
||||
limiter_noiseGate_init(NoiseGate.run_buf,
|
||||
limiter_attfactor,
|
||||
limiter_relfactor,
|
||||
noiseGate_attfactor,
|
||||
noiseGate_relfactor,
|
||||
limiter_thr,
|
||||
noise_gate,
|
||||
noise_gain,
|
||||
sample_rate, 1);
|
||||
os_mutex_create(&NoiseGate.mutex);
|
||||
NoiseGate.state = NG_STA_OPEN;
|
||||
NG_LOG("audio_noise_gate_open succ");
|
||||
return 0;
|
||||
}
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
void audio_noise_gate_run(void *in, void *out, u16 len)
|
||||
{
|
||||
if (NoiseGate.state == NG_STA_CLOSE) {
|
||||
return;
|
||||
}
|
||||
os_mutex_pend(&NoiseGate.mutex, 0);
|
||||
if (NoiseGate.run_buf) {
|
||||
limiter_noiseGate_run(NoiseGate.run_buf, in, out, len / 2);
|
||||
}
|
||||
os_mutex_post(&NoiseGate.mutex);
|
||||
}
|
||||
|
||||
void audio_noise_gate_close()
|
||||
{
|
||||
NG_LOG("audio_noise_gate_close");
|
||||
os_mutex_pend(&NoiseGate.mutex, 0);
|
||||
NoiseGate.state = NG_STA_CLOSE;
|
||||
if (NoiseGate.run_buf) {
|
||||
free(NoiseGate.run_buf);
|
||||
}
|
||||
os_mutex_post(&NoiseGate.mutex);
|
||||
NG_LOG("audio_noise_gate_close succ");
|
||||
}
|
||||
|
||||
11
apps/common/audio/audio_noise_gate.h
Normal file
11
apps/common/audio/audio_noise_gate.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef _AUDIO_LIMITER_NOISE_GATE_H_
|
||||
#define _AUDIO_LIMITER_NOISE_GATE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
|
||||
int audio_noise_gate_open(u16 sample_rate, int limiter_thr, int noise_gate, int noise_gain);
|
||||
void audio_noise_gate_run(void *in, void *out, u16 len);
|
||||
void audio_noise_gate_close();
|
||||
|
||||
#endif/*_AUDIO_NOISE_GATE_H_*/
|
||||
112
apps/common/audio/audio_ns.c
Normal file
112
apps/common/audio/audio_ns.c
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
******************************************************************
|
||||
* Noise Suppress Module(降噪模块)
|
||||
*Notes:
|
||||
*(1)支持降噪的数据采样率:8k/16k
|
||||
*(2)增加多5k左右代码
|
||||
*(3)内存消耗跟数据采样率有关,具体可通过以下接口查询:
|
||||
* int ns_mem_size = noise_suppress_mem_query(&ans->ns_para);
|
||||
******************************************************************
|
||||
*/
|
||||
|
||||
#include "audio_ns.h"
|
||||
|
||||
#ifdef CONFIG_MEDIA_NEW_ENABLE
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* NoiseSuppress Process
|
||||
* Description: 降噪处理主函数
|
||||
* Arguments : ns 降噪句柄
|
||||
* in 输入数据
|
||||
* out 输出数据
|
||||
* len 输入数据长度
|
||||
* Return : 降噪输出长度
|
||||
* Note(s) : 由于降噪是固定处理帧长的,所以如果输入数据长度不是降噪
|
||||
* 帧长整数倍,则某一次会输出0长度,即没有输出
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_run(audio_ns_t *ns, short *in, short *out, u16 len)
|
||||
{
|
||||
if (ns == NULL) {
|
||||
return len;
|
||||
}
|
||||
#if 0
|
||||
int wlen = cbuf_write(&ns->cbuf, in, len);
|
||||
if (wlen != len) {
|
||||
printf("ns_cbuf full\n");
|
||||
}
|
||||
if (ns->cbuf.data_len >= NS_FRAME_SIZE) {
|
||||
cbuf_read(&ns->cbuf, out, NS_FRAME_SIZE);
|
||||
putchar('.');
|
||||
noise_suppress_run(out, out, NS_FRAME_POINTS);
|
||||
return NS_FRAME_SIZE;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
//putchar('.');
|
||||
int nOut = noise_suppress_run(in, out, (len / 2));
|
||||
return (nOut << 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Open
|
||||
* Description: 初始化降噪模块
|
||||
* Arguments : sr 数据采样率
|
||||
* mode 降噪模式(0,1,2:越大越耗资源,效果越好)
|
||||
* NoiseLevel 初始噪声水平(评估初始噪声,加快收敛)
|
||||
* AggressFactor 降噪强度(越大越强:1~2)
|
||||
* MinSuppress 降噪最小压制(越小越强:0~1)
|
||||
* Return : 降噪模块句柄
|
||||
* Note(s) : (1)采样率只支持8k、16k
|
||||
* (2)如果内存不足,可以考虑wideband强制为0,即只做窄带降噪
|
||||
* ans-ns_para.wideband = 0;
|
||||
*********************************************************************
|
||||
*/
|
||||
audio_ns_t *audio_ns_open(u16 sr, u8 mode, float NoiseLevel, float AggressFactor, float MinSuppress)
|
||||
{
|
||||
audio_ns_t *ans = zalloc(sizeof(audio_ns_t));
|
||||
//cbuf_init(&ans->cbuf, ans->in, sizeof(ans->in));
|
||||
|
||||
ans->ns_para.wideband = (sr == 16000) ? 1 : 0;
|
||||
ans->ns_para.mode = mode;
|
||||
ans->ns_para.NoiseLevel = NoiseLevel;
|
||||
ans->ns_para.AggressFactor = AggressFactor;
|
||||
ans->ns_para.MinSuppress = MinSuppress;
|
||||
printf("ns wideband:%d\n", ans->ns_para.wideband);
|
||||
//int ns_mem_size = noise_suppress_mem_query(&ans->ns_para);
|
||||
//printf("ns mem_size:%d\n", ns_mem_size);
|
||||
noise_suppress_open(&ans->ns_para);
|
||||
float lowcut = -60.f;
|
||||
noise_suppress_config(NS_CMD_LOWCUTTHR, 0, &lowcut);
|
||||
float noise_floor = -60.f;
|
||||
noise_suppress_config(NS_CMD_NOISE_FLOOR, 0, &noise_floor);
|
||||
printf("audio_ns_open ok\n");
|
||||
return ans;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Close
|
||||
* Description: 关闭降噪模块
|
||||
* Arguments : ns 降噪模块句柄
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_close(audio_ns_t *ns)
|
||||
{
|
||||
noise_suppress_close();
|
||||
if (ns) {
|
||||
free(ns);
|
||||
ns = NULL;
|
||||
}
|
||||
printf("esco_ans_close ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*CONFIG_MEDIA_NEW_ENABLE*/
|
||||
|
||||
61
apps/common/audio/audio_ns.h
Normal file
61
apps/common/audio/audio_ns.h
Normal file
@ -0,0 +1,61 @@
|
||||
#ifndef _AUDIO_NOISE_SUPPRESS_H_
|
||||
#define _AUDIO_NOISE_SUPPRESS_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "generic/circular_buf.h"
|
||||
#include "commproc_ns.h"
|
||||
|
||||
/*降噪数据帧长(单位:点数)*/
|
||||
#define NS_FRAME_POINTS 160
|
||||
#define NS_FRAME_SIZE (NS_FRAME_POINTS << 1)
|
||||
/*降噪输出buf长度*/
|
||||
#define NS_OUT_POINTS_MAX (NS_FRAME_POINTS << 1)
|
||||
|
||||
typedef struct {
|
||||
//s16 in[512];
|
||||
//cbuffer_t cbuf;
|
||||
noise_suppress_param ns_para;
|
||||
} audio_ns_t;
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Open
|
||||
* Description: 初始化降噪模块
|
||||
* Arguments : sr 数据采样率
|
||||
* mode 降噪模式(0,1,2:越大越耗资源,效果越好)
|
||||
* NoiseLevel 初始噪声水平(评估初始噪声,加快收敛)
|
||||
* AggressFactor 降噪强度(越大越强:1~2)
|
||||
* MinSuppress 降噪最小压制(越小越强:0~1)
|
||||
* Return : 降噪模块句柄
|
||||
* Note(s) : 采样率只支持8k、16k
|
||||
*********************************************************************
|
||||
*/
|
||||
audio_ns_t *audio_ns_open(u16 sr, u8 mode, float NoiseLevel, float AggressFactor, float MinSuppress);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* NoiseSuppress Process
|
||||
* Description: 降噪处理主函数
|
||||
* Arguments : ns 降噪句柄
|
||||
* in 输入数据
|
||||
* out 输出数据
|
||||
* len 输入数据长度
|
||||
* Return : 降噪输出长度
|
||||
* Note(s) : 由于降噪是固定处理帧长的,所以如果输入数据长度不是降噪
|
||||
* 帧长整数倍,则某一次会输出0长度,即没有输出
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_run(audio_ns_t *ns, short *in, short *out, u16 len);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Noise Suppress Close
|
||||
* Description: 关闭降噪模块
|
||||
* Arguments : ns 降噪模块句柄
|
||||
* Return : 0 成功 其他 失败
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_ns_close(audio_ns_t *ns);
|
||||
|
||||
#endif/*_AUDIO_NOISE_SUPPRESS_H_*/
|
||||
138
apps/common/audio/audio_plc.c
Normal file
138
apps/common/audio/audio_plc.c
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
************************************************************
|
||||
*/
|
||||
#include "system/includes.h"
|
||||
#include "PLC.h"
|
||||
#include "os/os_api.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
|
||||
#if TCFG_ESCO_PLC
|
||||
|
||||
//#define AUDIO_PLC_LOG_ENABLE
|
||||
#ifdef AUDIO_PLC_LOG_ENABLE
|
||||
#define PLC_LOG y_printf
|
||||
#else
|
||||
#define PLC_LOG(...)
|
||||
#endif/*AUDIO_PLC_LOG_ENABLE*/
|
||||
|
||||
enum {
|
||||
PLC_STA_CLOSE = 0,
|
||||
PLC_STA_OPEN,
|
||||
PLC_STA_RUN,
|
||||
};
|
||||
|
||||
|
||||
#define PLC_FRAME_LEN 120
|
||||
typedef struct {
|
||||
u8 state;
|
||||
u8 repair;
|
||||
u8 wideband;
|
||||
OS_MUTEX mutex;
|
||||
s16 *run_buf;
|
||||
} audio_plc_t;
|
||||
static audio_plc_t plc;
|
||||
|
||||
int audio_plc_open(u16 sr)
|
||||
{
|
||||
PLC_LOG("audio_plc_open:%d\n", sr);
|
||||
memset((u8 *)&plc, 0, sizeof(audio_plc_t));
|
||||
plc.run_buf = malloc(PLC_query()); /*buf_size:1040*/
|
||||
PLC_LOG("PLC_buf:%x,size:%d\n", plc.run_buf, PLC_query());
|
||||
if (plc.run_buf) {
|
||||
s8 err = PLC_init(plc.run_buf);
|
||||
if (err) {
|
||||
PLC_LOG("PLC_init err:%d", err);
|
||||
free(plc.run_buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
os_mutex_create(&plc.mutex);
|
||||
if (sr == 16000) {
|
||||
plc.wideband = 1;
|
||||
}
|
||||
plc.state = PLC_STA_OPEN;
|
||||
}
|
||||
PLC_LOG("audio_plc_open succ\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_plc_run(s16 *data, u16 len, u8 repair)
|
||||
{
|
||||
u16 repair_point, tmp_point;
|
||||
s16 *p_in, *p_out;
|
||||
p_in = data;
|
||||
p_out = data;
|
||||
tmp_point = len / 2;
|
||||
u8 repair_flag = 0;
|
||||
|
||||
os_mutex_pend(&plc.mutex, 0);
|
||||
if (plc.state == PLC_STA_CLOSE) {
|
||||
os_mutex_post(&plc.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0 //debug
|
||||
static u16 repair_cnt = 0;
|
||||
if (repair) {
|
||||
repair_cnt++;
|
||||
y_printf("[E%d]", repair_cnt);
|
||||
} else {
|
||||
repair_cnt = 0;
|
||||
}
|
||||
//printf("[%d]",point);
|
||||
#endif/*debug*/
|
||||
|
||||
repair_flag = repair;
|
||||
if (plc.wideband) {
|
||||
/*
|
||||
*msbc plc deal
|
||||
*如果上一帧是错误,则当前帧也要修复
|
||||
*/
|
||||
if (plc.repair) {
|
||||
repair_flag = 1;
|
||||
}
|
||||
plc.repair = repair;
|
||||
}
|
||||
|
||||
while (tmp_point) {
|
||||
repair_point = (tmp_point > PLC_FRAME_LEN) ? PLC_FRAME_LEN : tmp_point;
|
||||
tmp_point = tmp_point - repair_point;
|
||||
PLC_run(p_in, p_out, repair_point, repair_flag);
|
||||
p_in += repair_point;
|
||||
p_out += repair_point;
|
||||
}
|
||||
os_mutex_post(&plc.mutex);
|
||||
}
|
||||
|
||||
int audio_plc_close(void)
|
||||
{
|
||||
PLC_LOG("audio_plc_close\n");
|
||||
os_mutex_pend(&plc.mutex, 0);
|
||||
plc.state = PLC_STA_CLOSE;
|
||||
if (plc.run_buf) {
|
||||
free(plc.run_buf);
|
||||
plc.run_buf = NULL;
|
||||
}
|
||||
os_mutex_post(&plc.mutex);
|
||||
PLC_LOG("audio_plc_close succ\n");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
int audio_plc_open(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_plc_run(s16 *dat, u16 len, u8 repair_flag)
|
||||
{
|
||||
}
|
||||
|
||||
int audio_plc_close()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif/*TCFG_ESCO_PLC*/
|
||||
10
apps/common/audio/audio_plc.h
Normal file
10
apps/common/audio/audio_plc.h
Normal file
@ -0,0 +1,10 @@
|
||||
#ifndef _AUDIO_PLC_H_
|
||||
#define _AUDIO_PLC_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
int audio_plc_open(u16 sr);
|
||||
void audio_plc_run(s16 *dat, u16 len, u8 repair_flag);
|
||||
int audio_plc_close(void);
|
||||
|
||||
#endif/*_AUDIO_PLC_H_*/
|
||||
28
apps/common/audio/audio_utils.c
Normal file
28
apps/common/audio/audio_utils.c
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
************************************************************
|
||||
* Audio Utils
|
||||
*Brief:数字信号处理常用模块合集
|
||||
*Notes:
|
||||
************************************************************
|
||||
*/
|
||||
|
||||
#include "audio_utils.h"
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Phase Inverter
|
||||
* Description: 数字反相器,用来反转数字音频信号的相位
|
||||
* Arguments : dat 数据buf地址
|
||||
* len 数据长度(unit:byte)
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void digital_phase_inverter_s16(s16 *dat, int len)
|
||||
{
|
||||
int data_size = len / 2;
|
||||
for (int i = 0; i < data_size; i++) {
|
||||
dat[i] = (dat[i] == -32768) ? 32767 : -dat[i];
|
||||
}
|
||||
}
|
||||
|
||||
18
apps/common/audio/audio_utils.h
Normal file
18
apps/common/audio/audio_utils.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef _AUDIO_UTILS_H_
|
||||
#define _AUDIO_UTILS_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Digital Phase Inverter
|
||||
* Description: 数字反相器,用来反转数字音频信号的相位
|
||||
* Arguments : dat 数据buf地址
|
||||
* len 数据长度(unit:byte)
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void digital_phase_inverter_s16(s16 *dat, int len);
|
||||
|
||||
#endif/*_AUDIO_UTILS_H_*/
|
||||
707
apps/common/audio/decode/audio_key_tone.c
Normal file
707
apps/common/audio/decode/audio_key_tone.c
Normal file
@ -0,0 +1,707 @@
|
||||
#include "asm/includes.h"
|
||||
#include "media/includes.h"
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
/* #include "audio_dec.h" */
|
||||
#include "application/audio_dec_app.h"
|
||||
#include "tone_player.h"
|
||||
#include "sine_make.h"
|
||||
|
||||
#if TCFG_KEY_TONE_EN
|
||||
|
||||
// 按键提示音任务名
|
||||
#define AUDIO_KEY_TONE_TASK_NAME "key_tone"
|
||||
|
||||
// 按键提示音数字音量控制
|
||||
#if (SYS_DIGVOL_GROUP_EN && defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
#define AUDIO_KEY_TONE_DIGVOL_EN 0
|
||||
#define AUDIO_KEY_TONE_DIGVOL_NAME "key_tone"
|
||||
#else
|
||||
#define AUDIO_KEY_TONE_DIGVOL_EN 0
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* 使用audio_dec_app.h里面的接口,可以实现普通文件、正弦波文件、正弦波数组播放
|
||||
*/
|
||||
|
||||
// 参数
|
||||
struct __key_tone_play_info {
|
||||
const char *file_name; // 文件名
|
||||
struct audio_sin_param *sin; // 正弦波数组
|
||||
u8 sin_num; // 正弦波数组长度
|
||||
u8 preemption; // 1-抢占,0-叠加
|
||||
void (*evt_handler)(void *priv, int flag); // 事件回调
|
||||
void *evt_priv; // 事件回调私有句柄
|
||||
};
|
||||
|
||||
// 按键提示音
|
||||
struct __key_tone {
|
||||
volatile u8 busy; // 任务工作中
|
||||
volatile u8 start; // 运行标志
|
||||
volatile u8 play;
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
u8 volume; // 音量
|
||||
#endif
|
||||
struct __key_tone_play_info play_info; // 输入参数
|
||||
struct audio_dec_sine_app_hdl *dec_sin; // 文件播放句柄
|
||||
struct audio_dec_file_app_hdl *dec_file; // sine播放句柄
|
||||
void (*evt_handler)(void *priv, int flag); // 事件回调
|
||||
void *evt_priv; // 事件回调私有句柄
|
||||
const char *evt_owner; // 事件回调所在任务
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern struct audio_mixer mixer;
|
||||
|
||||
static struct __key_tone *key_tone = NULL;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Get File Ext Name
|
||||
* Description: 获取文件名后缀
|
||||
* Arguments : *name 文件名
|
||||
* Return : 后缀
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static char *get_file_ext_name(char *name)
|
||||
{
|
||||
int len = strlen(name);
|
||||
char *ext = (char *)name;
|
||||
|
||||
while (len--) {
|
||||
if (*ext++ == '.') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (len <= 0) {
|
||||
ext = name + (strlen(name) - 3);
|
||||
}
|
||||
|
||||
return ext;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Post Event
|
||||
* Description: 解码事件
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* end_flag 结束标志
|
||||
* Return : true 成功
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_event_handler(struct __key_tone *ktone, u8 end_flag)
|
||||
{
|
||||
int argv[4];
|
||||
if (!ktone->evt_handler) {
|
||||
log_i("evt_handler null\n");
|
||||
return false;
|
||||
}
|
||||
argv[0] = (int)ktone->evt_handler;
|
||||
argv[1] = 2;
|
||||
argv[2] = (int)ktone->evt_priv;
|
||||
argv[3] = (int)end_flag; //0正常关闭,1被打断关闭
|
||||
|
||||
int ret = os_taskq_post_type(ktone->evt_owner, Q_CALLBACK, 4, argv);
|
||||
if (ret) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Reelease
|
||||
* Description: 提示音解码器释放
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_dec_hdl_release(struct __key_tone *ktone)
|
||||
{
|
||||
if (ktone->dec_file) {
|
||||
audio_dec_file_app_close(ktone->dec_file);
|
||||
ktone->dec_file = NULL;
|
||||
}
|
||||
if (ktone->dec_sin) {
|
||||
audio_dec_sine_app_close(ktone->dec_sin);
|
||||
ktone->dec_sin = NULL;
|
||||
}
|
||||
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
app_audio_state_exit(APP_AUDIO_STATE_WTONE);
|
||||
#endif
|
||||
/* clock_remove_set(DEC_TONE_CLK); */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Init OK
|
||||
* Description: 解码初始化完成
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_dec_hdl_init_ok(struct __key_tone *ktone)
|
||||
{
|
||||
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
if (audio_mixer_get_ch_num(&mixer) <= 1) {
|
||||
#ifdef TCFG_WTONT_ONCE_VOL
|
||||
extern u8 get_tone_once_vol(void);
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol());
|
||||
#else
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol());
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
/* clock_add_set(DEC_TONE_CLK); */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Close
|
||||
* Description: 关闭提示音解码
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_play_close(struct __key_tone *ktone)
|
||||
{
|
||||
/* log_i("ktone:0x%x, sin:0x%x, file:0x%x \n", ktone, ktone->dec_file, ktone->dec_file); */
|
||||
if (ktone->dec_file || ktone->dec_sin) {
|
||||
key_tone_dec_hdl_release(ktone);
|
||||
key_tone_dec_event_handler(ktone, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Event Callback
|
||||
* Description: 解码回调处理
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* event 事件
|
||||
* *param 事件参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_app_evt_cb(struct __key_tone *ktone, enum audio_dec_app_event event, int *param)
|
||||
{
|
||||
switch (event) {
|
||||
case AUDIO_DEC_APP_EVENT_START_INIT_OK:
|
||||
log_i("key_tone start init ok\n");
|
||||
key_tone_dec_hdl_init_ok(ktone);
|
||||
break;
|
||||
case AUDIO_DEC_APP_EVENT_PLAY_END:
|
||||
log_i("key_tone play end\n");
|
||||
key_tone_dec_hdl_release(ktone);
|
||||
key_tone_dec_event_handler(ktone, 0);
|
||||
break;
|
||||
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
case AUDIO_DEC_APP_EVENT_STREAM_OPEN: {
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param;
|
||||
void *dvol_entry = NULL;
|
||||
audio_dig_vol_param temp_digvol_param = {
|
||||
.vol_start = ktone->volume,//get_max_sys_vol(),
|
||||
.vol_max = get_max_sys_vol(),
|
||||
.ch_total = audio_output_channel_num(),
|
||||
.fade_en = 0,
|
||||
.fade_points_step = 5,
|
||||
.fade_gain_step = 10,
|
||||
.vol_list = NULL,
|
||||
};
|
||||
dvol_entry = sys_digvol_group_ch_open(AUDIO_KEY_TONE_DIGVOL_NAME, -1, &temp_digvol_param);
|
||||
(entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry;
|
||||
#endif // SYS_DIGVOL_GROUP_EN
|
||||
}
|
||||
break;
|
||||
|
||||
case AUDIO_DEC_APP_EVENT_STREAM_CLOSE: {
|
||||
}
|
||||
break;
|
||||
|
||||
#endif /*#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)*/
|
||||
|
||||
case AUDIO_DEC_APP_EVENT_DEC_CLOSE:
|
||||
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
sys_digvol_group_ch_close(AUDIO_KEY_TONE_DIGVOL_NAME);
|
||||
#endif // SYS_DIGVOL_GROUP_EN
|
||||
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Sin Event Callback
|
||||
* Description: sine提示音解码回调
|
||||
* Arguments : *priv 私有句柄
|
||||
* event 事件
|
||||
* *param 事件参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
|
||||
{
|
||||
struct audio_dec_sine_app_hdl *sine_dec = priv;
|
||||
struct __key_tone *ktone = sine_dec->priv;
|
||||
switch (event) {
|
||||
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
|
||||
if (sine_dec->sin_maker) {
|
||||
break;
|
||||
}
|
||||
audio_dec_sine_app_probe(sine_dec);
|
||||
if (!sine_dec->sin_maker) {
|
||||
return -ENOENT;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
return key_tone_dec_app_evt_cb(ktone, event, param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone File Event Callback
|
||||
* Description: file提示音解码回调
|
||||
* Arguments : *priv 私有句柄
|
||||
* event 事件
|
||||
* *param 事件参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param)
|
||||
{
|
||||
struct audio_dec_file_app_hdl *file_dec = priv;
|
||||
struct __key_tone *ktone = file_dec->priv;
|
||||
switch (event) {
|
||||
case AUDIO_DEC_APP_EVENT_DEC_PROBE:
|
||||
break;
|
||||
default :
|
||||
return key_tone_dec_app_evt_cb(ktone, event, param);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Run
|
||||
* Description: 按键提示音运行
|
||||
* Arguments : *ktone 按键提示音解码句柄
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int key_tone_play_run(struct __key_tone *ktone)
|
||||
{
|
||||
if (!ktone->start) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct __key_tone_play_info info = {0};
|
||||
local_irq_disable();
|
||||
if (!ktone->play) {
|
||||
local_irq_enable();
|
||||
return 0;
|
||||
}
|
||||
// 保存播放参数
|
||||
memcpy(&info, &ktone->play_info, sizeof(struct __key_tone_play_info));
|
||||
ktone->play = 0;
|
||||
local_irq_enable();
|
||||
|
||||
// 关闭现有play
|
||||
key_tone_play_close(ktone);
|
||||
|
||||
// 设置参数
|
||||
ktone->evt_handler = info.evt_handler;
|
||||
ktone->evt_priv = info.evt_priv;
|
||||
ktone->evt_owner = "app_core";
|
||||
|
||||
// 正弦波数组播放
|
||||
if (info.sin && info.sin_num) {
|
||||
ktone->dec_sin = audio_dec_sine_app_create_by_parm(info.sin, info.sin_num, !info.preemption);
|
||||
if (ktone->dec_sin == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
|
||||
ktone->dec_sin->priv = ktone;
|
||||
/* audio_dec_sine_app_open(ktone->dec_sin); */
|
||||
ktone->dec_sin->dec->wait.only_del = 1;
|
||||
audio_dec_app_start(ktone->dec_sin->dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 判断文件名后缀
|
||||
u8 file_name[16];
|
||||
char *format = NULL;
|
||||
FILE *file = fopen(info.file_name, "r");
|
||||
if (!file) {
|
||||
return -1;
|
||||
}
|
||||
fget_name(file, file_name, 16);
|
||||
format = get_file_ext_name((char *)file_name);
|
||||
fclose(file);
|
||||
|
||||
// 正弦波文件播放
|
||||
if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) {
|
||||
ktone->dec_sin = audio_dec_sine_app_create(info.file_name, !info.preemption);
|
||||
if (ktone->dec_sin == NULL) {
|
||||
return -1;
|
||||
}
|
||||
ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb;
|
||||
ktone->dec_sin->priv = ktone;
|
||||
/* audio_dec_sine_app_open(ktone->dec_sin); */
|
||||
ktone->dec_sin->dec->wait.only_del = 1;
|
||||
audio_dec_app_start(ktone->dec_sin->dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 普通文件播放
|
||||
ktone->dec_file = audio_dec_file_app_create(info.file_name, !info.preemption);
|
||||
if (ktone->dec_file == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (ktone->dec_file->dec->dec_type == AUDIO_CODING_SBC) {
|
||||
audio_dec_app_set_frame_info(ktone->dec_file->dec, 0x4e, ktone->dec_file->dec->dec_type);
|
||||
}
|
||||
ktone->dec_file->dec->evt_cb = key_tone_dec_file_app_evt_cb;
|
||||
ktone->dec_file->priv = ktone;
|
||||
/* audio_dec_file_app_open(ktone->dec_file); */
|
||||
ktone->dec_file->dec->wait.only_del = 1;
|
||||
audio_dec_app_start(ktone->dec_file->dec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Task Run
|
||||
* Description: 按键提示音任务处理
|
||||
* Arguments : *p 按键提示音解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static void key_tone_task_deal(void *p)
|
||||
{
|
||||
int res = 0;
|
||||
int msg[16];
|
||||
struct __key_tone *ktone = (struct __key_tone *)p;
|
||||
ktone->start = 1;
|
||||
ktone->busy = 1;
|
||||
while (1) {
|
||||
os_taskq_pend(NULL, msg, ARRAY_SIZE(msg));
|
||||
res = key_tone_play_run(ktone);
|
||||
if (res) {
|
||||
///等待删除线程
|
||||
key_tone_play_close(ktone);
|
||||
ktone->busy = 0;
|
||||
while (1) {
|
||||
os_time_dly(10000);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Destroy
|
||||
* Description: 注销按键提示音播放
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_key_tone_destroy(void)
|
||||
{
|
||||
if (!key_tone) {
|
||||
return ;
|
||||
}
|
||||
|
||||
key_tone->start = 0;
|
||||
|
||||
while (key_tone->busy) {
|
||||
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
|
||||
os_time_dly(1);
|
||||
}
|
||||
|
||||
task_kill(AUDIO_KEY_TONE_TASK_NAME);
|
||||
|
||||
local_irq_disable();
|
||||
free(key_tone);
|
||||
key_tone = NULL;
|
||||
local_irq_enable();
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Init
|
||||
* Description: 按键提示音初始化
|
||||
* Arguments : None.
|
||||
* Return : true 成功
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_init(void)
|
||||
{
|
||||
int err = 0;
|
||||
if (key_tone) {
|
||||
return true;
|
||||
}
|
||||
struct __key_tone *ktone = zalloc(sizeof(struct __key_tone));
|
||||
err = task_create(key_tone_task_deal, (void *)ktone, AUDIO_KEY_TONE_TASK_NAME);
|
||||
if (err != OS_NO_ERR) {
|
||||
log_e("%s creat fail %x\n", __FUNCTION__, err);
|
||||
free(ktone);
|
||||
return false;
|
||||
}
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
ktone->volume = get_max_sys_vol();
|
||||
#endif
|
||||
key_tone = ktone;
|
||||
return true;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 正弦波序号
|
||||
#define KTONE_SINE_NORAML 0
|
||||
|
||||
// 按键提示音序号
|
||||
enum {
|
||||
KTONE_IDEX_NORAML = 0,
|
||||
KTONE_IDEX_NUM_0,
|
||||
KTONE_IDEX_NUM_1,
|
||||
|
||||
KTONE_IDEX_MAX,
|
||||
};
|
||||
|
||||
// 序号对应表
|
||||
static const char *const key_tone_index[] = {
|
||||
[KTONE_IDEX_NORAML] = DEFAULT_SINE_TONE(KTONE_SINE_NORAML),
|
||||
[KTONE_IDEX_NUM_0] = SDFILE_RES_ROOT_PATH"tone/0.*",
|
||||
[KTONE_IDEX_NUM_1] = SDFILE_RES_ROOT_PATH"tone/1.*",
|
||||
};
|
||||
|
||||
/*
|
||||
* 正弦波参数配置:
|
||||
* freq : 实际频率 * 512
|
||||
* points : 正弦波点数
|
||||
* win : 正弦窗
|
||||
* decay : 衰减系数(百分比), 正弦窗模式下为频率设置:频率*512
|
||||
*/
|
||||
static const struct sin_param sine_16k_normal[] = {
|
||||
/*{0, 1000, 0, 100},*/
|
||||
{200 << 9, 4000, 0, 100},
|
||||
};
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Get Sine Param Data
|
||||
* Description: 获取正弦波数组
|
||||
* Arguments : id 正弦波序号
|
||||
* *num 正弦波数组长度
|
||||
* Return : 正弦波数组
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static const struct sin_param *get_sine_param_data(u8 id, u8 *num)
|
||||
{
|
||||
const struct sin_param *param_data = NULL;
|
||||
switch (id) {
|
||||
case KTONE_SINE_NORAML:
|
||||
param_data = sine_16k_normal;
|
||||
*num = ARRAY_SIZE(sine_16k_normal);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
return param_data;
|
||||
};
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Open With Callback
|
||||
* Description: 打开文件播放
|
||||
* Arguments : *file_name 文件名
|
||||
* *sin 正弦波数组
|
||||
* sin_num 正弦波数组长度
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* evt_handler 事件回调
|
||||
* evt_priv 事件回调参数
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
static int ktone_play_open_with_callback_base(const char *file_name, struct audio_sin_param *sin, u8 sin_num, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv)
|
||||
{
|
||||
struct __key_tone *ktone = key_tone;
|
||||
if ((!ktone) || (!ktone->start)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct __key_tone_play_info info = {0};
|
||||
info.preemption = preemption;
|
||||
info.evt_handler = evt_handler;
|
||||
info.evt_priv = evt_priv;
|
||||
if (sin && sin_num) {
|
||||
info.sin = sin;
|
||||
info.sin_num = sin_num;
|
||||
} else {
|
||||
info.file_name = file_name;
|
||||
if (IS_DEFAULT_SINE(file_name)) {
|
||||
info.sin = get_sine_param_data(DEFAULT_SINE_ID(file_name), &info.sin_num);
|
||||
}
|
||||
}
|
||||
|
||||
local_irq_disable();
|
||||
memcpy(&ktone->play_info, &info, sizeof(struct __key_tone_play_info));
|
||||
ktone->play = 1;
|
||||
local_irq_enable();
|
||||
|
||||
os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play Sine
|
||||
* Description: 播放正弦波数组
|
||||
* Arguments : *sin 正弦波数组
|
||||
* sin_num 正弦波数组长度
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_play_sin(struct audio_sin_param *sin, u8 sin_num, u8 preemption)
|
||||
{
|
||||
/* y_printf("n:0x%x \n", name); */
|
||||
return ktone_play_open_with_callback_base(NULL, sin, sin_num, preemption, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play File
|
||||
* Description: 播放文件
|
||||
* Arguments : *name 文件名
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* Return : 0 正常
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_play_name(const char *name, u8 preemption)
|
||||
{
|
||||
/* y_printf("n:0x%x \n", name); */
|
||||
return ktone_play_open_with_callback_base(name, NULL, 0, preemption, NULL, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play Index
|
||||
* Description: 按序号播放文件
|
||||
* Arguments : index 序号
|
||||
* preemption 1-抢断播放;0-叠加播放
|
||||
* Return : 0 正常
|
||||
* Note(s) : 使用key_tone_index[]数组
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_play_index(u8 index, u8 preemption)
|
||||
{
|
||||
if (index >= KTONE_IDEX_MAX) {
|
||||
return -1;
|
||||
}
|
||||
return audio_key_tone_play_name(key_tone_index[index], preemption);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Play
|
||||
* Description: 按键提示音播放
|
||||
* Arguments : None.
|
||||
* Return : None.
|
||||
* Note(s) : 默认播放
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_key_tone_play(void)
|
||||
{
|
||||
audio_key_tone_play_index(KTONE_IDEX_NORAML, 0);
|
||||
/* audio_key_tone_play_index(KTONE_IDEX_NUM_0, 0); */
|
||||
/* audio_key_tone_play_sin(sine_16k_normal, ARRAY_SIZE(sine_16k_normal), 0); */
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Check Play
|
||||
* Description: 检测按键提示音是否在播放
|
||||
* Arguments : None.
|
||||
* Return : true 正在播放
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int audio_key_tone_is_play(void)
|
||||
{
|
||||
if ((!key_tone) || (!key_tone->start)) {
|
||||
return false;
|
||||
}
|
||||
if (key_tone->dec_file || key_tone->dec_sin) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Key Tone Set Digvol
|
||||
* Description: 设置按键提示音的音量
|
||||
* Arguments : volume 音量
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_key_tone_digvol_set(u8 volume)
|
||||
{
|
||||
#if AUDIO_KEY_TONE_DIGVOL_EN
|
||||
log_i("vol:%d \n", volume);
|
||||
if (!key_tone) {
|
||||
return ;
|
||||
}
|
||||
key_tone->volume = volume;
|
||||
void *vol_hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, AUDIO_KEY_TONE_DIGVOL_NAME);
|
||||
if (vol_hdl == NULL) {
|
||||
return;
|
||||
}
|
||||
audio_dig_vol_set(vol_hdl, AUDIO_DIG_VOL_ALL_CH, volume);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
325
apps/common/audio/decode/decode.c
Normal file
325
apps/common/audio/decode/decode.c
Normal file
@ -0,0 +1,325 @@
|
||||
|
||||
#include "application/audio_dec_app.h"
|
||||
#include "app_config.h"
|
||||
#include "audio_config.h"
|
||||
#include "app_main.h"
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
extern struct audio_decoder_task decode_task;
|
||||
extern struct audio_mixer mixer;
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
|
||||
extern struct audio_dac_channel default_dac;
|
||||
#endif
|
||||
|
||||
extern const int audio_dec_app_mix_en;
|
||||
|
||||
extern u32 audio_output_channel_num(void);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
struct audio_dec_app_audio_state_hdl {
|
||||
struct audio_mixer *p_mixer;
|
||||
u32 dec_mix : 1; // 1:叠加模式
|
||||
u32 flag;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
const struct audio_dec_format_hdl decode_format_list[] = {
|
||||
{"wtg", AUDIO_CODING_G729},
|
||||
{"msbc", AUDIO_CODING_MSBC},
|
||||
{"msb", AUDIO_CODING_MSBC},
|
||||
{"sbc", AUDIO_CODING_SBC},
|
||||
{"mty", AUDIO_CODING_MTY},
|
||||
{"aac", AUDIO_CODING_AAC},
|
||||
{"mp3", AUDIO_CODING_MP3},
|
||||
{"wma", AUDIO_CODING_WMA},
|
||||
{"wav", AUDIO_CODING_WAV},
|
||||
#if (defined(TCFG_DEC_MIDI_ENABLE) && TCFG_DEC_MIDI_ENABLE)
|
||||
//midi 文件播放,需要对应音色文件配合
|
||||
{"midi", AUDIO_CODING_MIDI},
|
||||
{"mid", AUDIO_CODING_MIDI},
|
||||
#endif //TCFG_DEC_MIDI_ENABLE
|
||||
|
||||
#if TCFG_DEC_WTGV2_ENABLE
|
||||
{"wts", AUDIO_CODING_WTGV2},
|
||||
#endif
|
||||
{"speex", AUDIO_CODING_SPEEX},
|
||||
{"opus", AUDIO_CODING_OPUS},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
static struct audio_stream_entry *audio_dec_app_entries[2] = {NULL};
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 解码创建参数初始化
|
||||
@param *dec: 解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_app_create_param_init(struct audio_dec_app_hdl *dec)
|
||||
{
|
||||
dec->p_decode_task = &decode_task;
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
if (!audio_dec_app_mix_en) {
|
||||
#if AUDIO_DAC_MULTI_CHANNEL_ENABLE
|
||||
audio_dec_app_entries[0] = &default_dac.entry;
|
||||
#else
|
||||
audio_dec_app_entries[0] = &dac_hdl.entry;
|
||||
#endif
|
||||
dec->entries = audio_dec_app_entries;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
dec->p_mixer = &mixer;
|
||||
}
|
||||
#if defined(CONFIG_MEDIA_DEVELOP_ENABLE)
|
||||
u8 dac_connect_mode = app_audio_output_mode_get();
|
||||
if (dac_connect_mode == DAC_OUTPUT_FRONT_LR_REAR_LR) {
|
||||
dec->out_ch_num = 4;
|
||||
} else {
|
||||
dec->out_ch_num = audio_output_channel_num();
|
||||
}
|
||||
#else
|
||||
u8 dac_connect_mode = audio_dac_get_channel(&dac_hdl);
|
||||
switch (dac_connect_mode) {
|
||||
/* case DAC_OUTPUT_DUAL_LR_DIFF: */
|
||||
case DAC_OUTPUT_LR:
|
||||
dec->out_ch_num = 2;
|
||||
break;
|
||||
/* case DAC_OUTPUT_FRONT_LR_REAR_LR: */
|
||||
/* dec->out_ch_num = 4; */
|
||||
/* break; */
|
||||
default :
|
||||
dec->out_ch_num = 1;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 文件解码创建参数初始化
|
||||
@param *file_dec: 文件解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_file_app_create_param_init(struct audio_dec_file_app_hdl *file_dec)
|
||||
{
|
||||
file_dec->format = (struct audio_dec_format_hdl *)decode_format_list;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 解码输出状态设置
|
||||
@param *dec: 解码句柄
|
||||
@param flag: 解码标签
|
||||
@return 0-正常
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_app_audio_state_switch(struct audio_dec_app_hdl *dec, u32 flag)
|
||||
{
|
||||
u8 need_set_audio = 1;
|
||||
/* if ((dec->dec_mix) && (audio_mixer_get_ch_num(dec->p_mixer) > 1)) { */
|
||||
/* need_set_audio = 0; */
|
||||
/* } */
|
||||
if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) {
|
||||
need_set_audio = 1;
|
||||
}
|
||||
if (need_set_audio) {
|
||||
if (flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) {
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol());
|
||||
} else {
|
||||
#ifdef TCFG_WTONT_ONCE_VOL
|
||||
extern u8 get_tone_once_vol(void);
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol());
|
||||
#else
|
||||
app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol());
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 解码输出状态退出
|
||||
@param *p_aud_state: 输出状态
|
||||
@return 0-正常
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_app_audio_state_exit(struct audio_dec_app_audio_state_hdl *p_aud_state)
|
||||
{
|
||||
u8 need_set_audio = 1;
|
||||
/* if ((p_aud_state->dec_mix) && (audio_mixer_get_ch_num(p_aud_state->p_mixer) > 1)) { */
|
||||
/* need_set_audio = 0; */
|
||||
/* } */
|
||||
/* if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) { */
|
||||
/* need_set_audio = 1; */
|
||||
/* } */
|
||||
if (need_set_audio) {
|
||||
if (p_aud_state->flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) {
|
||||
app_audio_state_exit(APP_AUDIO_STATE_MUSIC);
|
||||
} else {
|
||||
app_audio_state_exit(APP_AUDIO_STATE_WTONE);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 文件解码初始化完成
|
||||
@param *file_dec: 文件解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_file_app_init_ok(struct audio_dec_file_app_hdl *file_dec)
|
||||
{
|
||||
audio_dec_app_audio_state_switch(file_dec->dec, file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 文件解码结束
|
||||
@param *file_dec: 文件解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_file_app_play_end(struct audio_dec_file_app_hdl *file_dec)
|
||||
{
|
||||
struct audio_dec_app_audio_state_hdl aud_state = {0};
|
||||
aud_state.p_mixer = file_dec->dec->p_mixer;
|
||||
aud_state.dec_mix = file_dec->dec->dec_mix;
|
||||
aud_state.flag = file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK;
|
||||
audio_dec_file_app_close(file_dec);
|
||||
audio_dec_app_audio_state_exit(&aud_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 正弦波解码初始化完成
|
||||
@param *sine_dec: 正弦波解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_sine_app_init_ok(struct audio_dec_sine_app_hdl *sine_dec)
|
||||
{
|
||||
audio_dec_app_audio_state_switch(sine_dec->dec, sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK);
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 正弦波解码结束
|
||||
@param *sine_dec: 正弦波解码句柄
|
||||
@return 0-正常
|
||||
@note 弱函数重定义
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
int audio_dec_sine_app_play_end(struct audio_dec_sine_app_hdl *sine_dec)
|
||||
{
|
||||
struct audio_dec_app_audio_state_hdl aud_state = {0};
|
||||
aud_state.p_mixer = sine_dec->dec->p_mixer;
|
||||
aud_state.dec_mix = sine_dec->dec->dec_mix;
|
||||
aud_state.flag = sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK;
|
||||
audio_dec_sine_app_close(sine_dec);
|
||||
audio_dec_app_audio_state_exit(&aud_state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE))
|
||||
void audio_dec_app_output_sr_set(struct audio_dec_app_hdl *dec)
|
||||
{
|
||||
/* #if defined(CONFIG_CPU_BR23) */
|
||||
/* extern u32 audio_output_rate(int input_rate); */
|
||||
/* dec->src_out_sr = audio_output_rate(dec->src_out_sr); */
|
||||
/* #endif */
|
||||
if (dec->src_out_sr == 0) {
|
||||
dec->src_out_sr = audio_dac_get_sample_rate(&dac_hdl);
|
||||
if (dec->src_out_sr == 0) {
|
||||
dec->src_out_sr = 16000;
|
||||
log_w("src out is zero \n");
|
||||
}
|
||||
}
|
||||
if (dec->sample_rate == 0) {
|
||||
dec->sample_rate = dec->src_out_sr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// test
|
||||
#if 0
|
||||
#include "tone_player.h"
|
||||
|
||||
void audio_dec_file_test(void)
|
||||
{
|
||||
struct audio_dec_file_app_hdl *hdl;
|
||||
hdl = audio_dec_file_app_create(TONE_POWER_ON, 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(2);
|
||||
hdl = audio_dec_file_app_create(TONE_POWER_OFF, 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(300);
|
||||
}
|
||||
|
||||
static const struct audio_sin_param sine_test[] = {
|
||||
/*{0, 1000, 0, 100},*/
|
||||
{200 << 9, 4000, 0, 100},
|
||||
};
|
||||
static const struct audio_sin_param sine_test1[] = {
|
||||
{450 << 9, 24960, 1, 16.667 * 512},
|
||||
{0, 16000, 0, 100},
|
||||
};
|
||||
void audio_dec_sine_test(void)
|
||||
{
|
||||
struct audio_dec_sine_app_hdl *hdl;
|
||||
/* hdl = audio_dec_sine_app_create(SDFILE_RES_ROOT_PATH"tone/vol_max.sin", 1); */
|
||||
hdl = audio_dec_sine_app_create_by_parm(sine_test1, ARRAY_SIZE(sine_test1), 1);
|
||||
if (hdl) {
|
||||
audio_dec_sine_app_open(hdl);
|
||||
}
|
||||
os_time_dly(2);
|
||||
hdl = audio_dec_sine_app_create_by_parm(sine_test, ARRAY_SIZE(sine_test), 1);
|
||||
if (hdl) {
|
||||
audio_dec_sine_app_open(hdl);
|
||||
}
|
||||
/* os_time_dly(300); */
|
||||
}
|
||||
|
||||
void audio_dec_usb_file_test(void)
|
||||
{
|
||||
tone_play_stop();
|
||||
clk_set("sys", 192 * 1000000L);
|
||||
|
||||
struct audio_dec_file_app_hdl *hdl;
|
||||
/* hdl = audio_dec_file_app_create("storage/udisk/C/1.mp3", 1); */
|
||||
hdl = audio_dec_file_app_create("storage/udisk/C/1.wav", 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(2);
|
||||
/* hdl = audio_dec_file_app_create("storage/udisk/C/2.mp3", 1); */
|
||||
hdl = audio_dec_file_app_create("storage/udisk/C/2.wav", 1);
|
||||
if (hdl) {
|
||||
audio_dec_file_app_open(hdl);
|
||||
}
|
||||
os_time_dly(300);
|
||||
}
|
||||
|
||||
#endif /*test*/
|
||||
|
||||
|
||||
212
apps/common/audio/demo/audio_decoder_test.c
Normal file
212
apps/common/audio/demo/audio_decoder_test.c
Normal file
@ -0,0 +1,212 @@
|
||||
/*
|
||||
****************************************************************
|
||||
* AUDIO DECODER TEST
|
||||
* File : audio_decoder_test.c
|
||||
* By :
|
||||
* Notes : 解码测试
|
||||
* before和after之间就是解码对应功能的处理,
|
||||
* 可以在before和after中分别翻转IO来卡一下处理时间
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include "media/includes.h"
|
||||
|
||||
|
||||
#define DEC_IO_DEBUG_1(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);}
|
||||
#define DEC_IO_DEBUG_0(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);}
|
||||
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test output before
|
||||
* Description: 解码输出
|
||||
* Arguments : *dec 解码句柄
|
||||
* *buff 输出buf
|
||||
* len 输出长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_out_before(struct audio_decoder *dec, void *buff, int len)
|
||||
{
|
||||
DEC_IO_DEBUG_1(C, 3);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test output after
|
||||
* Description: 解码输出
|
||||
* Arguments : *dec 解码句柄
|
||||
* wlen 实际输出长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_out_after(struct audio_decoder *dec, int wlen)
|
||||
{
|
||||
DEC_IO_DEBUG_0(C, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test read file before
|
||||
* Description: 解码获取文件数据
|
||||
* Arguments : *dec 解码句柄
|
||||
* len 获取数据长度
|
||||
* offset 获取数据偏移地址
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_read_before(struct audio_decoder *dec, int len, u32 offset)
|
||||
{
|
||||
DEC_IO_DEBUG_1(C, 2);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test read file after
|
||||
* Description: 解码获取文件数据
|
||||
* Arguments : *dec 解码句柄
|
||||
* *data 获取到的数据
|
||||
* rlen 获取到的数据长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_read_after(struct audio_decoder *dec, u8 *data, int rlen)
|
||||
{
|
||||
DEC_IO_DEBUG_0(C, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test get frame before
|
||||
* Description: 解码获取帧数据
|
||||
* Arguments : *dec 解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_get_frame_before(struct audio_decoder *dec)
|
||||
{
|
||||
DEC_IO_DEBUG_1(C, 2);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test get frame after
|
||||
* Description: 解码获取帧数据
|
||||
* Arguments : *dec 解码句柄
|
||||
* *frame 获取到的帧数据
|
||||
* rlen 获取到的帧数据长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_get_frame_after(struct audio_decoder *dec, u8 *frame, int rlen)
|
||||
{
|
||||
DEC_IO_DEBUG_0(C, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test fetch frame before
|
||||
* Description: 解码检查帧数据
|
||||
* Arguments : *dec 解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_fetch_before(struct audio_decoder *dec)
|
||||
{
|
||||
DEC_IO_DEBUG_1(C, 2);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test fetch frame after
|
||||
* Description: 解码检查帧数据
|
||||
* Arguments : *dec 解码句柄
|
||||
* *frame 获取到的帧数据
|
||||
* rlen 获取到的帧数据长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_fetch_after(struct audio_decoder *dec, u8 *frame, int rlen)
|
||||
{
|
||||
DEC_IO_DEBUG_0(C, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test run before
|
||||
* Description: 解码处理
|
||||
* Arguments : *dec 解码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_run_before(struct audio_decoder *dec)
|
||||
{
|
||||
DEC_IO_DEBUG_1(C, 1);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio Decoder test run after
|
||||
* Description: 解码处理
|
||||
* Arguments : *dec 解码句柄
|
||||
* err 解码处理返回值
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_decoder_test_run_after(struct audio_decoder *dec, int err)
|
||||
{
|
||||
DEC_IO_DEBUG_0(C, 1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 数据流节点统计时间示例
|
||||
* 这里的时间是数据流节点运行的时间加上输出的时间
|
||||
* 数据流节点的运行时间约等于当前统计的时间减去下一个节点的统计时间
|
||||
* */
|
||||
#if 0
|
||||
|
||||
// 保存原来的数据流数据处理
|
||||
static void *demo_data_handler_save;
|
||||
// 数据流data_handler处理
|
||||
static int demo_new_data_handler(struct audio_stream_entry *entry,
|
||||
struct audio_data_frame *in,
|
||||
struct audio_data_frame *out)
|
||||
{
|
||||
DEC_IO_DEBUG_1(C, 1);
|
||||
|
||||
// 调用原来的接口输出
|
||||
int wlen = ((int (*)(struct audio_stream_entry *, struct audio_data_frame *, struct audio_data_frame *))demo_data_handler_save)(entry, in, out);
|
||||
|
||||
DEC_IO_DEBUG_0(C, 1);
|
||||
return wlen;
|
||||
}
|
||||
|
||||
|
||||
void test_start(void)
|
||||
{
|
||||
#if 1
|
||||
// 用变量保存原来的数据处理接口,然后重新赋值新的数据处理
|
||||
// 这里以获取mix节点的数据为例
|
||||
demo_data_handler_save = (void *)bt_a2dp_dec->mix_ch.entry.data_handler;
|
||||
bt_a2dp_dec->mix_ch.entry.data_handler = demo_new_data_handler;
|
||||
#endif
|
||||
|
||||
// 数据流串联
|
||||
struct audio_stream_entry *entries[8] = {NULL};
|
||||
u8 entry_cnt = 0;
|
||||
entries[entry_cnt++] = &dec->dec.decoder.entry;
|
||||
entries[entry_cnt++] = &dec->mix_ch.entry;
|
||||
// ...
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
106
apps/common/audio/demo/audio_demo.c
Normal file
106
apps/common/audio/demo/audio_demo.c
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "audio_config.h"
|
||||
#include "asm/dac.h"
|
||||
|
||||
|
||||
short const sin_1k_44100[441] = {
|
||||
0x0000, 0x122d, 0x23fb, 0x350f, 0x450f, 0x53aa, 0x6092, 0x6b85, 0x744b, 0x7ab5, 0x7ea2, 0x7fff, 0x7ec3, 0x7af6, 0x74ab, 0x6c03,
|
||||
0x612a, 0x545a, 0x45d4, 0x35e3, 0x24db, 0x1314, 0x00e9, 0xeeba, 0xdce5, 0xcbc6, 0xbbb6, 0xad08, 0xa008, 0x94fa, 0x8c18, 0x858f,
|
||||
0x8181, 0x8003, 0x811d, 0x84ca, 0x8af5, 0x9380, 0x9e3e, 0xaaf7, 0xb969, 0xc94a, 0xda46, 0xec06, 0xfe2d, 0x105e, 0x223a, 0x3365,
|
||||
0x4385, 0x5246, 0x5f5d, 0x6a85, 0x7384, 0x7a2d, 0x7e5b, 0x7ffa, 0x7f01, 0x7b75, 0x7568, 0x6cfb, 0x6258, 0x55b7, 0x4759, 0x3789,
|
||||
0x2699, 0x14e1, 0x02bc, 0xf089, 0xdea7, 0xcd71, 0xbd42, 0xae6d, 0xa13f, 0x95fd, 0x8ce1, 0x861a, 0x81cb, 0x800b, 0x80e3, 0x844e,
|
||||
0x8a3c, 0x928c, 0x9d13, 0xa99c, 0xb7e6, 0xc7a5, 0xd889, 0xea39, 0xfc5a, 0x0e8f, 0x2077, 0x31b8, 0x41f6, 0x50de, 0x5e23, 0x697f,
|
||||
0x72b8, 0x799e, 0x7e0d, 0x7fee, 0x7f37, 0x7bed, 0x761f, 0x6ded, 0x6380, 0x570f, 0x48db, 0x392c, 0x2855, 0x16ad, 0x048f, 0xf259,
|
||||
0xe06b, 0xcf20, 0xbed2, 0xafd7, 0xa27c, 0x9705, 0x8db0, 0x86ab, 0x821c, 0x801a, 0x80b0, 0x83da, 0x8988, 0x919c, 0x9bee, 0xa846,
|
||||
0xb666, 0xc603, 0xd6ce, 0xe86e, 0xfa88, 0x0cbf, 0x1eb3, 0x3008, 0x4064, 0x4f73, 0x5ce4, 0x6874, 0x71e6, 0x790a, 0x7db9, 0x7fdc,
|
||||
0x7f68, 0x7c5e, 0x76d0, 0x6ed9, 0x64a3, 0x5863, 0x4a59, 0x3acc, 0x2a0f, 0x1878, 0x0661, 0xf42a, 0xe230, 0xd0d0, 0xc066, 0xb145,
|
||||
0xa3bd, 0x9813, 0x8e85, 0x8743, 0x8274, 0x8030, 0x8083, 0x836b, 0x88da, 0x90b3, 0x9acd, 0xa6f5, 0xb4ea, 0xc465, 0xd515, 0xe6a3,
|
||||
0xf8b6, 0x0aee, 0x1ced, 0x2e56, 0x3ecf, 0x4e02, 0x5ba1, 0x6764, 0x710e, 0x786f, 0x7d5e, 0x7fc3, 0x7f91, 0x7cc9, 0x777a, 0x6fc0,
|
||||
0x65c1, 0x59b3, 0x4bd3, 0x3c6a, 0x2bc7, 0x1a41, 0x0833, 0xf5fb, 0xe3f6, 0xd283, 0xc1fc, 0xb2b7, 0xa503, 0x9926, 0x8f60, 0x87e1,
|
||||
0x82d2, 0x804c, 0x805d, 0x8303, 0x8833, 0x8fcf, 0x99b2, 0xa5a8, 0xb372, 0xc2c9, 0xd35e, 0xe4da, 0xf6e4, 0x091c, 0x1b26, 0x2ca2,
|
||||
0x3d37, 0x4c8e, 0x5a58, 0x664e, 0x7031, 0x77cd, 0x7cfd, 0x7fa3, 0x7fb4, 0x7d2e, 0x781f, 0x70a0, 0x66da, 0x5afd, 0x4d49, 0x3e04,
|
||||
0x2d7d, 0x1c0a, 0x0a05, 0xf7cd, 0xe5bf, 0xd439, 0xc396, 0xb42d, 0xa64d, 0x9a3f, 0x9040, 0x8886, 0x8337, 0x806f, 0x803d, 0x82a2,
|
||||
0x8791, 0x8ef2, 0x989c, 0xa45f, 0xb1fe, 0xc131, 0xd1aa, 0xe313, 0xf512, 0x074a, 0x195d, 0x2aeb, 0x3b9b, 0x4b16, 0x590b, 0x6533,
|
||||
0x6f4d, 0x7726, 0x7c95, 0x7f7d, 0x7fd0, 0x7d8c, 0x78bd, 0x717b, 0x67ed, 0x5c43, 0x4ebb, 0x3f9a, 0x2f30, 0x1dd0, 0x0bd6, 0xf99f,
|
||||
0xe788, 0xd5f1, 0xc534, 0xb5a7, 0xa79d, 0x9b5d, 0x9127, 0x8930, 0x83a2, 0x8098, 0x8024, 0x8247, 0x86f6, 0x8e1a, 0x978c, 0xa31c,
|
||||
0xb08d, 0xbf9c, 0xcff8, 0xe14d, 0xf341, 0x0578, 0x1792, 0x2932, 0x39fd, 0x499a, 0x57ba, 0x6412, 0x6e64, 0x7678, 0x7c26, 0x7f50,
|
||||
0x7fe6, 0x7de4, 0x7955, 0x7250, 0x68fb, 0x5d84, 0x5029, 0x412e, 0x30e0, 0x1f95, 0x0da7, 0xfb71, 0xe953, 0xd7ab, 0xc6d4, 0xb725,
|
||||
0xa8f1, 0x9c80, 0x9213, 0x89e1, 0x8413, 0x80c9, 0x8012, 0x81f3, 0x8662, 0x8d48, 0x9681, 0xa1dd, 0xaf22, 0xbe0a, 0xce48, 0xdf89,
|
||||
0xf171, 0x03a6, 0x15c7, 0x2777, 0x385b, 0x481a, 0x5664, 0x62ed, 0x6d74, 0x75c4, 0x7bb2, 0x7f1d, 0x7ff5, 0x7e35, 0x79e6, 0x731f,
|
||||
0x6a03, 0x5ec1, 0x5193, 0x42be, 0x328f, 0x2159, 0x0f77, 0xfd44, 0xeb1f, 0xd967, 0xc877, 0xb8a7, 0xaa49, 0x9da8, 0x9305, 0x8a98,
|
||||
0x848b, 0x80ff, 0x8006, 0x81a5, 0x85d3, 0x8c7c, 0x957b, 0xa0a3, 0xadba, 0xbc7b, 0xcc9b, 0xddc6, 0xefa2, 0x01d3, 0x13fa, 0x25ba,
|
||||
0x36b6, 0x4697, 0x5509, 0x61c2, 0x6c80, 0x750b, 0x7b36, 0x7ee3, 0x7ffd, 0x7e7f, 0x7a71, 0x73e8, 0x6b06, 0x5ff8, 0x52f8, 0x444a,
|
||||
0x343a, 0x231b, 0x1146, 0xff17, 0xecec, 0xdb25, 0xca1d, 0xba2c, 0xaba6, 0x9ed6, 0x93fd, 0x8b55, 0x850a, 0x813d, 0x8001, 0x815e,
|
||||
0x854b, 0x8bb5, 0x947b, 0x9f6e, 0xac56, 0xbaf1, 0xcaf1, 0xdc05, 0xedd3
|
||||
};
|
||||
|
||||
extern struct audio_dac_hdl dac_hdl;
|
||||
|
||||
static void dac_test_task_handle(void *p)
|
||||
{
|
||||
int len = 0;
|
||||
int wlen = 0;
|
||||
s16 *ptr;
|
||||
s16 *data_addr;
|
||||
u32 data_len;
|
||||
int res = 0;
|
||||
int msg[16];
|
||||
|
||||
printf(">>>>>>>>>>>>>>>>>>>>>audio_dac_demo>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
|
||||
app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol()); // 音量状态设置
|
||||
audio_dac_set_volume(&dac_hdl, get_max_sys_vol()); // dac 音量设置
|
||||
audio_dac_set_sample_rate(&dac_hdl, 44100); // 采样率设置
|
||||
audio_dac_start(&dac_hdl); // dac 启动
|
||||
|
||||
// 循环一直往dac写数据
|
||||
while (1) {
|
||||
// 这句是为了防止线程太久没有响应系统而产生异常,实际使用不需要
|
||||
/* res = os_taskq_accept(ARRAY_SIZE(msg), msg); */
|
||||
ptr = sin_1k_44100;
|
||||
len = 441 * 2;
|
||||
while (len) {
|
||||
// 往 dac 写数据
|
||||
wlen = audio_dac_write(&dac_hdl, ptr, len);
|
||||
/* void debug_random_read(u32 size); */
|
||||
/* debug_random_read(32 * 1024); */
|
||||
if (wlen != len) { // dac缓存满了,延时 10ms 后再继续写
|
||||
putchar('W');
|
||||
os_time_dly(1);
|
||||
}
|
||||
ptr += wlen / 2;
|
||||
len -= wlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void audio_demo(void)
|
||||
{
|
||||
int ret = os_task_create(dac_test_task_handle, NULL, 31, 512, 0, "dac_task");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef BT_DUT_INTERFERE
|
||||
|
||||
void idle_hook(void)
|
||||
{
|
||||
while (1) {
|
||||
wdt_close();
|
||||
//cpu 测试
|
||||
/* void coremark_main(void); */
|
||||
/* coremark_main(); */
|
||||
void debug_random_read(u32 size);
|
||||
debug_random_read(32 * 1024);
|
||||
local_irq_disable();
|
||||
putchar('c');
|
||||
putchar('o');
|
||||
putchar('r');
|
||||
putchar('e');
|
||||
local_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
110
apps/common/audio/demo/audio_encoder_test.c
Normal file
110
apps/common/audio/demo/audio_encoder_test.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
****************************************************************
|
||||
* AUDIO ENCODE TEST
|
||||
* File : audio_encoder_test.c
|
||||
* By :
|
||||
* Notes : 编码测试
|
||||
* before和after之间就是编码对应功能的处理,
|
||||
* 可以在before和after中分别翻转IO来卡一下处理时间
|
||||
****************************************************************
|
||||
*/
|
||||
|
||||
|
||||
#include "media/includes.h"
|
||||
|
||||
|
||||
#define ENC_IO_DEBUG_1(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);}
|
||||
#define ENC_IO_DEBUG_0(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio encoder test output before
|
||||
* Description: 编码输出
|
||||
* Arguments : *enc 编码句柄
|
||||
* *buff 输出buf
|
||||
* len 输出长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_encoder_test_out_before(struct audio_encoder *enc, void *buff, int len)
|
||||
{
|
||||
ENC_IO_DEBUG_1(C, 3);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio encoder test output after
|
||||
* Description: 编码输出
|
||||
* Arguments : *enc 编码句柄
|
||||
* wlen 实际输出长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_encoder_test_out_after(struct audio_encoder *enc, int wlen)
|
||||
{
|
||||
ENC_IO_DEBUG_0(C, 3);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio encoder test get frame before
|
||||
* Description: 编码获取帧数据
|
||||
* Arguments : *enc 编码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_encoder_test_get_frame_before(struct audio_encoder *enc, u16 frame_len)
|
||||
{
|
||||
ENC_IO_DEBUG_1(C, 2);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio encoder test get frame after
|
||||
* Description: 编码获取帧数据
|
||||
* Arguments : *enc 编码句柄
|
||||
* *frame 获取到的帧数据
|
||||
* rlen 获取到的帧数据长度
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_encoder_test_get_frame_after(struct audio_encoder *enc, s16 *frame, int rlen)
|
||||
{
|
||||
ENC_IO_DEBUG_0(C, 2);
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio encoder test run before
|
||||
* Description: 编码处理
|
||||
* Arguments : *enc 编码句柄
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_encoder_test_run_before(struct audio_encoder *enc)
|
||||
{
|
||||
ENC_IO_DEBUG_1(C, 1);
|
||||
}
|
||||
/*
|
||||
*********************************************************************
|
||||
* Audio encoder test run after
|
||||
* Description: 编码处理
|
||||
* Arguments : *enc 编码句柄
|
||||
* err 编码处理返回值
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void audio_encoder_test_run_after(struct audio_encoder *enc, int err)
|
||||
{
|
||||
ENC_IO_DEBUG_0(C, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
211
apps/common/audio/online_debug/aud_data_export.c
Normal file
211
apps/common/audio/online_debug/aud_data_export.c
Normal file
@ -0,0 +1,211 @@
|
||||
#include "aud_data_export.h"
|
||||
#include "audio_online_debug.h"
|
||||
#include "circular_buf.h"
|
||||
#include "timer.h"
|
||||
|
||||
#define AUD_DE_LOG y_printf
|
||||
|
||||
/*支持的数据通道数:1~3*/
|
||||
#define AUDIO_DATA_EXPORT_CH 1
|
||||
|
||||
enum {
|
||||
AEC_ST_STOP = 0,
|
||||
AEC_ST_INIT,
|
||||
AEC_ST_START,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
u8 state;
|
||||
u8 ch; /*export data ch num*/
|
||||
u16 send_timer;
|
||||
u8 packet[256];
|
||||
#if (AUDIO_DATA_EXPORT_CH > 0)
|
||||
u8 buf0[1024];
|
||||
cbuffer_t data_cbuf0;
|
||||
u32 seqn0;
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
#if (AUDIO_DATA_EXPORT_CH > 1)
|
||||
u8 buf1[1024];
|
||||
cbuffer_t data_cbuf1;
|
||||
u32 seqn1;
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
#if (AUDIO_DATA_EXPORT_CH > 2)
|
||||
u8 buf2[1024];
|
||||
cbuffer_t data_cbuf2;
|
||||
u32 seqn2;
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
} aud_data_export_t;
|
||||
aud_data_export_t *aud_de = NULL;
|
||||
|
||||
typedef struct {
|
||||
int cmd;
|
||||
int data;
|
||||
} rec_cmd_t;
|
||||
|
||||
int audio_data_export_start(u8 ch)
|
||||
{
|
||||
if (aud_de) {
|
||||
AUD_DE_LOG("aud_de re-malloc !!!");
|
||||
return 0;
|
||||
}
|
||||
aud_de = zalloc(sizeof(aud_data_export_t));
|
||||
if (aud_de == NULL) {
|
||||
AUD_DE_LOG("aud_de malloc failed!!!");
|
||||
return -1;
|
||||
}
|
||||
if (ch <= AUDIO_DATA_EXPORT_CH) {
|
||||
aud_de->ch = ch;
|
||||
} else {
|
||||
aud_de->ch = AUDIO_DATA_EXPORT_CH;
|
||||
}
|
||||
#if (AUDIO_DATA_EXPORT_CH > 0)
|
||||
cbuf_init(&aud_de->data_cbuf0, aud_de->buf0, sizeof(aud_de->buf0));
|
||||
aud_de->seqn0 = 0;
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
#if (AUDIO_DATA_EXPORT_CH > 1)
|
||||
cbuf_init(&aud_de->data_cbuf1, aud_de->buf1, sizeof(aud_de->buf1));
|
||||
aud_de->seqn1 = 0;
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
#if (AUDIO_DATA_EXPORT_CH > 2)
|
||||
cbuf_init(&aud_de->data_cbuf2, aud_de->buf2, sizeof(aud_de->buf2));
|
||||
aud_de->seqn2 = 0;
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
aud_de->state = AEC_ST_START;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void audio_data_export_stop(void)
|
||||
{
|
||||
if (aud_de) {
|
||||
if (aud_de->send_timer) {
|
||||
sys_timer_del(aud_de->send_timer);
|
||||
aud_de->send_timer = 0;
|
||||
}
|
||||
aud_de->state = AEC_ST_STOP;
|
||||
free(aud_de);
|
||||
aud_de = NULL;
|
||||
}
|
||||
}
|
||||
static int spp_data_export(u8 ch, u8 *buf, u16 len)
|
||||
{
|
||||
u8 data_ch;
|
||||
putchar('.');
|
||||
if (ch == 0) {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH0;
|
||||
} else if (ch == 1) {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH1;
|
||||
} else {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH2;
|
||||
}
|
||||
int err = app_online_db_send_more(data_ch, buf, len);
|
||||
if (err) {
|
||||
printf("tx_err:%d", err);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
int audio_data_export_run(u8 ch, u8 *data, int len)
|
||||
{
|
||||
int ret = 0;
|
||||
if (aud_de && (aud_de->state == AEC_ST_START)) {
|
||||
#if (AUDIO_DATA_EXPORT_CH > 0)
|
||||
if (ch == 0) {
|
||||
int wlen = cbuf_write(&aud_de->data_cbuf0, data, len);
|
||||
if (cbuf_get_data_size(&aud_de->data_cbuf0) >= 640) {
|
||||
u8 tmp_buf[RECORD_CH0_LENGTH];
|
||||
memcpy(tmp_buf, &aud_de->seqn0, 4);
|
||||
s16 *data_buf = &tmp_buf[4];
|
||||
cbuf_read(&aud_de->data_cbuf0, data_buf, 640);
|
||||
spp_data_export(ch, tmp_buf, 644);
|
||||
aud_de->seqn0 ++;
|
||||
putchar('s');
|
||||
|
||||
}
|
||||
}
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
#if (AUDIO_DATA_EXPORT_CH > 1)
|
||||
else if (ch == 1) {
|
||||
int wlen = cbuf_write(&aud_de->data_cbuf1, data, len);
|
||||
if (cbuf_get_data_size(&aud_de->data_cbuf1) >= 640) {
|
||||
u8 tmp_buf[RECORD_CH1_LENGTH];
|
||||
memcpy(tmp_buf, &aud_de->seqn1, 4);
|
||||
s16 *data_buf = &tmp_buf[4];
|
||||
cbuf_read(&aud_de->data_cbuf1, data_buf, 640);
|
||||
spp_data_export(ch, tmp_buf, 644);
|
||||
aud_de->seqn1 ++;
|
||||
putchar('s');
|
||||
}
|
||||
|
||||
}
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
#if (AUDIO_DATA_EXPORT_CH > 2)
|
||||
else if (ch == 2) {
|
||||
int wlen = cbuf_write(&aud_de->data_cbuf2, data, len);
|
||||
if (cbuf_get_data_size(&aud_de->data_cbuf2) >= 640) {
|
||||
u8 tmp_buf[RECORD_CH2_LENGTH];
|
||||
memcpy(tmp_buf, &aud_de->seqn2, 4);
|
||||
s16 *data_buf = &tmp_buf[4];
|
||||
cbuf_read(&aud_de->data_cbuf2, data_buf, 640);
|
||||
spp_data_export(ch, tmp_buf, 644);
|
||||
aud_de->seqn2 ++;
|
||||
putchar('s');
|
||||
}
|
||||
}
|
||||
#endif /*AUDIO_DATA_EXPORT_CH*/
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
static int aud_online_data_export_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)
|
||||
{
|
||||
int res_data = 0;
|
||||
rec_cmd_t rec_cmd;
|
||||
int err = 0;
|
||||
u8 parse_seq = ext_data[1];
|
||||
//AUD_DE_LOG("aec_spp_rx,seq:%d,size:%d\n", parse_seq, size);
|
||||
//put_buf(packet, size);
|
||||
memcpy(&rec_cmd, packet, sizeof(rec_cmd_t));
|
||||
switch (rec_cmd.cmd) {
|
||||
case AUD_RECORD_COUNT:
|
||||
if (aud_de) {
|
||||
/* res_data = aud_de->ch; */
|
||||
res_data = AUDIO_DATA_EXPORT_CH;
|
||||
} else {
|
||||
res_data = AUDIO_DATA_EXPORT_CH;
|
||||
}
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4);
|
||||
AUD_DE_LOG("query record_ch num:%d\n", res_data);
|
||||
break;
|
||||
case AUD_RECORD_START:
|
||||
audio_data_export_start(AUDIO_DATA_EXPORT_CH);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 1); //该命令随便ack一个byte即可
|
||||
AUD_DE_LOG("record_start\n");
|
||||
break;
|
||||
case AUD_RECORD_STOP:
|
||||
AUD_DE_LOG("record_stop\n");
|
||||
audio_data_export_stop();
|
||||
app_online_db_ack(parse_seq, (u8 *)&res_data, 1); //该命令随便ack一个byte即可
|
||||
break;
|
||||
case ONLINE_OP_QUERY_RECORD_PACKAGE_LENGTH:
|
||||
if (rec_cmd.data == 0) {
|
||||
res_data = RECORD_CH0_LENGTH;
|
||||
} else if (rec_cmd.data == 1) {
|
||||
res_data = RECORD_CH1_LENGTH;
|
||||
} else {
|
||||
res_data = RECORD_CH2_LENGTH;
|
||||
}
|
||||
AUD_DE_LOG("query record ch%d packet length:%d\n", rec_cmd.data, res_data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4); //回复对应的通道数据长度
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aud_data_export_open(void)
|
||||
{
|
||||
app_online_db_register_handle(DB_PKT_TYPE_EXPORT, aud_online_data_export_parse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aud_data_export_close(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
8
apps/common/audio/online_debug/aud_data_export.h
Normal file
8
apps/common/audio/online_debug/aud_data_export.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef _AUD_DATA_EXPORT_H_
|
||||
#define _AUD_DATA_EXPORT_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
|
||||
|
||||
#endif/*_AUD_DATA_EXPORT_H_*/
|
||||
354
apps/common/audio/online_debug/aud_mic_dut.c
Normal file
354
apps/common/audio/online_debug/aud_mic_dut.c
Normal file
@ -0,0 +1,354 @@
|
||||
#include "aud_mic_dut.h"
|
||||
#include "audio_online_debug.h"
|
||||
#include "online_db_deal.h"
|
||||
#include "app_config.h"
|
||||
#include "system/includes.h"
|
||||
|
||||
#if ((defined TCFG_AUDIO_MIC_DUT_ENABLE) && TCFG_AUDIO_MIC_DUT_ENABLE)
|
||||
#include "mic_dut_process.h"
|
||||
|
||||
#define AUDIO_MIC_DUT_TASK_NAME "AudioMicDut"
|
||||
|
||||
typedef struct {
|
||||
u8 start; /*mic dut 开始和结束标志*/
|
||||
u16 mic_gain; /*保存在线调试的mic gain*/
|
||||
u32 sr; /*保存在线调试的mic采样率*/
|
||||
u8 mic_idx; /*记录当前使用的那个mic*/
|
||||
u8 scan_start; /*mic dut scan 开始和结束的标志*/
|
||||
u8 dac_gain; /*保存在线调试的dac gain*/
|
||||
u32 send_timer; /*定时器句柄*/
|
||||
u32 seqn; /*数据的seqn*/
|
||||
OS_SEM sem; /*信号量*/
|
||||
} mic_online_info_t;
|
||||
|
||||
/*硬件信息*/
|
||||
static mic_dut_info_t mic_info;
|
||||
|
||||
/*在线调试信息*/
|
||||
static mic_online_info_t online_info_t;
|
||||
static mic_online_info_t *online_info_hdl = &online_info_t;
|
||||
|
||||
static int spp_data_export(u8 ch, u8 *buf, u16 len)
|
||||
{
|
||||
u8 data_ch;
|
||||
putchar('.');
|
||||
if (ch == 0) {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH0;
|
||||
} else if (ch == 1) {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH1;
|
||||
} else {
|
||||
data_ch = DB_PKT_TYPE_DAT_CH2;
|
||||
}
|
||||
int err = app_online_db_send_more(data_ch, buf, len);
|
||||
if (err) {
|
||||
printf("tx_err:%d", err);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/*在线数据初始化*/
|
||||
static void mic_dut_online_init(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->start = 0;
|
||||
online_info_hdl->mic_gain = mic_info.mic_gain_default;
|
||||
online_info_hdl->sr = mic_info.sr_default;
|
||||
online_info_hdl->mic_idx = 0;
|
||||
online_info_hdl->scan_start = 0;
|
||||
online_info_hdl->dac_gain = mic_info.dac_gain_default;
|
||||
online_info_hdl->send_timer = 0;
|
||||
online_info_hdl->seqn = 1;
|
||||
} else {
|
||||
printf("online_info_hdl is NULL !!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_mic_dut_data_export_run(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
u8 buf[644];
|
||||
u8 *data = &buf[4];
|
||||
int len = 640;
|
||||
int rlen = 0;
|
||||
if (audio_mic_dut_get_data_len() >= len) {
|
||||
memcpy(buf, &online_info_hdl->seqn, 4);
|
||||
rlen = audio_mic_dut_data_get(data, len);
|
||||
extern void audio_mic_dut_eq_run(s16 * data, int len);
|
||||
audio_mic_dut_eq_run(data, len);
|
||||
/* printf("%d, %d", len, rlen); */
|
||||
int ret = spp_data_export(0, buf, rlen + 4);
|
||||
|
||||
online_info_hdl->seqn ++;
|
||||
/* printf("seqn %d %d\n", mic_online_info.seqn,*((int *) buf)); */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void audio_mic_dut_timer(void *p)
|
||||
{
|
||||
audio_mic_dut_data_export_run();
|
||||
}
|
||||
|
||||
static void audio_mic_dut_task(void *p)
|
||||
{
|
||||
while (1) {
|
||||
os_sem_pend(&online_info_hdl->sem, 0);
|
||||
audio_mic_dut_data_export_run();
|
||||
}
|
||||
}
|
||||
|
||||
static void mic_dut_online_start(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
#if MIC_DUT_DATA_SEND_BY_TIMER
|
||||
online_info_hdl->send_timer = usr_timer_add(NULL, audio_mic_dut_timer, MIC_DATA_SEND_INTERVAL, 1);
|
||||
#else
|
||||
os_sem_create(&online_info_hdl->sem, 0);
|
||||
os_task_create(audio_mic_dut_task, NULL, 1, 768, 64, AUDIO_MIC_DUT_TASK_NAME);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*释放mic dut 信号量*/
|
||||
void mic_dut_online_sem_post(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
#if (MIC_DUT_DATA_SEND_BY_TIMER == 0)
|
||||
os_sem_post(&online_info_hdl->sem);
|
||||
#endif /*SPP_SEND_BY_TIMER*/
|
||||
}
|
||||
}
|
||||
|
||||
static void mic_dut_online_stop(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
if (online_info_hdl->start) {
|
||||
audio_mic_dut_stop();
|
||||
online_info_hdl->start = 0;
|
||||
}
|
||||
if (online_info_hdl->scan_start) {
|
||||
audio_mic_dut_scan_stop();
|
||||
online_info_hdl->scan_start = 0;
|
||||
}
|
||||
|
||||
#if MIC_DUT_DATA_SEND_BY_TIMER
|
||||
if (online_info_hdl->send_timer) {
|
||||
usr_timer_del(online_info_hdl->send_timer);
|
||||
online_info_hdl->send_timer = 0;
|
||||
}
|
||||
#else
|
||||
os_task_del(AUDIO_MIC_DUT_TASK_NAME);
|
||||
os_sem_del(&online_info_hdl->sem, 0);
|
||||
#endif
|
||||
/* online_info_hdl = NULL; */
|
||||
}
|
||||
}
|
||||
|
||||
/*数据解析*/
|
||||
static int mic_dut_online_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)
|
||||
{
|
||||
int res_data = 0;
|
||||
online_cmd_t mic_dut_cmd;
|
||||
int err = 0;
|
||||
u8 parse_seq = ext_data[1];
|
||||
//AEC_ONLINE_LOG("[MIC_DUT]spp_rx,seq:%d,size:%d\n", parse_seq, size);
|
||||
put_buf(packet, size);
|
||||
memcpy(&mic_dut_cmd, packet, sizeof(online_cmd_t));
|
||||
printf("[MIC_DUT]cmd:0x%x\n", mic_dut_cmd.cmd);
|
||||
switch (mic_dut_cmd.cmd) {
|
||||
case AUD_RECORD_COUNT:
|
||||
y_printf("AEC_RECORD_COUNT\n");
|
||||
res_data = 1;
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4);
|
||||
break;
|
||||
case ONLINE_OP_QUERY_RECORD_PACKAGE_LENGTH:
|
||||
y_printf("ONLINE_OP_QUERY_RECORD_PACKAGE_LENGTH\n");
|
||||
if (mic_dut_cmd.data == 0) {
|
||||
res_data = RECORD_CH0_LENGTH;
|
||||
} else if (mic_dut_cmd.data == 1) {
|
||||
res_data = RECORD_CH1_LENGTH;
|
||||
} else {
|
||||
res_data = RECORD_CH2_LENGTH;
|
||||
}
|
||||
printf("query record ch%d packet length:%d\n", mic_dut_cmd.data, res_data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4); //回复对应的通道数据长度
|
||||
break;
|
||||
case MIC_DUT_INFO_QUERY:
|
||||
y_printf("MIC_DUT_INFO_QUERY\n");
|
||||
/*获取mic dut硬件数据*/
|
||||
audio_mic_dut_info_get(&mic_info);
|
||||
/*在线数据初始化*/
|
||||
mic_dut_online_init();
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&mic_info, sizeof(mic_info));
|
||||
break;
|
||||
case MIC_DUT_GAIN_SET:
|
||||
y_printf("MIC_DUT_GAIN_SET:%d\n", mic_dut_cmd.data);
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->mic_gain = mic_dut_cmd.data;
|
||||
}
|
||||
audio_mic_dut_gain_set(mic_dut_cmd.data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_SAMPLE_RATE_SET:
|
||||
y_printf("MIC_DUT_SAMPLE_RATE_SET:%d\n", mic_dut_cmd.data);
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->sr = mic_dut_cmd.data;
|
||||
}
|
||||
audio_mic_dut_sample_rate_set(mic_dut_cmd.data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_START:
|
||||
y_printf("MIC_DUT_START\n");
|
||||
/*打开发数资源*/
|
||||
mic_dut_online_start();
|
||||
/*打开mic*/
|
||||
audio_mic_dut_start();
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->start = 1;
|
||||
}
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_STOP:
|
||||
y_printf("MIC_DUT_STOP\n");
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->start = 0;
|
||||
}
|
||||
/*关闭mic*/
|
||||
audio_mic_dut_stop();
|
||||
/*关闭发数资源*/
|
||||
mic_dut_online_stop();
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_AMIC_SEL:
|
||||
y_printf("MIC_DUT_AMIC_SEL:%d\n", mic_dut_cmd.data);
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->mic_idx = mic_dut_cmd.data;
|
||||
}
|
||||
audio_mic_dut_amic_select(mic_dut_cmd.data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_DMIC_SEL:
|
||||
y_printf("MIC_DUT_DMIC_SEL:%d\n", mic_dut_cmd.data);
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->mic_idx = mic_dut_cmd.data;
|
||||
}
|
||||
audio_mic_dut_dmic_select(mic_dut_cmd.data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_DAC_GAIN_SET:
|
||||
y_printf("MIC_DUT_DAC_GAIN_SET:%d\n", mic_dut_cmd.data);
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->dac_gain = mic_dut_cmd.data;
|
||||
}
|
||||
audio_mic_dut_dac_gain_set(mic_dut_cmd.data);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_SCAN_START:
|
||||
y_printf("MIC_DUT_SCAN_START\n");
|
||||
/*打开发数资源*/
|
||||
mic_dut_online_start();
|
||||
/*打开dac*/
|
||||
audio_mic_dut_scan_start();
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->scan_start = 1;
|
||||
}
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case MIC_DUT_SCAN_STOP:
|
||||
y_printf("MIC_DUT_SCAN_STOP\n");
|
||||
if (online_info_hdl) {
|
||||
online_info_hdl->scan_start = 0;
|
||||
}
|
||||
/*关闭dac*/
|
||||
audio_mic_dut_scan_stop();
|
||||
/*关闭发数资源*/
|
||||
mic_dut_online_stop();
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
printf("err:%d\n", err);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*获取当前设置的mic增益*/
|
||||
int mic_dut_online_get_mic_gain(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
return online_info_hdl->mic_gain;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*获取当前设置的dac增益*/
|
||||
int mic_dut_online_get_dac_gain(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
return online_info_hdl->dac_gain;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*获取当前设置的采样率*/
|
||||
int mic_dut_online_get_sample_rate(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
return online_info_hdl->sr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*获取当前使能的模拟mic*/
|
||||
u8 mic_dut_online_amic_enable_bit(void)
|
||||
{
|
||||
return mic_info.amic_enable_bit;
|
||||
}
|
||||
|
||||
/*获取当前使能的数字mic*/
|
||||
u8 mic_dut_online_dmic_enable_bit(void)
|
||||
{
|
||||
return mic_info.dmic_enable_bit;
|
||||
}
|
||||
|
||||
/*获取当前在线使用的mic*/
|
||||
int mic_dut_online_get_mic_idx(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
return online_info_hdl->mic_idx;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*获取mic dut状态*/
|
||||
int mic_dut_online_get_mic_state(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
return online_info_hdl->start;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*获取dut scan状态*/
|
||||
int mic_dut_online_get_scan_state(void)
|
||||
{
|
||||
if (online_info_hdl) {
|
||||
return online_info_hdl->scan_start;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*注册mic dut解析回调*/
|
||||
int aud_mic_dut_open(void)
|
||||
{
|
||||
app_online_db_register_handle(DB_PKT_TYPE_MIC_DUT, mic_dut_online_parse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aud_mic_dut_close(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /*((defined TCFG_AUDIO_MIC_DUT_ENABLE) && TCFG_AUDIO_MIC_DUT_ENABLE)*/
|
||||
68
apps/common/audio/online_debug/aud_mic_dut.h
Normal file
68
apps/common/audio/online_debug/aud_mic_dut.h
Normal file
@ -0,0 +1,68 @@
|
||||
#ifndef _AUD_MIC_DUT_H_
|
||||
#define _AUD_MIC_DUT_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
|
||||
#define MIC_DUT_DATA_SEND_BY_TIMER 0 /*1:使用定时器发spp数据,0:使用任务发数*/
|
||||
|
||||
/*定时器发送间隔*/
|
||||
#define MIC_DATA_SEND_INTERVAL 4
|
||||
|
||||
//MIC采样率bitmap
|
||||
#define MIC_ADC_SR_8000 BIT(0)
|
||||
#define MIC_ADC_SR_11025 BIT(1)
|
||||
#define MIC_ADC_SR_12000 BIT(2)
|
||||
#define MIC_ADC_SR_16000 BIT(3)
|
||||
#define MIC_ADC_SR_22050 BIT(4)
|
||||
#define MIC_ADC_SR_24000 BIT(5)
|
||||
#define MIC_ADC_SR_32000 BIT(6)
|
||||
#define MIC_ADC_SR_44100 BIT(7)
|
||||
#define MIC_ADC_SR_48000 BIT(8)
|
||||
|
||||
typedef struct {
|
||||
u16 version;
|
||||
u16 amic_enable_bit; /*模拟MIC使能位:AMIC0-AMIC15,默认使能模拟MIC最低使能位*/
|
||||
u16 dmic_enable_bit; /*数字MIC使能位:DMIC0-DMIC15*/
|
||||
u8 channel; /*声道*/
|
||||
u8 bit_wide; /*位宽,有符号*/
|
||||
u32 sr_enable_bit; /*采样率支持列表使能位*/
|
||||
u32 sr_default; /*采样率默认值:16000*/
|
||||
u16 mic_gain; /*MIC增益范围*/
|
||||
u16 mic_gain_default; /*MIC增益默认值*/
|
||||
u16 dac_gain; /*DAC增益范围*/
|
||||
u16 dac_gain_default; /*DAC增益默认值*/
|
||||
} mic_dut_info_t;
|
||||
|
||||
|
||||
/*获取当前设置的mic增益*/
|
||||
int mic_dut_online_get_mic_gain(void);
|
||||
|
||||
/*获取当前设置的dac增益*/
|
||||
int mic_dut_online_get_dac_gain(void);
|
||||
|
||||
/*获取当前设置的采样率*/
|
||||
int mic_dut_online_get_sample_rate(void);
|
||||
|
||||
/*获取当前使能的模拟mic*/
|
||||
u8 mic_dut_online_amic_enable_bit(void);
|
||||
|
||||
/*获取当前使能的数字mic*/
|
||||
u8 mic_dut_online_dmic_enable_bit(void);
|
||||
|
||||
/*获取当前在线使用的mic*/
|
||||
int mic_dut_online_get_mic_idx(void);
|
||||
|
||||
/*获取mic dut状态*/
|
||||
int mic_dut_online_get_mic_state(void);
|
||||
|
||||
/*获取dut scan状态*/
|
||||
int mic_dut_online_get_scan_state(void);
|
||||
|
||||
|
||||
int aud_mic_dut_open(void);
|
||||
int aud_mic_dut_close(void);
|
||||
|
||||
|
||||
#endif/*_AUD_MIC_DUT_H_*/
|
||||
|
||||
160
apps/common/audio/online_debug/aud_spatial_effect_dut.c
Normal file
160
apps/common/audio/online_debug/aud_spatial_effect_dut.c
Normal file
@ -0,0 +1,160 @@
|
||||
#include "aud_spatial_effect_dut.h"
|
||||
#include "audio_online_debug.h"
|
||||
#include "config/config_interface.h"
|
||||
#include "app_config.h"
|
||||
#include "os/os_api.h"
|
||||
#include "classic/tws_api.h"
|
||||
#include "timer.h"
|
||||
|
||||
#if (defined(TCFG_AUDIO_SPATIAL_EFFECT_ENABLE) && TCFG_AUDIO_SPATIAL_EFFECT_ENABLE && TCFG_SPATIAL_EFFECT_ONLINE_ENABLE)
|
||||
|
||||
#define IMU_DATA_SEND_INTERVAL 100
|
||||
// 配置参数
|
||||
typedef struct _RP_PARM_CONIFG {
|
||||
int trackKIND; //角度合成算法选择: P360_T0或者P360_T1
|
||||
int ReverbKIND; //混响算法选择:P360_R0或者P360_R1
|
||||
int reverbance; //混响值 : 0到100
|
||||
int dampingval; //高频decay:0到80
|
||||
} RP_PARM_CONIFG;
|
||||
static RP_PARM_CONIFG parmK;
|
||||
|
||||
extern void spatial_effect_online_updata(RP_PARM_CONIFG *params);
|
||||
extern void get_spatial_effect_reverb_params(RP_PARM_CONIFG *params);
|
||||
|
||||
static u32 send_timer = 0;
|
||||
static int global_angle = 0;
|
||||
|
||||
int set_bt_media_imu_angle(int angle)
|
||||
{
|
||||
global_angle = angle;
|
||||
return global_angle;
|
||||
}
|
||||
|
||||
void spatial_effect_imu_dut_data_timer(void *p)
|
||||
{
|
||||
int tmp_angle = 0;
|
||||
extern u8 bt_media_is_running(void);
|
||||
#if TCFG_USER_TWS_ENABLE
|
||||
/*TWS连接的时候*/
|
||||
if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) {
|
||||
/*主机发送角度*/
|
||||
if (tws_api_get_role() == TWS_ROLE_MASTER) {
|
||||
/*播歌的时候*/
|
||||
if (bt_media_is_running()) {
|
||||
tmp_angle = global_angle;
|
||||
if (tmp_angle > 180) {
|
||||
tmp_angle = tmp_angle - 360;
|
||||
}
|
||||
int buf[2];
|
||||
buf[0] = SPATIAL_EFFECT_IMU_DUT_DATA;
|
||||
buf[1] = tmp_angle;
|
||||
/* app_online_db_send(DB_PKT_TYPE_SPATIAL_EFFECT, buf, sizeof(buf)); */
|
||||
app_online_db_send_more(DB_PKT_TYPE_SPATIAL_EFFECT, buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
} else
|
||||
#endif /*TCFG_USER_TWS_ENABLE*/
|
||||
{
|
||||
/*没有tws连接的时候*/
|
||||
if (bt_media_is_running()) {/*发送播歌角度*/
|
||||
tmp_angle = global_angle;
|
||||
if (tmp_angle > 180) {
|
||||
tmp_angle = tmp_angle - 360;
|
||||
}
|
||||
int buf[2];
|
||||
buf[0] = SPATIAL_EFFECT_IMU_DUT_DATA;
|
||||
buf[1] = tmp_angle;
|
||||
/* app_online_db_send(DB_PKT_TYPE_SPATIAL_EFFECT, buf, sizeof(buf)); */
|
||||
app_online_db_send_more(DB_PKT_TYPE_SPATIAL_EFFECT, buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int spatial_effect_imu_dut_start()
|
||||
{
|
||||
|
||||
if (send_timer == 0) {
|
||||
send_timer = usr_timer_add(NULL, spatial_effect_imu_dut_data_timer, IMU_DATA_SEND_INTERVAL, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int spatial_effect_imu_dut_stop()
|
||||
{
|
||||
if (send_timer) {
|
||||
usr_timer_del(send_timer);
|
||||
send_timer = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int spatial_effect_online_parse(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)
|
||||
{
|
||||
put_buf(packet, size);
|
||||
int res_data = 0;
|
||||
int err = 0;
|
||||
u8 parse_seq = ext_data[1];
|
||||
int cmd;
|
||||
memcpy(&cmd, packet, sizeof(cmd));
|
||||
u8 *data = &packet[4];
|
||||
|
||||
printf("[SPATIAL EFFECT]cmd:0x%x\n", cmd);
|
||||
switch (cmd) {
|
||||
case SPATIAL_EFFECT_REVERB_INFO_QUERY:
|
||||
printf("SPATIAL_EFFECT_REVERB_INFO_QUERY\n");
|
||||
get_spatial_effect_reverb_params(&parmK);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&parmK, sizeof(parmK));
|
||||
break;
|
||||
|
||||
case SPATIAL_EFFECT_REVERB_PARAM:
|
||||
printf("SPATIAL_EFFECT_REVERB_PARAM\n");
|
||||
memcpy(&parmK, data, sizeof(parmK));
|
||||
|
||||
spatial_effect_online_updata(&parmK);
|
||||
|
||||
printf("%s\n trackKIND:%d, ReverbKIND:%d, reverbance:%d, dampingval:%d\n", __func__,
|
||||
parmK.trackKIND, parmK.ReverbKIND, parmK.reverbance, parmK.dampingval);
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case SPATIAL_EFFECT_IMU_TRIM:
|
||||
printf("SPATIAL_EFFECT_IMU_TRIM\n");
|
||||
static int tmp = -2;
|
||||
|
||||
extern int spatial_imu_trim_start();
|
||||
spatial_imu_trim_start();
|
||||
|
||||
/*测试代码*/
|
||||
res_data = 0;
|
||||
err = app_online_db_ack(parse_seq, (u8 *)&res_data, 4);
|
||||
break;
|
||||
case SPATIAL_EFFECT_IMU_DUT_START:
|
||||
printf("SPATIAL_EFFECT_IMU_DUT_START\n");
|
||||
spatial_effect_imu_dut_start();
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
case SPATIAL_EFFECT_IMU_DUT_STOP:
|
||||
printf("SPATIAL_EFFECT_IMU_DUT_STOP\n");
|
||||
spatial_effect_imu_dut_stop();
|
||||
err = app_online_db_ack(parse_seq, (u8 *)"OK", 2);
|
||||
break;
|
||||
default :
|
||||
break;
|
||||
}
|
||||
printf("err:%d\n", err);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aud_spatial_effect_dut_open()
|
||||
{
|
||||
app_online_db_register_handle(DB_PKT_TYPE_SPATIAL_EFFECT, spatial_effect_online_parse);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int aud_spatial_effect_dut_close()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /*(defined(TCFG_SPATIAL_EFFECT_ONLINE_ENABLE) && (TCFG_SPATIAL_EFFECT_ONLINE_ENABLE == 1))*/
|
||||
9
apps/common/audio/online_debug/aud_spatial_effect_dut.h
Normal file
9
apps/common/audio/online_debug/aud_spatial_effect_dut.h
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
#ifndef _AUD_SPATIAL_EFFECT_DUT__
|
||||
#define _AUD_SPATIAL_EFFECT_DUT__
|
||||
|
||||
|
||||
int aud_spatial_effect_dut_open();
|
||||
int aud_spatial_effect_dut_close();
|
||||
|
||||
#endif _AUD_SPATIAL_EFFECT_DUT__
|
||||
52
apps/common/audio/online_debug/audio_online_debug.c
Normal file
52
apps/common/audio/online_debug/audio_online_debug.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include "audio_online_debug.h"
|
||||
#include "system/includes.h"
|
||||
#include "generic/list.h"
|
||||
#include "aud_mic_dut.h"
|
||||
#include "aud_data_export.h"
|
||||
#include "aud_spatial_effect_dut.h"
|
||||
#include "board_config.h"
|
||||
|
||||
typedef struct {
|
||||
struct list_head parser_head;
|
||||
|
||||
} aud_online_ctx_t;
|
||||
aud_online_ctx_t *aud_online_ctx = NULL;
|
||||
|
||||
int audio_online_debug_init(void)
|
||||
{
|
||||
//aud_online_ctx = zalloc(sizeof(aud_online_ctx_t));
|
||||
if (aud_online_ctx) {
|
||||
//INIT_LIST_HEAD(&aud_online_ctx->parser_head);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int audio_online_debug_open()
|
||||
{
|
||||
/*空间音频陀螺仪数据导出*/
|
||||
#if (TCFG_SENSOR_DATA_EXPORT_ENABLE == SENSOR_DATA_EXPORT_USE_SPP)
|
||||
aud_data_export_open();
|
||||
#endif /*TCFG_SENSOR_DATA_EXPORT_ENABLE*/
|
||||
|
||||
/*麦克风测试*/
|
||||
#if (defined(TCFG_AUDIO_MIC_DUT_ENABLE) && (TCFG_AUDIO_MIC_DUT_ENABLE == 1))
|
||||
aud_mic_dut_open();
|
||||
#endif/*TCFG_AUDIO_MIC_DUT_ENABLE*/
|
||||
|
||||
/*空间音效在线调试*/
|
||||
#if (defined(TCFG_SPATIAL_EFFECT_ONLINE_ENABLE) && (TCFG_SPATIAL_EFFECT_ONLINE_ENABLE == 1))
|
||||
aud_spatial_effect_dut_open();
|
||||
#endif /*(defined(TCFG_SPATIAL_EFFECT_ONLINE_ENABLE) && (TCFG_SPATIAL_EFFECT_ONLINE_ENABLE == 1))*/
|
||||
return 0;
|
||||
}
|
||||
__initcall(audio_online_debug_open);
|
||||
|
||||
int audio_online_debug_close()
|
||||
{
|
||||
if (aud_online_ctx) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
45
apps/common/audio/online_debug/audio_online_debug.h
Normal file
45
apps/common/audio/online_debug/audio_online_debug.h
Normal file
@ -0,0 +1,45 @@
|
||||
#ifndef _AUD_ONLINE_DEBUG_
|
||||
#define _AUD_ONLINE_DEBUG_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
#include "online_db_deal.h"
|
||||
|
||||
enum {
|
||||
AUD_RECORD_COUNT = 0x200,
|
||||
AUD_RECORD_START,
|
||||
AUD_RECORD_STOP,
|
||||
ONLINE_OP_QUERY_RECORD_PACKAGE_LENGTH,
|
||||
|
||||
MIC_DUT_INFO_QUERY = 0x300,
|
||||
MIC_DUT_GAIN_SET,
|
||||
MIC_DUT_SAMPLE_RATE_SET,
|
||||
MIC_DUT_START,
|
||||
MIC_DUT_STOP,
|
||||
MIC_DUT_AMIC_SEL,
|
||||
MIC_DUT_DMIC_SEL,
|
||||
MIC_DUT_DAC_GAIN_SET,
|
||||
MIC_DUT_SCAN_START,
|
||||
MIC_DUT_SCAN_STOP,
|
||||
|
||||
|
||||
SPATIAL_EFFECT_REVERB_PARAM = 0x400,
|
||||
SPATIAL_EFFECT_IMU_TRIM,
|
||||
SPATIAL_EFFECT_IMU_DUT_START,
|
||||
SPATIAL_EFFECT_IMU_DUT_STOP,
|
||||
SPATIAL_EFFECT_IMU_DUT_DATA,
|
||||
SPATIAL_EFFECT_REVERB_INFO_QUERY,
|
||||
};
|
||||
|
||||
#define RECORD_CH0_LENGTH 644
|
||||
#define RECORD_CH1_LENGTH 644
|
||||
#define RECORD_CH2_LENGTH 644
|
||||
|
||||
typedef struct {
|
||||
int cmd;
|
||||
int data;
|
||||
} online_cmd_t;
|
||||
|
||||
int audio_online_debug_open();
|
||||
|
||||
|
||||
#endif/*_AUD_ONLINE_DEBUG_*/
|
||||
410
apps/common/audio/sine_make.c
Normal file
410
apps/common/audio/sine_make.c
Normal file
@ -0,0 +1,410 @@
|
||||
/*****************************************************************
|
||||
>file name : apps/common/sine_make.c
|
||||
>author : lichao
|
||||
>create time : Sun 05 May 2019 08:37:35 PM CST
|
||||
*****************************************************************/
|
||||
#include "system/includes.h"
|
||||
#include "sine_make.h"
|
||||
|
||||
#define SINE_USE_MALLOC 1
|
||||
|
||||
struct audio_sin_maker {
|
||||
u8 open;
|
||||
u8 id;
|
||||
u8 sin_num;
|
||||
u8 channel;
|
||||
u8 repeat;
|
||||
u8 next_param;
|
||||
u16 fade_points;
|
||||
/*int sample_rate;*/
|
||||
int volume;
|
||||
int points;
|
||||
int sin_index;
|
||||
int win_sin_index;
|
||||
const struct sin_param *sin;
|
||||
};
|
||||
|
||||
#ifndef SINE_USE_MALLOC
|
||||
static struct audio_sin_maker sin_maker_handle;
|
||||
#endif
|
||||
|
||||
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat)
|
||||
{
|
||||
if (!param || !num) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SINE_USE_MALLOC
|
||||
struct audio_sin_maker *sin = zalloc(sizeof(struct audio_sin_maker));
|
||||
#else
|
||||
struct audio_sin_maker *sin = &sin_maker_handle;
|
||||
#endif
|
||||
|
||||
if (!sin) {
|
||||
return NULL;
|
||||
}
|
||||
if (sin->open) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sin->sin = param;
|
||||
sin->sin_num = num;
|
||||
sin->open = 1;
|
||||
sin->points = param[0].points;
|
||||
sin->id = 0;
|
||||
sin->channel = channel;
|
||||
sin->repeat = repeat;
|
||||
#if (defined CONFIG_CPU_BR18 || \
|
||||
defined CONFIG_CPU_BR21)
|
||||
/*这里如果加多fade points,会导致结束的时候有噪声,不是在淡出尾部*/
|
||||
sin->fade_points = 0;
|
||||
#else
|
||||
sin->fade_points = 480;
|
||||
#endif
|
||||
sin->next_param = 1;
|
||||
|
||||
return (void *)sin;
|
||||
}
|
||||
#if !defined(SINE_MAKE_IN_MASK)
|
||||
const int sf_sin_tab1[513] = {
|
||||
0x00000000, 0x0000c910, 0x0001921f, 0x00025b2d, 0x0003243a, 0x0003ed45, 0x0004b64e, 0x00057f53,
|
||||
0x00064855, 0x00071154, 0x0007da4e, 0x0008a343, 0x00096c33, 0x000a351d, 0x000afe00, 0x000bc6dd,
|
||||
0x000c8fb3, 0x000d5881, 0x000e2147, 0x000eea03, 0x000fb2b7, 0x00107b61, 0x00114401, 0x00120c96,
|
||||
0x0012d521, 0x00139d9f, 0x00146611, 0x00152e77, 0x0015f6d0, 0x0016bf1b, 0x00178758, 0x00184f87,
|
||||
0x001917a7, 0x0019dfb7, 0x001aa7b7, 0x001b6fa7, 0x001c3786, 0x001cff53, 0x001dc70f, 0x001e8eb8,
|
||||
0x001f564e, 0x00201dd1, 0x0020e541, 0x0021ac9b, 0x002273e2, 0x00233b13, 0x0024022e, 0x0024c933,
|
||||
0x00259021, 0x002656f8, 0x00271db7, 0x0027e45f, 0x0028aaed, 0x00297163, 0x002a37bf, 0x002afe01,
|
||||
0x002bc429, 0x002c8a35, 0x002d5026, 0x002e15fb, 0x002edbb4, 0x002fa14f, 0x003066ce, 0x00312c2e,
|
||||
0x0031f170, 0x0032b694, 0x00337b98, 0x0034407c, 0x00350540, 0x0035c9e4, 0x00368e66, 0x003752c6,
|
||||
0x00381705, 0x0038db21, 0x00399f19, 0x003a62ef, 0x003b26a0, 0x003bea2c, 0x003cad94, 0x003d70d7,
|
||||
0x003e33f3, 0x003ef6e9, 0x003fb9b8, 0x00407c60, 0x00413ee0, 0x00420138, 0x0042c367, 0x0043856d,
|
||||
0x0044474a, 0x004508fc, 0x0045ca83, 0x00468be0, 0x00474d11, 0x00480e16, 0x0048ceef, 0x00498f9a,
|
||||
0x004a5019, 0x004b1069, 0x004bd08b, 0x004c907f, 0x004d5043, 0x004e0fd8, 0x004ecf3c, 0x004f8e70,
|
||||
0x00504d72, 0x00510c43, 0x0051cae3, 0x0052894f, 0x00534789, 0x0054058f, 0x0054c362, 0x00558100,
|
||||
0x00563e6a, 0x0056fb9e, 0x0057b89d, 0x00587565, 0x005931f7, 0x0059ee52, 0x005aaa76, 0x005b6662,
|
||||
0x005c2215, 0x005cdd8f, 0x005d98d0, 0x005e53d8, 0x005f0ea5, 0x005fc937, 0x0060838f, 0x00613dab,
|
||||
0x0061f78b, 0x0062b12e, 0x00636a95, 0x006423be, 0x0064dcaa, 0x00659557, 0x00664dc6, 0x006705f5,
|
||||
0x0067bde5, 0x00687595, 0x00692d05, 0x0069e433, 0x006a9b21, 0x006b51cc, 0x006c0836, 0x006cbe5c,
|
||||
0x006d7440, 0x006e29e0, 0x006edf3d, 0x006f9454, 0x00704927, 0x0070fdb5, 0x0071b1fd, 0x007265ff,
|
||||
0x007319ba, 0x0073cd2f, 0x0074805c, 0x00753341, 0x0075e5dd, 0x00769831, 0x00774a3c, 0x0077fbfe,
|
||||
0x0078ad75, 0x00795ea2, 0x007a0f84, 0x007ac01a, 0x007b7065, 0x007c2064, 0x007cd016, 0x007d7f7c,
|
||||
0x007e2e93, 0x007edd5d, 0x007f8bd9, 0x00803a06, 0x0080e7e4, 0x00819573, 0x008242b1, 0x0082ef9f,
|
||||
0x00839c3d, 0x00844889, 0x0084f484, 0x0085a02c, 0x00864b82, 0x0086f686, 0x0087a136, 0x00884b92,
|
||||
0x0088f59b, 0x00899f4e, 0x008a48ad, 0x008af1b7, 0x008b9a6b, 0x008c42c9, 0x008cead0, 0x008d9281,
|
||||
0x008e39da, 0x008ee0db, 0x008f8784, 0x00902dd5, 0x0090d3cd, 0x0091796b, 0x00921eb0, 0x0092c39a,
|
||||
0x0093682a, 0x00940c5f, 0x0094b039, 0x009553b7, 0x0095f6d9, 0x0096999f, 0x00973c07, 0x0097de12,
|
||||
0x00987fc0, 0x0099210f, 0x0099c200, 0x009a6293, 0x009b02c6, 0x009ba299, 0x009c420c, 0x009ce11f,
|
||||
0x009d7fd1, 0x009e1e22, 0x009ebc12, 0x009f599f, 0x009ff6cb, 0x00a09393, 0x00a12ff9, 0x00a1cbfb,
|
||||
0x00a26799, 0x00a302d3, 0x00a39da9, 0x00a4381a, 0x00a4d225, 0x00a56bcb, 0x00a6050a, 0x00a69de3,
|
||||
0x00a73656, 0x00a7ce61, 0x00a86605, 0x00a8fd41, 0x00a99415, 0x00aa2a80, 0x00aac082, 0x00ab561b,
|
||||
0x00abeb4a, 0x00ac800f, 0x00ad1469, 0x00ada859, 0x00ae3bde, 0x00aecef7, 0x00af61a5, 0x00aff3e6,
|
||||
0x00b085bb, 0x00b11722, 0x00b1a81d, 0x00b238aa, 0x00b2c8c9, 0x00b3587a, 0x00b3e7bc, 0x00b4768f,
|
||||
0x00b504f3, 0x00b592e7, 0x00b6206c, 0x00b6ad7f, 0x00b73a23, 0x00b7c655, 0x00b85216, 0x00b8dd65,
|
||||
0x00b96842, 0x00b9f2ac, 0x00ba7ca4, 0x00bb0629, 0x00bb8f3b, 0x00bc17d9, 0x00bca003, 0x00bd27b8,
|
||||
0x00bdaef9, 0x00be35c5, 0x00bebc1b, 0x00bf41fc, 0x00bfc767, 0x00c04c5c, 0x00c0d0da, 0x00c154e1,
|
||||
0x00c1d870, 0x00c25b89, 0x00c2de29, 0x00c36051, 0x00c3e200, 0x00c46337, 0x00c4e3f5, 0x00c56439,
|
||||
0x00c5e403, 0x00c66354, 0x00c6e22a, 0x00c76085, 0x00c7de65, 0x00c85bca, 0x00c8d8b3, 0x00c95521,
|
||||
0x00c9d112, 0x00ca4c87, 0x00cac77f, 0x00cb41fa, 0x00cbbbf8, 0x00cc3578, 0x00ccae79, 0x00cd26fd,
|
||||
0x00cd9f02, 0x00ce1689, 0x00ce8d90, 0x00cf0417, 0x00cf7a1f, 0x00cfefa8, 0x00d064af, 0x00d0d937,
|
||||
0x00d14d3d, 0x00d1c0c2, 0x00d233c6, 0x00d2a649, 0x00d31849, 0x00d389c7, 0x00d3fac3, 0x00d46b3b,
|
||||
0x00d4db31, 0x00d54aa4, 0x00d5b993, 0x00d627fe, 0x00d695e5, 0x00d70348, 0x00d77026, 0x00d7dc7f,
|
||||
0x00d84853, 0x00d8b3a1, 0x00d91e6a, 0x00d988ad, 0x00d9f26a, 0x00da5ba0, 0x00dac450, 0x00db2c79,
|
||||
0x00db941a, 0x00dbfb34, 0x00dc61c7, 0x00dcc7d1, 0x00dd2d53, 0x00dd924d, 0x00ddf6be, 0x00de5aa6,
|
||||
0x00debe05, 0x00df20db, 0x00df8327, 0x00dfe4e9, 0x00e04621, 0x00e0a6cf, 0x00e106f2, 0x00e1668a,
|
||||
0x00e1c598, 0x00e2241a, 0x00e28210, 0x00e2df7b, 0x00e33c5a, 0x00e398ac, 0x00e3f473, 0x00e44fac,
|
||||
0x00e4aa59, 0x00e50479, 0x00e55e0b, 0x00e5b710, 0x00e60f88, 0x00e66771, 0x00e6becc, 0x00e71599,
|
||||
0x00e76bd8, 0x00e7c187, 0x00e816a8, 0x00e86b39, 0x00e8bf3c, 0x00e912ae, 0x00e96591, 0x00e9b7e4,
|
||||
0x00ea09a7, 0x00ea5ad9, 0x00eaab7b, 0x00eafb8c, 0x00eb4b0c, 0x00eb99fb, 0x00ebe858, 0x00ec3624,
|
||||
0x00ec835e, 0x00ecd007, 0x00ed1c1d, 0x00ed67a1, 0x00edb293, 0x00edfcf2, 0x00ee46be, 0x00ee8ff8,
|
||||
0x00eed89e, 0x00ef20b0, 0x00ef6830, 0x00efaf1b, 0x00eff573, 0x00f03b37, 0x00f08066, 0x00f0c501,
|
||||
0x00f10908, 0x00f14c7a, 0x00f18f57, 0x00f1d19f, 0x00f21352, 0x00f25470, 0x00f294f8, 0x00f2d4eb,
|
||||
0x00f31447, 0x00f3530e, 0x00f3913f, 0x00f3ced9, 0x00f40bdd, 0x00f4484b, 0x00f48422, 0x00f4bf62,
|
||||
0x00f4fa0b, 0x00f5341d, 0x00f56d97, 0x00f5a67b, 0x00f5dec6, 0x00f6167a, 0x00f64d97, 0x00f6841b,
|
||||
0x00f6ba07, 0x00f6ef5b, 0x00f72417, 0x00f7583a, 0x00f78bc5, 0x00f7beb7, 0x00f7f110, 0x00f822d1,
|
||||
0x00f853f8, 0x00f88486, 0x00f8b47b, 0x00f8e3d6, 0x00f91298, 0x00f940c0, 0x00f96e4e, 0x00f99b43,
|
||||
0x00f9c79d, 0x00f9f35e, 0x00fa1e84, 0x00fa4910, 0x00fa7302, 0x00fa9c59, 0x00fac516, 0x00faed37,
|
||||
0x00fb14be, 0x00fb3bab, 0x00fb61fc, 0x00fb87b2, 0x00fbaccd, 0x00fbd14d, 0x00fbf531, 0x00fc187a,
|
||||
0x00fc3b28, 0x00fc5d3a, 0x00fc7eb0, 0x00fc9f8a, 0x00fcbfc9, 0x00fcdf6c, 0x00fcfe73, 0x00fd1cdd,
|
||||
0x00fd3aac, 0x00fd57de, 0x00fd7474, 0x00fd906e, 0x00fdabcc, 0x00fdc68c, 0x00fde0b1, 0x00fdfa38,
|
||||
0x00fe1324, 0x00fe2b72, 0x00fe4323, 0x00fe5a38, 0x00fe70b0, 0x00fe868b, 0x00fe9bc9, 0x00feb069,
|
||||
0x00fec46d, 0x00fed7d4, 0x00feea9d, 0x00fefcc9, 0x00ff0e58, 0x00ff1f49, 0x00ff2f9d, 0x00ff3f54,
|
||||
0x00ff4e6d, 0x00ff5ce9, 0x00ff6ac7, 0x00ff7808, 0x00ff84ab, 0x00ff90b1, 0x00ff9c18, 0x00ffa6e3,
|
||||
0x00ffb10f, 0x00ffba9e, 0x00ffc38f, 0x00ffcbe2, 0x00ffd397, 0x00ffdaaf, 0x00ffe129, 0x00ffe705,
|
||||
0x00ffec43, 0x00fff0e3, 0x00fff4e6, 0x00fff84a, 0x00fffb11, 0x00fffd39, 0x00fffec4, 0x00ffffb1,
|
||||
0x00ffffff,
|
||||
};
|
||||
#else
|
||||
extern const int sf_sin_tab1[513] ;
|
||||
#endif
|
||||
|
||||
|
||||
#define SINE_INT_ZOOM 16384
|
||||
#define SINE_INT_ZBIT 14
|
||||
#define __int64 long long
|
||||
/*软件索引实现sin生成*/
|
||||
static int get_sine_value(int mx_idx)
|
||||
{
|
||||
int ret = 0;
|
||||
int idx = 0;
|
||||
int tm_idx = mx_idx & 0x1FFFFFF; //2^25
|
||||
int phase = tm_idx & 0x3FFF;
|
||||
int tp_idx0 = tm_idx >> 14;
|
||||
int tp_idx1 = tp_idx0 + 1;
|
||||
int sign = 1, dt0, dt1;
|
||||
|
||||
if (tp_idx0 > 1024) {
|
||||
sign = -1;
|
||||
tp_idx0 = 2048 - tp_idx0;
|
||||
}
|
||||
if (tp_idx0 < 513) {
|
||||
dt0 = sf_sin_tab1[tp_idx0];
|
||||
} else {
|
||||
dt0 = sf_sin_tab1[1024 - tp_idx0];
|
||||
}
|
||||
|
||||
if (tp_idx1 > 1024) {
|
||||
sign = -1;
|
||||
tp_idx1 = 2048 - tp_idx1;
|
||||
}
|
||||
if (tp_idx1 < 513) {
|
||||
dt1 = sf_sin_tab1[tp_idx1];
|
||||
} else {
|
||||
dt1 = sf_sin_tab1[1024 - tp_idx1];
|
||||
}
|
||||
|
||||
ret = ((__int64)dt0 * (SINE_INT_ZOOM - phase) + (__int64)dt1 * phase) >> SINE_INT_ZBIT;
|
||||
|
||||
ret *= sign;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void hw_sin_value(int a, int *sin_res, u8 precision)
|
||||
{
|
||||
u64 s64 = a;
|
||||
|
||||
*sin_res = __asm_sine(s64, precision);
|
||||
}
|
||||
|
||||
int sin_tone_make(void *_maker, void *data, int len)
|
||||
{
|
||||
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
|
||||
s16 *pcm = (s16 *)data;
|
||||
int sin_value = 0;
|
||||
int win_sin_value = 0;
|
||||
int add_idx = 0, sub_vol = 0, win_add_idx = 0;
|
||||
int offset = 0;
|
||||
u8 id = maker->id;
|
||||
u8 sin_num = maker->sin_num;
|
||||
u8 repeat = maker->repeat;
|
||||
u8 channel = maker->channel;
|
||||
int sin_index;
|
||||
int win_sin_index;
|
||||
int volume;
|
||||
u32 reamin_points = len / 2 / channel;
|
||||
|
||||
do {
|
||||
if (maker->next_param) {
|
||||
maker->volume = SINE_TOTAL_VOLUME;
|
||||
maker->sin_index = 0;
|
||||
maker->win_sin_index = 0;
|
||||
maker->next_param = 0;
|
||||
}
|
||||
|
||||
u8 win = maker->sin[id].win;
|
||||
add_idx = ((u64)(1 << 25) * maker->sin[id].freq / DEFAULT_SINE_SAMPLE_RATE) >> 9;
|
||||
if (win) {
|
||||
win_add_idx = ((u64)(1 << 25) * maker->sin[id].decay / DEFAULT_SINE_SAMPLE_RATE) >> 9;
|
||||
/*sub_vol = 0;*/
|
||||
} else {
|
||||
sub_vol = maker->sin[id].decay;
|
||||
}
|
||||
|
||||
sin_index = maker->sin_index;
|
||||
win_sin_index = maker->win_sin_index;
|
||||
volume = maker->volume;
|
||||
u32 points = 0;
|
||||
if (maker->fade_points) {
|
||||
points = maker->fade_points > reamin_points ? reamin_points : maker->fade_points;
|
||||
sub_vol = 0;
|
||||
maker->fade_points -= points;
|
||||
} else {
|
||||
points = maker->points > reamin_points ? reamin_points : maker->points;
|
||||
maker->points -= points;
|
||||
}
|
||||
reamin_points -= points;
|
||||
while (points--) {
|
||||
/*hw_sin_value(sin_index, &sin_value, 0);*/
|
||||
sin_value = __asm_sine((s64)sin_index, 2);
|
||||
if (win) {
|
||||
/*hw_sin_value(win_sin_index, &win_sin_value, 0);*/
|
||||
win_sin_value = __asm_sine((s64)win_sin_index, 2);
|
||||
#if ((defined CONFIG_CPU_BR36) || (defined CONFIG_CPU_BR28))
|
||||
sin_value = ((s64)sin_value * (s64)win_sin_value) >> 44;
|
||||
#else
|
||||
sin_value = ((s64)sin_value * (s64)win_sin_value) >> 34;
|
||||
#endif
|
||||
win_sin_index += win_add_idx;
|
||||
win_sin_index &= 0x1ffffff;
|
||||
} else {
|
||||
#if ((defined CONFIG_CPU_BR36) || (defined CONFIG_CPU_BR28))
|
||||
sin_value = ((s64)volume * sin_value) >> 39;
|
||||
#else
|
||||
sin_value = ((s64)volume * sin_value) >> 34;
|
||||
#endif
|
||||
}
|
||||
sin_index += add_idx;
|
||||
sin_index &= 0x1ffffff;
|
||||
|
||||
volume -= sub_vol;
|
||||
if (volume < 0) {
|
||||
volume = 0;
|
||||
}
|
||||
|
||||
*pcm++ = sin_value;
|
||||
if (channel == 2) {
|
||||
*pcm++ = sin_value;
|
||||
} else if (channel == 4) {
|
||||
*pcm++ = sin_value;
|
||||
*pcm++ = sin_value;
|
||||
*pcm++ = sin_value;
|
||||
}
|
||||
}
|
||||
|
||||
maker->volume = volume;
|
||||
maker->sin_index = sin_index;
|
||||
maker->win_sin_index = win_sin_index;
|
||||
if (!maker->points) {
|
||||
if (++id >= sin_num) {
|
||||
if (!repeat) {
|
||||
break;
|
||||
}
|
||||
id = 0;
|
||||
}
|
||||
maker->points = maker->sin[id].points;
|
||||
maker->id = id;
|
||||
maker->next_param = 1;
|
||||
}
|
||||
|
||||
if (!reamin_points) {
|
||||
break;
|
||||
}
|
||||
} while (1);
|
||||
|
||||
return len - (reamin_points * 2 * channel);
|
||||
}
|
||||
|
||||
int sin_tone_points(void *_maker)
|
||||
{
|
||||
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
|
||||
int points = 0;
|
||||
u8 i = 0;
|
||||
|
||||
for (i = 0; i < maker->sin_num; i++) {
|
||||
points += maker->sin[i].points;
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
void sin_tone_close(void *_maker)
|
||||
{
|
||||
struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker;
|
||||
|
||||
#ifdef SINE_USE_MALLOC
|
||||
if (maker) {
|
||||
free(maker);
|
||||
}
|
||||
#else
|
||||
if (sin_maker_handle.open) {
|
||||
sin_maker_handle.open = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#include "asm/math_fast_function.h"
|
||||
|
||||
#ifndef DATA16
|
||||
#define DATA16 32767
|
||||
#endif
|
||||
|
||||
/*********************************
|
||||
* fc : 正弦波中心频率
|
||||
* fs : 采样频率
|
||||
* FrameSize :每次计算输出点数
|
||||
* idx :当前计算起始indix
|
||||
* rst :结果存放地址
|
||||
* *******************************/
|
||||
void SinWave_Generator(int fc, int fs, int FrameSize, int idx, short *rst)
|
||||
{
|
||||
float tmp0, tmp1, tmp2;
|
||||
tmp0 = (float)fc / fs;
|
||||
for (int i = 0; i < FrameSize; i++) {
|
||||
tmp1 = (i + idx) * tmp0 * 2;
|
||||
tmp2 = sin_float(tmp1);
|
||||
*rst = (short)(tmp2 * DATA16);
|
||||
rst++;
|
||||
}
|
||||
}
|
||||
/*********************************
|
||||
* fs : 采样频率
|
||||
* FrameSize :每次计算输出点数
|
||||
* idx :当前计算起始indix
|
||||
* ts :期望一次扫频所持续时间
|
||||
* rst :结果存放地址
|
||||
* *******************************/
|
||||
void SweepSin_Generator(int fs, int FrameSize, int idx, float ts, short *rst)
|
||||
{
|
||||
float fp, fc, tmp1, tmp2;
|
||||
int Ncnt, NPoint, DPoint;
|
||||
|
||||
NPoint = fs * ts;
|
||||
// fp = (fs/2)/(fs*ts);
|
||||
fp = 1 / (2 * 2 * ts);
|
||||
|
||||
for (int i = 0; i < FrameSize; i++) {
|
||||
Ncnt = (i + idx) / NPoint;
|
||||
DPoint = (i + idx) - Ncnt * NPoint;
|
||||
//printf("idx:%d \n",DPoint);
|
||||
tmp1 = ((DPoint * fp) / fs) * DPoint * 2;
|
||||
tmp2 = sin_float(tmp1);
|
||||
//printf("Sin[%d]:%d",i,(int)(tmp2*1000));
|
||||
*rst = (short)(tmp2 * DATA16);
|
||||
rst++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 正弦信号生成
|
||||
* Arguments : fc 信号中心频率
|
||||
* fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int sin_idx = 0;
|
||||
void sin_pcm_fill(int fc, int fs, void *buf, u32 len)
|
||||
{
|
||||
SinWave_Generator(fc, fs, len / 2, sin_idx, buf);
|
||||
sin_idx += len / 2;
|
||||
}
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 扫频信号生成
|
||||
* Arguments : fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
int sweep_sin_idx = 0;
|
||||
void sweepsin_pcm_fill(int fs, void *buf, u32 len)
|
||||
{
|
||||
SweepSin_Generator(fs, len / 2, sweep_sin_idx, 25, buf);
|
||||
sweep_sin_idx += len / 2;
|
||||
}
|
||||
47
apps/common/audio/sine_make.h
Normal file
47
apps/common/audio/sine_make.h
Normal file
@ -0,0 +1,47 @@
|
||||
#ifndef __SINE_MAKE_H_
|
||||
#define __SINE_MAKE_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
|
||||
#define DEFAULT_SINE_SAMPLE_RATE 16000
|
||||
#define SINE_TOTAL_VOLUME 26843546//16106128//20132660 //26843546
|
||||
|
||||
struct sin_param {
|
||||
//int idx_increment;
|
||||
int freq;
|
||||
int points;
|
||||
int win;
|
||||
int decay;
|
||||
};
|
||||
|
||||
int sin_tone_make(void *_maker, void *data, int len);
|
||||
void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat);
|
||||
int sin_tone_points(void *_maker);
|
||||
void sin_tone_close(void *_maker);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 正弦信号生成
|
||||
* Arguments : fc 信号中心频率
|
||||
* fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void sin_pcm_fill(int fc, int fs, void *buf, u32 len);
|
||||
|
||||
/*
|
||||
*********************************************************************
|
||||
* Description: 扫频信号生成
|
||||
* Arguments : fs 信号采样率
|
||||
* buf 数据输出地址
|
||||
* len 数据生成长度,单位是bytes
|
||||
* Return : None.
|
||||
* Note(s) : None.
|
||||
*********************************************************************
|
||||
*/
|
||||
void sweepsin_pcm_fill(int fs, void *buf, u32 len);
|
||||
|
||||
#endif/*__SINE_MAKE_H_*/
|
||||
20
apps/common/audio/stream/stream_entry.h
Normal file
20
apps/common/audio/stream/stream_entry.h
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef __STREAM_ENTRY_H__
|
||||
#define __STREAM_ENTRY_H__
|
||||
|
||||
#include "system/includes.h"
|
||||
#include "media/includes.h"
|
||||
|
||||
// struct __stream_entry;
|
||||
struct __stream_entry {
|
||||
u8 is_end;
|
||||
void *data_priv;
|
||||
int (*data_callback)(void *priv, struct audio_data_frame *in);
|
||||
struct audio_stream_entry entry;
|
||||
};
|
||||
|
||||
struct __stream_entry *stream_entry_open(void *priv, int (*data_callback)(void *priv, struct audio_data_frame *in), u8 is_end);
|
||||
void stream_entry_close(struct __stream_entry **hdl);
|
||||
void stream_entry_resume(struct __stream_entry *hdl);
|
||||
|
||||
#endif// __STREAM_ENTRY_H__
|
||||
|
||||
129
apps/common/audio/uartPcmSender.c
Normal file
129
apps/common/audio/uartPcmSender.c
Normal file
@ -0,0 +1,129 @@
|
||||
#include "app_config.h"
|
||||
|
||||
#ifdef AUDIO_PCM_DEBUG
|
||||
#include "system/includes.h"
|
||||
#include "asm/uart_dev.h"
|
||||
#include "uartPcmSender.h"
|
||||
|
||||
static u8 uart_cbuf[32] __attribute__((aligned(4)));
|
||||
const uart_bus_t *uart_bus = NULL;
|
||||
|
||||
//设备事件响应demo
|
||||
void uart_event_handler(struct sys_event *e)
|
||||
{
|
||||
u8 uart_rxbuf[12] = {0};
|
||||
u8 uart_txbuf[12] = {0};
|
||||
const uart_bus_t *_uart_bus;
|
||||
u32 uart_rxcnt = 0;
|
||||
u8 i = 0;
|
||||
|
||||
if (0) {//!strcmp(e->arg, "uart_rx_overflow")) {
|
||||
if (e->u.dev.event == DEVICE_EVENT_CHANGE) {
|
||||
printf("uart event: %s\n", e->arg);
|
||||
_uart_bus = (const uart_bus_t *)e->u.dev.value;
|
||||
uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
|
||||
if (uart_rxcnt) {
|
||||
g_printf("rx:%s", uart_rxbuf);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (0) { //(!strcmp(e->arg, "uart_rx_outtime")) {
|
||||
if (e->u.dev.event == DEVICE_EVENT_CHANGE) {
|
||||
printf("uart event: %s\n", e->arg);
|
||||
_uart_bus = (const uart_bus_t *)e->u.dev.value;
|
||||
uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0);
|
||||
if (uart_rxcnt) {
|
||||
printf("get_buffer:\n");
|
||||
for (int i = 0; i < uart_rxcnt; i++) {
|
||||
putbyte(uart_rxbuf[i]);
|
||||
if (i % 16 == 15) {
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
if (uart_rxcnt % 16) {
|
||||
putchar('\n');
|
||||
}
|
||||
_uart_bus->write(uart_rxbuf, uart_rxcnt);
|
||||
}
|
||||
printf("uart out\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
SYS_EVENT_HANDLER(SYS_DEVICE_EVENT, uart_event_handler, 0);
|
||||
|
||||
void gpio_change(void *priv);
|
||||
static void uart_isr_hook(void *arg, u32 status)
|
||||
{
|
||||
const uart_bus_t *ubus = arg;
|
||||
struct sys_event e;
|
||||
|
||||
//当CONFIG_UARTx_ENABLE_TX_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
|
||||
21
apps/common/audio/uartPcmSender.h
Normal file
21
apps/common/audio/uartPcmSender.h
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef _UARTPCMSENDER_H_
|
||||
#define _UARTPCMSENDER_H_
|
||||
#include "system/includes.h"
|
||||
#include "app_config.h"
|
||||
/*
|
||||
*串口导出数据配置
|
||||
*注意IO口设置不要和普通log输出uart冲突
|
||||
*/
|
||||
#define PCM_UART1_TX_PORT IO_PORT_DM /*数据导出发送IO*/
|
||||
#define PCM_UART1_RX_PORT -1
|
||||
#define PCM_UART1_BAUDRATE 2000000 /*数据导出波特率,不用修改,和接收端设置一直*/
|
||||
|
||||
#if ((TCFG_UART0_ENABLE == ENABLE_THIS_MOUDLE) && (PCM_UART1_TX_PORT == TCFG_UART0_TX_PORT))
|
||||
//IO口配置冲突,请检查修改
|
||||
#error "PCM_UART1_TX_PORT conflict with TCFG_UART0_TX_PORT"
|
||||
#endif/*PCM_UART1_TX_PORT*/
|
||||
|
||||
void uartSendInit(); //串口发数初始化
|
||||
void uartSendData(void *buf, u16 len); //发送数据的接口
|
||||
|
||||
#endif /*_UARTPCMSENDER_H_*/
|
||||
414
apps/common/audio/wm8978/iic.c
Normal file
414
apps/common/audio/wm8978/iic.c
Normal file
@ -0,0 +1,414 @@
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/**@file iic_io.c
|
||||
@brief IO模拟的IIC的驱动
|
||||
@details
|
||||
@author zhiying
|
||||
@date 2013-3-26
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
#include "iic.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: IIC 模块初始化函数
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void iic_init_io(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_init_io(void)
|
||||
{
|
||||
iic_data_h();
|
||||
iic_data_out(); //SDA设置成输出
|
||||
iic_clk_h();
|
||||
iic_clk_out(); //SCL设置成输出
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief
|
||||
@param 无
|
||||
@return
|
||||
@note
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_start(void)
|
||||
{
|
||||
iic_init_io();
|
||||
iic_delay();
|
||||
iic_data_l();
|
||||
iic_delay();
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
//iic_data_h();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief STOP IIC
|
||||
@param 无
|
||||
@return 无
|
||||
@note void iic_stop(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_stop(void)
|
||||
{
|
||||
iic_data_out();
|
||||
iic_data_l();
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
iic_data_h();
|
||||
iic_delay();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 读取ACK
|
||||
@param 无
|
||||
@return 都会的ACK/NACK的电平
|
||||
@note tbool r_ack(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tbool r_ack(void)
|
||||
{
|
||||
tbool tnack;
|
||||
iic_data_in();
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
tnack = iic_data_r();
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
return tnack;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 发送一个ACK信号的数据,
|
||||
@param flag :发送的ACK/nack的类型
|
||||
@return 无
|
||||
@note void s_ack(u8 flag)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void s_ack(u8 flag)
|
||||
{
|
||||
iic_data_out();
|
||||
iic_clk_l();
|
||||
if (flag) {
|
||||
iic_data_h();
|
||||
} else {
|
||||
iic_data_l();
|
||||
}
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
iic_clk_l();
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 从IIC总线接收一个BYTE的数据,
|
||||
@param 无
|
||||
@return 读取回的数据
|
||||
@note u8 iic_revbyte_io( void )
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 iic_revbyte_io(void)
|
||||
{
|
||||
u8 tbyteI2C = 0X00;
|
||||
u8 i;
|
||||
iic_data_in();
|
||||
iic_delay();
|
||||
for (i = 0; i < 8; i++) {
|
||||
iic_clk_h();
|
||||
tbyteI2C <<= 1;
|
||||
iic_delay();
|
||||
if (iic_data_r()) {
|
||||
tbyteI2C++;
|
||||
}
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
}
|
||||
return tbyteI2C;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 从IIC总线接收一个BYTE的数据,并发送一个指定的ACK
|
||||
@param para :发送ACK 还是 NACK
|
||||
@return 读取回的数据
|
||||
@note u8 iic_revbyte( u8 para )
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 iic_revbyte(u8 para)
|
||||
{
|
||||
u8 tbyte;
|
||||
tbyte = iic_revbyte_io();
|
||||
s_ack(para);
|
||||
delay(30000);
|
||||
return tbyte;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 向IIC总线发送一个BYTE的数据
|
||||
@param byte :要写的EEROM的地址
|
||||
@return 无
|
||||
@note void iic_sendbyte_io(u8 byte)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_sendbyte_io(u8 byte)
|
||||
{
|
||||
u8 i;
|
||||
iic_data_out();
|
||||
iic_delay();
|
||||
//otp_printf("byte: %02x\n", byte);
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (byte & BIT(7)) {
|
||||
iic_data_h(); //最高位是否为1,为1则SDA= 1,否则 SDA=0
|
||||
} else {
|
||||
iic_data_l();
|
||||
}
|
||||
iic_delay();
|
||||
iic_clk_h();
|
||||
iic_delay();
|
||||
byte <<= 1; //数据左移一位,进入下一轮送数
|
||||
iic_clk_l();
|
||||
iic_delay();
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 向IIC总线发送一个BYTE的数据,并读取ACK
|
||||
@param byte :要写的EEROM的地址
|
||||
@return 无
|
||||
@note void iic_sendbyte(u8 byte)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_sendbyte(u8 byte)
|
||||
{
|
||||
iic_sendbyte_io(byte);
|
||||
r_ack();
|
||||
delay(30000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///------------------------------------------------------------------------------
|
||||
///------------------------------------IIC_API-----------------------------------
|
||||
///------------------------------------------------------------------------------
|
||||
|
||||
|
||||
bool g_iic_busy = 0; ///<iic繁忙标记
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: IIC 模块初始化函数
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void iic_init(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_init(void)
|
||||
{
|
||||
// iic_data_out();
|
||||
iic_data_h();
|
||||
iic_data_out();
|
||||
//iic_clk_out();
|
||||
iic_clk_h(); ///<配置接口函数IO
|
||||
iic_clk_out();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: eeprom 核实
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void eeprom_verify(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void eeprom_verify(void)
|
||||
{
|
||||
puts("eeprom_verify 1\n");
|
||||
|
||||
if ((read_eerom(0) != 0x55)
|
||||
|| (read_eerom(1) != 0xAA)) {
|
||||
write_eerom(0, 0x55);
|
||||
write_eerom(1, 0xAA);
|
||||
}
|
||||
|
||||
puts("eeprom_verify 2\n");
|
||||
if ((read_eerom(0) != 0x55)
|
||||
|| (read_eerom(1) != 0xAA)) {
|
||||
puts("iic-no\n");//外接eeprom无效
|
||||
} else {
|
||||
puts("iic-yes\n"); //有外接eeprom
|
||||
}
|
||||
}
|
||||
|
||||
void iic_write_one_byte(u8 iic_dat)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(iic_dat); //写数据
|
||||
iic_stop(); //I2C停止时序
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief IIC写函数
|
||||
@param chip_id :目标IC的ID号
|
||||
@param iic_addr: 目标IC的目标寄存器的地址
|
||||
@param *iic_dat: 写望目标IC的数据的指针
|
||||
@param n:需要写的数据的数目
|
||||
@return 无
|
||||
@note void iic_write(u8 chip_id,u8 iic_addr,u8 *iic_dat,u8 n)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_write(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(chip_id); //写命令
|
||||
|
||||
if (0xff != iic_addr) {
|
||||
iic_sendbyte(iic_addr); //写地址
|
||||
}
|
||||
for (; n > 0; n--) {
|
||||
iic_sendbyte(*iic_dat++); //写数据
|
||||
}
|
||||
iic_stop(); //I2C停止时序
|
||||
g_iic_busy = 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief IIC总线向一个目标ID读取几个数据
|
||||
@param address : 目标ID
|
||||
@param *p : 存档读取到的数据的buffer指针
|
||||
@param number : 需要读取的数据的个数
|
||||
@return 无
|
||||
@note void i2c_read_nbyte(u8 address,u8 *p,u8 number)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void iic_readn(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(chip_id); //写命令
|
||||
if (0xff != iic_addr) {
|
||||
iic_sendbyte(iic_addr); //写地址
|
||||
}
|
||||
for (; n > 1; n--) {
|
||||
*iic_dat++ = iic_revbyte(0); //读数据
|
||||
}
|
||||
*iic_dat++ = iic_revbyte(1);
|
||||
iic_stop(); //I2C停止时序
|
||||
g_iic_busy = 0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief EEROM/RTC RAM读函数
|
||||
@param addr :要写的EEROM/RTC RAM的地址
|
||||
@return 读到的数据
|
||||
@note u8 read_info(u8 addr)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 read_info(u8 addr)
|
||||
{
|
||||
return read_eerom(addr);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief EEROM/RTC RAM写函数
|
||||
@param addr :要读的EEROM/RTC RAM的地址
|
||||
@param dat :需要读的数据
|
||||
@return 无
|
||||
@note void write_info(u8 addr,u8 dat)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void write_info(u8 addr, u8 dat)
|
||||
{
|
||||
write_eerom(addr, dat);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief eeprom START
|
||||
@param 无
|
||||
@return 无
|
||||
@note void eeprom_page_write_start(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void eeprom_page_write_start(void)
|
||||
{
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(0xa0); //写命令
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief IIC STOP
|
||||
@param 无
|
||||
@return 无
|
||||
@note void eeprom_page_write_stop(void)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void eeprom_page_write_stop(void)
|
||||
{
|
||||
iic_stop(); //I2C停止iic_data_out
|
||||
g_iic_busy = 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief EEROM读函数
|
||||
@param addr :要写的EEROM的地址
|
||||
@param 无
|
||||
@return 无
|
||||
@note u8 iic_read(u8 iic_addr)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
tu8 read_eerom(u8 iic_addr)
|
||||
{
|
||||
u8 tbyte;
|
||||
g_iic_busy = 1;
|
||||
iic_start(); //I2C启动
|
||||
iic_sendbyte(0xa0); //写命令
|
||||
iic_sendbyte(iic_addr); //写地址
|
||||
iic_start(); //写转为读命令,需要再次启动I2C
|
||||
iic_sendbyte(0xa1); //读命令
|
||||
tbyte = iic_revbyte(1);
|
||||
iic_stop(); //I2C停止
|
||||
g_iic_busy = 0;
|
||||
return tbyte;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/**@brief 带有毫秒延时的EEROM写函数
|
||||
@param addr :要写的EEROM的地址
|
||||
@param dat :需要写的数据
|
||||
@return 无
|
||||
@note void write_info(u8 addr,u8 dat)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void write_eerom(u8 addr, u8 dat)
|
||||
{
|
||||
iic_write(0xa0, addr, &dat, 1);
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
iic_delay();
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: 记忆信息到存储器(EEPROM)
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: void set_memory(u8 addr, u8 dat)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
void set_memory(u8 addr, u8 dat)
|
||||
{
|
||||
write_eerom(addr, dat);
|
||||
}
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief: 获取记忆信息(EEPROM)
|
||||
@param: void
|
||||
@return:void
|
||||
@author:Juntham
|
||||
@note: u8 get_memory(u8 addr)
|
||||
*/
|
||||
/*----------------------------------------------------------------------------*/
|
||||
u8 get_memory(u8 addr)
|
||||
{
|
||||
return read_eerom(addr);
|
||||
}
|
||||
63
apps/common/audio/wm8978/iic.h
Normal file
63
apps/common/audio/wm8978/iic.h
Normal file
@ -0,0 +1,63 @@
|
||||
#ifndef _IIC_H_
|
||||
#define _IIC_H_
|
||||
|
||||
#include "generic/typedef.h"
|
||||
typedef unsigned int tu8, tbool ;
|
||||
|
||||
void iic_write(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n);
|
||||
void iic_readn(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n);
|
||||
void iic_init(void);
|
||||
void iic_init_io(void);
|
||||
void write_info(u8 addr, u8 dat);
|
||||
tu8 read_info(u8 addr);
|
||||
|
||||
void write_eerom(u8 addr, u8 dat);
|
||||
tu8 read_eerom(u8 iic_addr);
|
||||
void eeprom_page_write_stop(void);
|
||||
void eeprom_page_write_start(void);
|
||||
void eeprom_verify(void);
|
||||
|
||||
void iic_start(void);
|
||||
void iic_stop(void);
|
||||
void iic_sendbyte_io(u8 byte);
|
||||
void iic_sendbyte(u8 byte);
|
||||
tu8 iic_revbyte(u8 para);
|
||||
|
||||
extern bool g_iic_busy;
|
||||
|
||||
//#define iic_delay() delay(3000)
|
||||
#define iic_delay() delay(100)
|
||||
|
||||
|
||||
#define IIC_PORT JL_PORTB
|
||||
#define IIC_DATA_PORT 5
|
||||
#define IIC_CLK_PORT 6
|
||||
|
||||
#define iic_clk_out() do{IIC_PORT->DIR &= ~BIT(IIC_CLK_PORT);IIC_PORT->PU &= ~BIT(IIC_CLK_PORT);}while(0)
|
||||
#define iic_clk_h() do{IIC_PORT->OUT |= BIT(IIC_CLK_PORT);IIC_PORT->DIR &=~BIT(IIC_CLK_PORT);}while(0)
|
||||
#define iic_clk_l() do{IIC_PORT->OUT &=~BIT(IIC_CLK_PORT);IIC_PORT->DIR &=~BIT(IIC_CLK_PORT);}while(0)
|
||||
|
||||
#define iic_data_out() do{IIC_PORT->DIR &= ~BIT(IIC_DATA_PORT);IIC_PORT->PU &= ~BIT(IIC_DATA_PORT);}while(0)
|
||||
#define iic_data_in() do{IIC_PORT->DIR |= BIT(IIC_DATA_PORT);IIC_PORT->PU |= BIT(IIC_DATA_PORT);}while(0)
|
||||
#define iic_data_r() (IIC_PORT->IN&BIT(IIC_DATA_PORT))
|
||||
#define iic_data_h() do{IIC_PORT->OUT |= BIT(IIC_DATA_PORT);IIC_PORT->DIR &= ~BIT(IIC_DATA_PORT);}while(0)
|
||||
#define iic_data_l() do{IIC_PORT->OUT &=~BIT(IIC_DATA_PORT);IIC_PORT->DIR &= ~BIT(IIC_DATA_PORT);}while(0)
|
||||
|
||||
/*
|
||||
#define app_IIC_write(a, b, c, d) \
|
||||
iic_write(a, b, c, d)
|
||||
#define app_IIC_readn(a, b, c, d) \
|
||||
iic_readn(a, b, c, d)
|
||||
#define app_E2PROM_write(a, b) \
|
||||
write_eerom(a, b)
|
||||
#define app_E2PROM_read(a) \
|
||||
read_eerom(a)
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
359
apps/common/audio/wm8978/wm8978.c
Normal file
359
apps/common/audio/wm8978/wm8978.c
Normal file
@ -0,0 +1,359 @@
|
||||
#include "iic.h"
|
||||
#include "wm8978.h"
|
||||
|
||||
extern tbool r_ack(void);
|
||||
//--------------------------------------------------------------------------------
|
||||
#define IIC_Init iic_init_io
|
||||
#define IIC_Start iic_start
|
||||
#define IIC_Stop iic_stop
|
||||
#define IIC_Send_Byte iic_sendbyte_io
|
||||
#define IIC_Wait_Ack r_ack
|
||||
|
||||
|
||||
|
||||
|
||||
//WM8978寄存器值缓存区(总共58个寄存器,0~57),占用116字节内存
|
||||
//因为WM8978的IIC操作不支持读操作,所以在本地保存所有寄存器值
|
||||
//写WM8978寄存器时,同步更新到本地寄存器值,读寄存器时,直接返回本地保存的寄存器值.
|
||||
//注意:WM8978的寄存器值是9位的,所以要用u16来存储.
|
||||
static u16 WM8978_REGVAL_TBL[58] = {
|
||||
0X0000, 0X0000, 0X0000, 0X0000, 0X0050, 0X0000, 0X0140, 0X0000,
|
||||
0X0000, 0X0000, 0X0000, 0X00FF, 0X00FF, 0X0000, 0X0100, 0X00FF,
|
||||
0X00FF, 0X0000, 0X012C, 0X002C, 0X002C, 0X002C, 0X002C, 0X0000,
|
||||
0X0032, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000, 0X0000,
|
||||
0X0038, 0X000B, 0X0032, 0X0000, 0X0008, 0X000C, 0X0093, 0X00E9,
|
||||
0X0000, 0X0000, 0X0000, 0X0000, 0X0003, 0X0010, 0X0010, 0X0100,
|
||||
0X0100, 0X0002, 0X0001, 0X0001, 0X0039, 0X0039, 0X0039, 0X0039,
|
||||
0X0001, 0X0001
|
||||
};
|
||||
|
||||
//WM8978写寄存器
|
||||
//reg:寄存器地址
|
||||
//val:要写入寄存器的值
|
||||
//返回值:0,成功;
|
||||
// 其他,错误代码
|
||||
u8 WM8978_Write_Reg(u8 reg, u16 val)
|
||||
{
|
||||
IIC_Start();
|
||||
IIC_Send_Byte((WM8978_ADDR << 1) | 0); //发送器件地址+写命令
|
||||
if (IIC_Wait_Ack()) {
|
||||
return 1; //等待应答(成功?/失败?)
|
||||
}
|
||||
IIC_Send_Byte((reg << 1) | ((val >> 8) & 0X01)); //写寄存器地址+数据的最高位
|
||||
if (IIC_Wait_Ack()) {
|
||||
return 2; //等待应答(成功?/失败?)
|
||||
}
|
||||
IIC_Send_Byte(val & 0XFF); //发送数据
|
||||
if (IIC_Wait_Ack()) {
|
||||
return 3; //等待应答(成功?/失败?)
|
||||
}
|
||||
IIC_Stop();
|
||||
WM8978_REGVAL_TBL[reg] = val; //保存寄存器值到本地
|
||||
return 0;
|
||||
}
|
||||
|
||||
//WM8978初始化
|
||||
//返回值:0,初始化正常
|
||||
//其他,错误代码
|
||||
u8 WM8978_Init(u8 dacen, u8 adcen)
|
||||
{
|
||||
u8 res;
|
||||
IIC_Init();//初始化IIC接口
|
||||
|
||||
int i = 10;
|
||||
while (--i) {
|
||||
res = WM8978_Write_Reg(0, 0); //软复位WM8978
|
||||
if (!res) {
|
||||
printf("wm8978 reset ok,i=%d\n", i);
|
||||
break;
|
||||
} else {
|
||||
printf("wm8978 cmu err!!!\n");
|
||||
}
|
||||
delay(50000);
|
||||
}
|
||||
if (0 == i) {
|
||||
printf("Rest WM8978 10 times FAIL\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//以下为通用设置
|
||||
WM8978_Write_Reg(1, 0X1B); //R1,MICEN设置为1(MIC使能),BIASEN设置为1(模拟器工作),VMIDSEL[1:0]设置为:11(5K)
|
||||
WM8978_Write_Reg(2, 0X1B0); //R2,ROUT1,LOUT1输出使能(耳机可以工作),BOOSTENR,BOOSTENL使能
|
||||
WM8978_Write_Reg(3, 0X6C); //R3,LOUT2,ROUT2输出使能(喇叭工作),RMIX,LMIX使能
|
||||
WM8978_Write_Reg(6, 0); //R6,MCLK由外部提供
|
||||
WM8978_Write_Reg(43, 1 << 4); //R43,INVROUT2反向,驱动喇叭
|
||||
WM8978_Write_Reg(47, 0 << 8); //R47设置,PGABOOSTL,左通道MIC获得20倍增益
|
||||
WM8978_Write_Reg(48, 0 << 8); //R48设置,PGABOOSTR,右通道MIC获得20倍增益
|
||||
WM8978_Write_Reg(49, 1 << 1); //R49,TSDEN,开启过热保护
|
||||
WM8978_Write_Reg(10, 1 << 3); //R10,SOFTMUTE关闭,128x采样,最佳SNR
|
||||
WM8978_Write_Reg(14, 1 << 3); //R14,ADC 128x采样率
|
||||
|
||||
|
||||
//
|
||||
delay(10000);
|
||||
WM8978_HPvol_Set(30, 30); //耳机音量设置
|
||||
WM8978_SPKvol_Set(60); //喇叭音量设置
|
||||
delay(10000);
|
||||
WM8978_ADDA_Cfg(dacen, adcen); //开启DAC
|
||||
WM8978_Input_Cfg(adcen, 0, 0); //关闭输入通道
|
||||
WM8978_Output_Cfg(dacen, adcen); //开启DAC输出
|
||||
delay(10000);
|
||||
WM8978_I2S_Cfg(2, 0); //飞利浦标准,16位数据长度
|
||||
WM8978_MIC_Gain(63);
|
||||
|
||||
printf("WM8978_Init Finish\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//WM8978读寄存器
|
||||
//就是读取本地寄存器值缓冲区内的对应值
|
||||
//reg:寄存器地址
|
||||
//返回值:寄存器值
|
||||
u16 WM8978_Read_Reg(u8 reg)
|
||||
{
|
||||
return WM8978_REGVAL_TBL[reg];
|
||||
}
|
||||
//WM8978 DAC/ADC配置
|
||||
//adcen:adc使能(1)/关闭(0)
|
||||
//dacen:dac使能(1)/关闭(0)
|
||||
void WM8978_ADDA_Cfg(u8 dacen, u8 adcen)
|
||||
{
|
||||
u16 regval;
|
||||
regval = WM8978_Read_Reg(3); //读取R3
|
||||
if (dacen) {
|
||||
regval |= 3 << 0; //R3最低2个位设置为1,开启DACR&DACL
|
||||
} else {
|
||||
regval &= ~(3 << 0); //R3最低2个位清零,关闭DACR&DACL.
|
||||
}
|
||||
WM8978_Write_Reg(3, regval); //设置R3
|
||||
regval = WM8978_Read_Reg(2); //读取R2
|
||||
if (adcen) {
|
||||
regval |= 3 << 0; //R2最低2个位设置为1,开启ADCR&ADCL
|
||||
} else {
|
||||
regval &= ~(3 << 0); //R2最低2个位清零,关闭ADCR&ADCL.
|
||||
}
|
||||
WM8978_Write_Reg(2, regval); //设置R2
|
||||
}
|
||||
//WM8978 输入通道配置
|
||||
//micen:MIC开启(1)/关闭(0)
|
||||
//lineinen:Line In开启(1)/关闭(0)
|
||||
//auxen:aux开启(1)/关闭(0)
|
||||
void WM8978_Input_Cfg(u8 micen, u8 lineinen, u8 auxen)
|
||||
{
|
||||
u16 regval;
|
||||
regval = WM8978_Read_Reg(2); //读取R2
|
||||
if (micen) {
|
||||
regval |= 3 << 2; //开启INPPGAENR,INPPGAENL(MIC的PGA放大)
|
||||
} else {
|
||||
regval &= ~(3 << 2); //关闭INPPGAENR,INPPGAENL.
|
||||
}
|
||||
WM8978_Write_Reg(2, regval); //设置R2
|
||||
|
||||
regval = WM8978_Read_Reg(44); //读取R44
|
||||
if (micen) {
|
||||
regval |= 3 << 4 | 3 << 0; //开启LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
|
||||
} else {
|
||||
regval &= ~(3 << 4 | 3 << 0); //关闭LIN2INPPGA,LIP2INPGA,RIN2INPPGA,RIP2INPGA.
|
||||
}
|
||||
WM8978_Write_Reg(44, regval); //设置R44
|
||||
|
||||
if (lineinen) {
|
||||
WM8978_LINEIN_Gain(5); //LINE IN 0dB增益
|
||||
} else {
|
||||
WM8978_LINEIN_Gain(0); //关闭LINE IN
|
||||
}
|
||||
if (auxen) {
|
||||
WM8978_AUX_Gain(7); //AUX 6dB增益
|
||||
} else {
|
||||
WM8978_AUX_Gain(0); //关闭AUX输入
|
||||
}
|
||||
}
|
||||
//WM8978 输出配置
|
||||
//dacen:DAC输出(放音)开启(1)/关闭(0)
|
||||
//bpsen:Bypass输出(录音,包括MIC,LINE IN,AUX等)开启(1)/关闭(0)
|
||||
void WM8978_Output_Cfg(u8 dacen, u8 bpsen)
|
||||
{
|
||||
u16 regval = 0;
|
||||
if (dacen) {
|
||||
regval |= 1 << 0; //DAC输出使能
|
||||
}
|
||||
if (bpsen) {
|
||||
regval |= 1 << 1; //BYPASS使能
|
||||
regval |= 5 << 2; //0dB增益
|
||||
}
|
||||
WM8978_Write_Reg(50, regval); //R50设置
|
||||
WM8978_Write_Reg(51, regval); //R51设置
|
||||
}
|
||||
//WM8978 MIC增益设置(不包括BOOST的20dB,MIC-->ADC输入部分的增益)
|
||||
//gain:0~63,对应-12dB~35.25dB,0.75dB/Step
|
||||
void WM8978_MIC_Gain(u8 gain)
|
||||
{
|
||||
gain &= 0X3F;
|
||||
WM8978_Write_Reg(45, gain); //R45,左通道PGA设置
|
||||
WM8978_Write_Reg(46, gain | 1 << 8); //R46,右通道PGA设置
|
||||
}
|
||||
//WM8978 L2/R2(也就是Line In)增益设置(L2/R2-->ADC输入部分的增益)
|
||||
//gain:0~7,0表示通道禁止,1~7,对应-12dB~6dB,3dB/Step
|
||||
void WM8978_LINEIN_Gain(u8 gain)
|
||||
{
|
||||
u16 regval;
|
||||
gain &= 0X07;
|
||||
regval = WM8978_Read_Reg(47); //读取R47
|
||||
regval &= ~(7 << 4); //清除原来的设置
|
||||
WM8978_Write_Reg(47, regval | gain << 4); //设置R47
|
||||
regval = WM8978_Read_Reg(48); //读取R48
|
||||
regval &= ~(7 << 4); //清除原来的设置
|
||||
WM8978_Write_Reg(48, regval | gain << 4); //设置R48
|
||||
}
|
||||
//WM8978 AUXR,AUXL(PWM音频部分)增益设置(AUXR/L-->ADC输入部分的增益)
|
||||
//gain:0~7,0表示通道禁止,1~7,对应-12dB~6dB,3dB/Step
|
||||
void WM8978_AUX_Gain(u8 gain)
|
||||
{
|
||||
u16 regval;
|
||||
gain &= 0X07;
|
||||
regval = WM8978_Read_Reg(47); //读取R47
|
||||
regval &= ~(7 << 0); //清除原来的设置
|
||||
WM8978_Write_Reg(47, regval | gain << 0); //设置R47
|
||||
regval = WM8978_Read_Reg(48); //读取R48
|
||||
regval &= ~(7 << 0); //清除原来的设置
|
||||
WM8978_Write_Reg(48, regval | gain << 0); //设置R48
|
||||
}
|
||||
//设置I2S工作模式
|
||||
//fmt:0,LSB(右对齐);1,MSB(左对齐);2,飞利浦标准I2S;3,PCM/DSP;
|
||||
//len:0,16位;1,20位;2,24位;3,32位;
|
||||
void WM8978_I2S_Cfg(u8 fmt, u8 len)
|
||||
{
|
||||
fmt &= 0X03;
|
||||
len &= 0X03; //限定范围
|
||||
WM8978_Write_Reg(4, (fmt << 3) | (len << 5)); //R4,WM8978工作模式设置
|
||||
}
|
||||
|
||||
//设置耳机左右声道音量
|
||||
//voll:左声道音量(0~63)
|
||||
//volr:右声道音量(0~63)
|
||||
void WM8978_HPvol_Set(u8 voll, u8 volr)
|
||||
{
|
||||
voll &= 0X3F;
|
||||
volr &= 0X3F; //限定范围
|
||||
if (voll == 0) {
|
||||
voll |= 1 << 6; //音量为0时,直接mute
|
||||
}
|
||||
if (volr == 0) {
|
||||
volr |= 1 << 6; //音量为0时,直接mute
|
||||
}
|
||||
WM8978_Write_Reg(52, voll); //R52,耳机左声道音量设置
|
||||
WM8978_Write_Reg(53, volr | (1 << 8)); //R53,耳机右声道音量设置,同步更新(HPVU=1)
|
||||
}
|
||||
//设置喇叭音量
|
||||
//voll:左声道音量(0~63)
|
||||
void WM8978_SPKvol_Set(u8 volx)
|
||||
{
|
||||
volx &= 0X3F; //限定范围
|
||||
if (volx == 0) {
|
||||
volx |= 1 << 6; //音量为0时,直接mute
|
||||
}
|
||||
WM8978_Write_Reg(54, volx); //R54,喇叭左声道音量设置
|
||||
WM8978_Write_Reg(55, volx | (1 << 8)); //R55,喇叭右声道音量设置,同步更新(SPKVU=1)
|
||||
}
|
||||
//设置3D环绕声
|
||||
//depth:0~15(3D强度,0最弱,15最强)
|
||||
void WM8978_3D_Set(u8 depth)
|
||||
{
|
||||
depth &= 0XF; //限定范围
|
||||
WM8978_Write_Reg(41, depth); //R41,3D环绕设置
|
||||
}
|
||||
//设置EQ/3D作用方向
|
||||
//dir:0,在ADC起作用
|
||||
// 1,在DAC起作用(默认)
|
||||
void WM8978_EQ_3D_Dir(u8 dir)
|
||||
{
|
||||
u16 regval;
|
||||
regval = WM8978_Read_Reg(0X12);
|
||||
if (dir) {
|
||||
regval |= 1 << 8;
|
||||
} else {
|
||||
regval &= ~(1 << 8);
|
||||
}
|
||||
WM8978_Write_Reg(18, regval); //R18,EQ1的第9位控制EQ/3D方向
|
||||
}
|
||||
|
||||
//设置EQ1
|
||||
//cfreq:截止频率,0~3,分别对应:80/105/135/175Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ1_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval = WM8978_Read_Reg(18);
|
||||
regval &= 0X100;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(18, regval); //R18,EQ1设置
|
||||
}
|
||||
//设置EQ2
|
||||
//cfreq:中心频率,0~3,分别对应:230/300/385/500Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ2_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(19, regval); //R19,EQ2设置
|
||||
}
|
||||
//设置EQ3
|
||||
//cfreq:中心频率,0~3,分别对应:650/850/1100/1400Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ3_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(20, regval); //R20,EQ3设置
|
||||
}
|
||||
//设置EQ4
|
||||
//cfreq:中心频率,0~3,分别对应:1800/2400/3200/4100Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ4_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(21, regval); //R21,EQ4设置
|
||||
}
|
||||
//设置EQ5
|
||||
//cfreq:中心频率,0~3,分别对应:5300/6900/9000/11700Hz
|
||||
//gain:增益,0~24,对应-12~+12dB
|
||||
void WM8978_EQ5_Set(u8 cfreq, u8 gain)
|
||||
{
|
||||
u16 regval = 0;
|
||||
cfreq &= 0X3; //限定范围
|
||||
if (gain > 24) {
|
||||
gain = 24;
|
||||
}
|
||||
gain = 24 - gain;
|
||||
regval |= cfreq << 5; //设置截止频率
|
||||
regval |= gain; //设置增益
|
||||
WM8978_Write_Reg(22, regval); //R22,EQ5设置
|
||||
}
|
||||
|
||||
|
||||
55
apps/common/audio/wm8978/wm8978.h
Normal file
55
apps/common/audio/wm8978/wm8978.h
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef __WM8978_H
|
||||
#define __WM8978_H
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
#define WM8978_ADDR 0X1A //WM8978的器件地址,固定为0X1A
|
||||
|
||||
#define EQ1_80Hz 0X00
|
||||
#define EQ1_105Hz 0X01
|
||||
#define EQ1_135Hz 0X02
|
||||
#define EQ1_175Hz 0X03
|
||||
|
||||
#define EQ2_230Hz 0X00
|
||||
#define EQ2_300Hz 0X01
|
||||
#define EQ2_385Hz 0X02
|
||||
#define EQ2_500Hz 0X03
|
||||
|
||||
#define EQ3_650Hz 0X00
|
||||
#define EQ3_850Hz 0X01
|
||||
#define EQ3_1100Hz 0X02
|
||||
#define EQ3_14000Hz 0X03
|
||||
|
||||
#define EQ4_1800Hz 0X00
|
||||
#define EQ4_2400Hz 0X01
|
||||
#define EQ4_3200Hz 0X02
|
||||
#define EQ4_4100Hz 0X03
|
||||
|
||||
#define EQ5_5300Hz 0X00
|
||||
#define EQ5_6900Hz 0X01
|
||||
#define EQ5_9000Hz 0X02
|
||||
#define EQ5_11700Hz 0X03
|
||||
|
||||
|
||||
u8 WM8978_Init(u8 dacen, u8 adcen);
|
||||
void WM8978_ADDA_Cfg(u8 dacen, u8 adcen);
|
||||
void WM8978_Input_Cfg(u8 micen, u8 lineinen, u8 auxen);
|
||||
void WM8978_Output_Cfg(u8 dacen, u8 bpsen);
|
||||
void WM8978_MIC_Gain(u8 gain);
|
||||
void WM8978_LINEIN_Gain(u8 gain);
|
||||
void WM8978_AUX_Gain(u8 gain);
|
||||
u8 WM8978_Write_Reg(u8 reg, u16 val);
|
||||
u16 WM8978_Read_Reg(u8 reg);
|
||||
void WM8978_HPvol_Set(u8 voll, u8 volr);
|
||||
void WM8978_SPKvol_Set(u8 volx);
|
||||
void WM8978_I2S_Cfg(u8 fmt, u8 len);
|
||||
void WM8978_3D_Set(u8 depth);
|
||||
void WM8978_EQ_3D_Dir(u8 dir);
|
||||
void WM8978_EQ1_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ2_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ3_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ4_Set(u8 cfreq, u8 gain);
|
||||
void WM8978_EQ5_Set(u8 cfreq, u8 gain);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user