1359 lines
32 KiB
C
Raw Permalink Normal View History

#include "system/includes.h"
#include "media/includes.h"
#include "tone_player.h"
#include "audio_config.h"
#include "app_main.h"
#include "btstack/avctp_user.h"
#include "aec_user.h"
/* #include "audio_digital_vol.h" */
#include "audio_codec_clock.h"
#include "board_config.h"
#include "audio_digital_vol.h"
#if TCFG_APP_FM_EMITTER_EN
#include "fm_emitter/fm_emitter_manage.h"
#endif
#if TCFG_AUDIO_MUSIC_SIDETONE_ENABLE //播歌时侧耳监听功能
#include "audio_dec_mic2pcm.h"
#endif
#ifdef CONFIG_LITE_AUDIO
#include "tone_player_api.h"
#endif /*CONFIG_LITE_AUDIO*/
#define LOG_TAG_CONST APP_TONE
#define LOG_TAG "[APP-TONE]"
#define LOG_ERROR_ENABLE
#define LOG_INFO_ENABLE
#define LOG_DUMP_ENABLE
#include "debug.h"
#define TONE_LIST_MAX_NUM 4
#if TCFG_USER_TWS_ENABLE
#include "media/bt_audio_timestamp.h"
#include "audio_syncts.h"
#include "bt_tws.h"
#define msecs_to_bt_time(m) (((m + 1)* 1000) / 625)
#define TWS_TONE_ALIGN_TIME 0
#define TWS_TONE_ALIGN_MIX 1
#define TONE_DEC_NOT_START 0
#define TONE_DEC_WAIT_ALIGN_TIME 1
#define TONE_DEC_WAIT_MIX 2
#define TONE_DEC_CONFIRM 3
#define TWS_TONE_CONFIRM_TIME 250 /*TWS提示音音频同步确认时间(也是音频解码主从确认超时时间)*/
#endif
#if TCFG_WAV_TONE_MIX_ENABLE
#define TONE_FILE_DEC_MIX 1 // 提示音叠加播放
#else
#define TONE_FILE_DEC_MIX 0
#endif
//软件数字音量(调节解码输出数据的音量),选择此音量类型需要把audio_digital_vol.h中BG_DVOL_FADE_ENABLE 这个宏置0
#define VOL_TYPE_DIGITAL 0
#define VOL_TYPE_NULL 1 //不使用音量
#define SYS_VOL_TYPE VOL_TYPE_NULL
static OS_MUTEX tone_mutex;
struct tone_file_handle {
u8 start;
u8 idx;
u8 repeat_begin;
u8 remain;
u8 tws;
u16 loop;
u32 magic;
void *file;
const char **list;
enum audio_channel channel;
struct audio_decoder decoder;
struct audio_mixer_ch mix_ch;
u8 ch_num;
u16 target_sample_rate;
#if TCFG_USER_TWS_ENABLE
u32 wait_time;
u8 tws_align_step;
u8 ts_start;
void *audio_sync;
void *syncts;
void *ts_handle;
u32 time_base;
#endif
u32 mix_ch_event_params[3];
struct audio_src_handle *hw_src;
u32 clk_before_dec;
u8 dec_mix;
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
dvol_handle *dvol;
#endif
};
struct tone_dec_handle {
u8 r_index;
u8 w_index;
u8 list_cnt;
u8 preemption;
const char **list[4];
struct audio_res_wait wait;
u8 dec_mix;
const char *user_evt_owner;
void (*user_evt_handler)(void *priv);
void *priv;
};
extern struct audio_mixer mixer;
extern struct audio_dac_hdl dac_hdl;
extern struct audio_decoder_task decode_task;
static struct tone_file_handle *file_dec;
static char *single_file[2] = {NULL};
struct tone_dec_handle *tone_dec;
int tone_file_dec_start();
u16 get_source_sample_rate();
extern void audio_mix_ch_event_handler(void *priv, int event);
extern int bt_audio_sync_nettime_select(u8 basetime);
extern u32 bt_audio_sync_lat_time(void);
static void file_decoder_syncts_free(struct tone_file_handle *dec);
void tone_event_to_user(u8 event, const char *name);
void tone_event_clear()
{
struct sys_event e = {0};
e.type = SYS_DEVICE_EVENT;
e.arg = (void *)DEVICE_EVENT_FROM_TONE;
sys_event_clear(&e);
}
void tone_set_user_event_handler(struct tone_dec_handle *dec, void (*user_evt_handler)(void *priv), void *priv)
{
printf("tone_set_user_event_handler:%d\n", *(u8 *)priv);
dec->user_evt_owner = os_current_task();
dec->user_evt_handler = user_evt_handler;
dec->priv = priv;
}
__attribute__((weak)) void audio_pwm_set_resume(void (*resume)(void *))
{
return;
}
int tone_event_handler(struct tone_dec_handle *dec, u8 end_flag)
{
int argv[4];
if (!dec->user_evt_handler) {
/* log_info("user_evt_handler null\n"); */
return -1;
}
if (strcmp(os_current_task(), dec->user_evt_owner) == 0) {
dec->user_evt_handler(dec->priv);
return 0;
}
/* dec->user_evt_handler(dec->priv); */
argv[0] = (int)dec->user_evt_handler;
argv[1] = 1;
argv[2] = (int)dec->priv;
argv[3] = (int)end_flag;//是否是被打断 关闭0正常关闭1被打断关闭, 模式切换时由file_dec->end_flag, 决定该值
return os_taskq_post_type(dec->user_evt_owner, Q_CALLBACK, 4, argv);
/* return 0; */
}
__attribute__((weak))
int audio_dac_stop(struct audio_dac_hdl *p)
{
return 0;
}
__attribute__((weak))
int audio_dac_write(struct audio_dac_hdl *dac, void *data, int len)
{
return len;
}
__attribute__((weak))
int audio_dac_get_sample_rate(struct audio_dac_hdl *p)
{
return 16000;
}
__attribute__((weak))
void audio_dac_clear(struct audio_dac_hdl *dac)
{
}
static u8 tone_dec_idle_query()
{
if (file_dec) {
return 0;
}
return 1;
}
REGISTER_LP_TARGET(tone_dec_lp_target) = {
.name = "tone_dec",
.is_idle = tone_dec_idle_query,
};
#if TCFG_USER_TWS_ENABLE
#define bt_time_before(t1, t2) \
(((t1 < t2) && ((t2 - t1) & 0x7ffffff) < 0xffff) || \
((t1 > t2) && ((t1 - t2) & 0x7ffffff) > 0xffff))
#define TWS_FUNC_ID_TONE_ALIGN \
(((u8)('T' + 'O' + 'N' + 'E') << (2 * 8)) | \
((u8)('P' + 'L' + 'A' + 'Y' + 'E' + 'R') << (1 * 8)) | \
((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8)))
struct tws_tone_align {
u8 confirm;
u8 type;
union {
int time;
int position;
};
};
struct tws_tone_align tws_tone = {0};
/*static u8 tws_tone_align = 0;*/
/*static int tws_tone_align_time = 0;*/
static void tws_tone_play_rx_align_data(void *data, u16 len, bool rx)
{
local_irq_disable();
memcpy(&tws_tone, data, sizeof(tws_tone));
tws_tone.confirm = 1;
local_irq_enable();
y_printf("tone tws confirm rx : %d\n", tws_tone.time);
}
REGISTER_TWS_FUNC_STUB(tone_play_align) = {
.func_id = TWS_FUNC_ID_TONE_ALIGN,
.func = tws_tone_play_rx_align_data,
};
static void tone_mixer_ch_event_handler(void *priv, int event)
{
struct tone_file_handle *dec = (struct tone_file_handle *)priv;
switch (event) {
case MIXER_EVENT_CH_OPEN:
break;
case MIXER_EVENT_CH_CLOSE:
case MIXER_EVENT_CH_RESET:
break;
default:
break;
}
}
#endif
void tone_event_to_user(u8 event, const char *name)
{
struct sys_event e;
e.type = SYS_DEVICE_EVENT;
e.arg = (void *)DEVICE_EVENT_FROM_TONE;
e.u.dev.event = event;
e.u.dev.value = (int)name;
sys_event_notify(&e);
}
static char *get_file_ext_name(char *name)
{
int len = strlen(name);
char *ext = (char *)name;
while (len--) {
if (*ext++ == '.') {
break;
}
}
return ext;
}
struct audio_dec_input tone_input;
static void tone_file_dec_release()
{
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
if ((tone_input.coding_type == AUDIO_CODING_WAV) && (tone_dec->preemption == 0)) {
audio_digital_vol_bg_fade(0);
}
audio_digital_vol_close(file_dec->dvol);
file_dec->dvol = NULL;
#endif
free(file_dec);
file_dec = NULL;
}
int tone_list_play_start(const char **list, u8 preemption, u8 tws);
static int tone_file_list_clean(u8 decoding)
{
int i = 0;
if (!tone_dec) {
return 0;
}
for (i = 0; i < TONE_LIST_MAX_NUM; i++) {
if (tone_dec->list[i]) {
if (decoding && i == tone_dec->r_index) {
continue;
}
free(tone_dec->list[i]);
tone_dec->list[i] = NULL;
}
}
if (decoding) {
tone_dec->w_index = tone_dec->r_index + 1;
if (tone_dec->w_index >= TONE_LIST_MAX_NUM) {
tone_dec->w_index = 0;
}
tone_dec->list_cnt = 1;
} else {
tone_dec->list_cnt = 0;
}
return 0;
}
void tone_dec_release()
{
if (!tone_dec) {
os_mutex_post(&tone_mutex);
return;
}
tone_event_handler(tone_dec, 0);
audio_decoder_task_del_wait(&decode_task, &tone_dec->wait);
tone_file_list_clean(0);
free(tone_dec);
tone_dec = NULL;
os_mutex_post(&tone_mutex);
}
void tone_dec_end_handler(int event, const char *name)
{
const char **list;
list = tone_dec->list[tone_dec->r_index];
if (++tone_dec->r_index >= TONE_LIST_MAX_NUM) {
tone_dec->r_index = 0;
}
if (--tone_dec->list_cnt > 0) {
tone_list_play_start(tone_dec->list[tone_dec->r_index], tone_dec->preemption, 1);
} else {
tone_dec_release();
}
tone_event_to_user(event, name);
}
static int tone_file_list_repeat(struct audio_decoder *decoder)
{
int err = 0;
file_dec->idx++;
if (!file_dec->list[file_dec->idx]) {
log_info("repeat end 1:idx end");
return 0;
}
if (IS_REPEAT_END(file_dec->list[file_dec->idx])) {
//log_info("repeat_loop:%d",file_dec->loop);
if (file_dec->loop) {
file_dec->loop--;
file_dec->idx = file_dec->repeat_begin;
} else {
file_dec->idx++;
if (!file_dec->list[file_dec->idx]) {
log_info("repeat end 2:idx end");
return 0;
}
}
}
if (IS_REPEAT_BEGIN(file_dec->list[file_dec->idx])) {
if (!file_dec->loop) {
file_dec->loop = TONE_REPEAT_COUNT(file_dec->list[file_dec->idx]);
log_info("repeat begin:%d", file_dec->loop);
}
file_dec->idx++;
file_dec->repeat_begin = file_dec->idx;
}
log_info("repeat idx:%d,%s", file_dec->idx, file_dec->list[file_dec->idx]);
file_dec->file = fopen(file_dec->list[file_dec->idx], "r");
if (!file_dec->file) {
log_error("repeat end:fopen repeat file faild");
return 0;
}
return 1;
}
static int tone_audio_res_close(u8 rpt)
{
if (file_dec->start) {
audio_decoder_close(&file_dec->decoder);
}
if (file_dec->start) {
file_dec->start = 0;
}
return 0;
}
static void tone_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv)
{
int repeat = 0;
switch (argv[0]) {
case AUDIO_DEC_EVENT_END:
case AUDIO_DEC_EVENT_ERR:
if (argv[1] != file_dec->magic) {
log_error("file_dec magic no match:%d-%d", argv[1], file_dec->magic);
break;
}
repeat = tone_file_list_repeat(decoder);
log_info("AUDIO_DEC_EVENT_END,err=%x,repeat=%d\n", argv[0], repeat);
if (repeat) {
tone_audio_res_close(repeat);
tone_file_dec_start();
} else {
tone_file_list_stop(0);
}
break;
default:
return;
}
}
int tone_get_status()
{
return tone_dec ? TONE_START : TONE_STOP;
}
int tone_get_dec_status()
{
if (tone_dec && file_dec && (file_dec->decoder.state != DEC_STA_WAIT_STOP)) {
return TONE_START;
}
return TONE_STOP;
}
int tone_dec_wait_stop(u32 timeout_ms)
{
u32 to_cnt = 0;
while (tone_get_dec_status()) {
/* putchar('t'); */
os_time_dly(1);
if (timeout_ms) {
to_cnt += 10;
if (to_cnt >= timeout_ms) {
break;
}
}
}
return tone_get_dec_status();
}
static int tone_fread(struct audio_decoder *decoder, void *buf, u32 len)
{
int rlen = 0;
if (!file_dec->file) {
return 0;
}
rlen = fread(file_dec->file, buf, len);
if (rlen < len) {
fclose(file_dec->file);
file_dec->file = NULL;
}
return rlen;
}
static int tone_fseek(struct audio_decoder *decoder, u32 offset, int seek_mode)
{
if (!file_dec->file) {
return 0;
}
return fseek(file_dec->file, offset, seek_mode);
}
static int tone_flen(struct audio_decoder *decoder)
{
void *tone_file = NULL;
int len = 0;
if (file_dec->file) {
len = flen(file_dec->file);
return len;
}
tone_file = fopen(file_dec->list[file_dec->idx], "r");
if (tone_file) {
len = flen(tone_file);
fclose(tone_file);
tone_file = NULL;
}
return len;
}
static int tone_fclose(void *file)
{
if (file_dec->file) {
fclose(file_dec->file);
file_dec->file = NULL;
}
file_dec->idx = 0;
return 0;
}
struct tone_format {
const char *fmt;
u32 coding_type;
};
const struct tone_format tone_fmt_support_list[] = {
{"wtg", AUDIO_CODING_G729},
{"msbc", AUDIO_CODING_MSBC},
{"sbc", AUDIO_CODING_SBC},
{"mty", AUDIO_CODING_MTY},
{"aac", AUDIO_CODING_AAC},
#if TCFG_DEC_OPUS_ENABLE
{"opus", AUDIO_CODING_OPUS},
#endif/*TCFG_DEC_WTGV2_ENABLE*/
#if TCFG_DEC_SPEEX_ENABLE
{"speex", AUDIO_CODING_SPEEX},
#endif/*TCFG_DEC_WTGV2_ENABLE*/
#if TCFG_DEC_WTGV2_ENABLE
{"wts", AUDIO_CODING_WTGV2},
#endif/*TCFG_DEC_WTGV2_ENABLE*/
#if TCFG_DEC_MP3_ENABLE
{"mp3", AUDIO_CODING_MP3},
#endif/*TCFG_DEC_MP3_ENABLE*/
#if (TCFG_WAV_TONE_MIX_ENABLE || TCFG_DEC_WAV_ENABLE)
{"wav", AUDIO_CODING_WAV},
#endif/*TCFG_WAV_TONE_MIX_ENABLE*/
};
struct audio_dec_input tone_input = {
.coding_type = AUDIO_CODING_G729,
.data_type = AUDIO_INPUT_FILE,
.ops = {
.file = {
.fread = tone_fread,
.fseek = tone_fseek,
.flen = tone_flen,
}
}
};
static u32 tone_file_format_match(char *fmt)
{
int list_num = ARRAY_SIZE(tone_fmt_support_list);
int i = 0;
if (fmt == NULL) {
return AUDIO_CODING_UNKNOW;
}
for (i = 0; i < list_num; i++) {
if (ASCII_StrCmpNoCase(fmt, tone_fmt_support_list[i].fmt, 4) == 0) {
return tone_fmt_support_list[i].coding_type;
}
}
return AUDIO_CODING_UNKNOW;
}
static int tone_dec_probe_handler(struct audio_decoder *decoder)
{
struct tone_file_handle *dec = container_of(decoder, struct tone_file_handle, decoder);
int err = 0;
#if TCFG_USER_TWS_ENABLE
if (dec->tws_align_step == 0 && dec->ts_handle) {
if (!tws_file_timestamp_available(dec->ts_handle)) {
audio_decoder_suspend(decoder, 0);
return -EINVAL;
}
dec->tws_align_step = 1;
}
#endif
return 0;
}
static int tone_final_output_handler(struct tone_file_handle *dec, s16 *data, int len)
{
#if 1
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
if (file_dec->dvol) {
audio_digital_vol_run(file_dec->dvol, data, len);
}
#endif
u32 wlen = audio_pwm_write(data, len);
if (wlen != len) {
/* putchar('W'); */
}
return wlen;
#else
put_buf(data, len);
return len;
#endif
}
static int tone_output_after_syncts_filter(void *priv, void *data, int len)
{
struct tone_file_handle *dec = (struct tone_file_handle *)priv;
int wlen = 0;
if (dec->remain == 0) {
//get_sine_data(&tmp_cnnt, data, len/2, 1);
}
wlen = tone_final_output_handler(dec, data, len);
ret:
dec->remain = wlen < len ? 1 : 0;
return wlen;
}
static int tone_dec_output_handler(struct audio_decoder *decoder, s16 *data, int len, void *priv)
{
int wlen = 0;
int remain_len = len;
struct tone_file_handle *dec = container_of(decoder, struct tone_file_handle, decoder);
return tone_output_after_syncts_filter(dec, data, len);
}
static int tone_dec_post_handler(struct audio_decoder *decoder)
{
return 0;
}
const struct audio_dec_handler tone_dec_handler = {
.dec_probe = tone_dec_probe_handler,
.dec_output = tone_dec_output_handler,
.dec_post = tone_dec_post_handler,
};
static void tone_dec_set_output_channel(struct tone_file_handle *dec)
{
int state;
enum audio_channel channel;
/* dec->channel = AUDIO_CH_LR; */
dec->channel = AUDIO_CH_L;
audio_decoder_set_output_channel(&dec->decoder, dec->channel);
dec->ch_num = 1;
}
static int file_decoder_syncts_setup(struct tone_file_handle *dec)
{
int err = 0;
#if TCFG_USER_TWS_ENABLE
if (dec->hw_src) {
audio_hw_src_close(dec->hw_src);
free(dec->hw_src);
dec->hw_src = NULL;
}
struct audio_syncts_params params = {0};
params.nch = dec->ch_num;
#if defined(TCFG_AUDIO_OUTPUT_IIS) && TCFG_AUDIO_OUTPUT_IIS
params.pcm_device = PCM_OUTSIDE_DAC;
params.rout_sample_rate = TCFG_IIS_SAMPLE_RATE;
#else
params.pcm_device = PCM_INSIDE_DAC;
/* params.rout_sample_rate = dec->target_sample_rate; */
params.rout_sample_rate = 32000;
#endif
params.network = AUDIO_NETWORK_BT2_1;
params.rin_sample_rate = dec->decoder.fmt.sample_rate;
params.priv = dec;
params.factor = TIME_US_FACTOR;
params.output = tone_output_after_syncts_filter;
u8 base = 3;
int state = tws_api_get_tws_state();
if (state & TWS_STA_SIBLING_CONNECTED) {
base = dec->dec_mix ? 3 : 1;
}
bt_audio_sync_nettime_select(base);//3 - 优先选择远端主机为网络时钟
dec->ts_start = 0;
dec->ts_handle = file_audio_timestamp_create(0,
dec->decoder.fmt.sample_rate,
bt_audio_sync_lat_time(),
TWS_TONE_CONFIRM_TIME,
TIME_US_FACTOR);
err = audio_syncts_open(&dec->syncts, &params);
if (!err) {
dec->mix_ch_event_params[0] = (u32)&dec->mix_ch;
dec->mix_ch_event_params[1] = (u32)dec->syncts;
audio_mixer_ch_set_event_handler(&dec->mix_ch, (void *)dec->mix_ch_event_params, audio_mix_ch_event_handler);
} else {
log_e("tone audio syncts open err\n");
}
#endif
return err;
}
static void file_decoder_syncts_free(struct tone_file_handle *dec)
{
#if TCFG_USER_TWS_ENABLE
if (dec->ts_handle) {
file_audio_timestamp_close(dec->ts_handle);
dec->ts_handle = NULL;
}
if (dec->syncts) {
audio_syncts_close(dec->syncts);
dec->syncts = NULL;
}
#endif
}
void tone_play_resume_handler(void *priv)
{
if (file_dec) {
/* putchar('Z'); */
audio_decoder_resume(&file_dec->decoder);
}
}
int tone_file_dec_start()
{
int err;
struct audio_fmt *fmt;
u8 file_name[16];
if (!file_dec || !file_dec->file) {
return -EINVAL;
}
if (file_dec->start) {
return 0;
}
fget_name(file_dec->file, file_name, 16);
tone_input.coding_type = tone_file_format_match(get_file_ext_name((char *)file_name));
if (tone_input.coding_type == AUDIO_CODING_UNKNOW) {
log_e("unknow tone file format\n");
return -EINVAL;
}
#if 0
if (tone_input.coding_type == AUDIO_CODING_AAC) {
file_dec->clk_before_dec = clk_get("sys");
if (get_call_status() == BT_CALL_HANGUP) {
puts("aac tone play:48M\n");
clk_set_sys_lock(48 * 1000000L, 1);
} else {
puts("aac tone play:64M\n");
clk_set_sys_lock(64 * 1000000L, 1);
}
} else if (1) {//(tone_input.coding_type == AUDIO_CODING_WAV) || (tone_input.coding_type == AUDIO_CODING_MP3)) {
/*当前时钟小于wav/mp3提示音播放需要得时钟则自动提高主频*/
file_dec->clk_before_dec = clk_get("sys");
u32 wav_tone_play_clk = 96 * 1000000L;
if (wav_tone_play_clk < file_dec->clk_before_dec) {
wav_tone_play_clk = file_dec->clk_before_dec;
}
printf("wav/mp3 tone play clk:%d->%d\n", file_dec->clk_before_dec, wav_tone_play_clk);
clk_set_sys_lock(wav_tone_play_clk, 1);
}
#else
audio_codec_clock_set(AUDIO_TONE_MODE, tone_input.coding_type, tone_dec->wait.preemption);
#endif
err = audio_decoder_open(&file_dec->decoder, &tone_input, &decode_task);
if (err) {
return err;
}
audio_decoder_set_handler(&file_dec->decoder, &tone_dec_handler);
/*用于处理DEC_EVENT与当前解码的匹配*/
file_dec->magic = rand32();
audio_decoder_set_event_handler(&file_dec->decoder, tone_dec_event_handler, file_dec->magic);
err = audio_decoder_get_fmt(&file_dec->decoder, &fmt);
if (err) {
printf("tone file get fmt err \n");
goto __err1;
}
tone_dec_set_output_channel(file_dec);
audio_pwm_set_resume((void (*)(void *))tone_play_resume_handler);
/* audio_pwm_start(); */
set_state(2);
file_dec->target_sample_rate = fmt->sample_rate;
__dec_start:
#if TCFG_USER_TWS_ENABLE
/* if (file_dec->tws) { */
/* file_decoder_syncts_setup(file_dec); */
/* } */
/* file_dec->tws_align_step = 0; */
#endif
/* sys_hi_timer_add(NULL,tone_play_resume_handler,3); */
#if (SYS_VOL_TYPE == VOL_TYPE_DIGITAL)
if ((tone_input.coding_type == AUDIO_CODING_WAV) && (tone_dec->preemption == 0)) {
/* audio_digital_vol_bg_fade(1); */
}
file_dec->dvol = audio_digital_vol_open(SYS_DEFAULT_TONE_VOL, SYS_MAX_VOL, 20);
#endif/*VOL_TYPE_DIGITAL*/
err = audio_decoder_start(&file_dec->decoder);
if (err) {
goto __err2;
}
file_dec->start = 1;
return 0;
__err2:
#if TCFG_APP_FM_EMITTER_EN
#else
#endif
__err1:
audio_decoder_close(&file_dec->decoder);
tone_file_dec_release();
return err;
}
static int tone_wait_res_handler(struct audio_res_wait *wait, int event)
{
int err = 0;
if (event == AUDIO_RES_GET) {
printf(">>> %s %d\n", __func__, __LINE__);
err = tone_file_dec_start();
printf(">>> %s %d\n", __func__, __LINE__);
} else if (event == AUDIO_RES_PUT) {
printf(">>> %s %d\n", __func__, __LINE__);
tone_file_list_stop(0);
printf(">>> %s %d\n", __func__, __LINE__);
}
return err;
}
int tone_file_list_stop(u8 no_end)
{
const char *name = NULL;
log_info("tone_file_list_stop\n");
os_mutex_pend(&tone_mutex, 0);
if (!file_dec) {
log_info("tone_file_list_stop out 0\n");
os_mutex_post(&tone_mutex);
return 0;
}
tone_audio_res_close(0);
/* extern void audio_pwm_close(void); */
/* audio_pwm_close(); */
#if 0
if ((tone_input.coding_type == AUDIO_CODING_AAC) || (tone_input.coding_type == AUDIO_CODING_WAV)) {
printf("tone_play end,clk restore:%d", file_dec->clk_before_dec);
clk_set_sys_lock(file_dec->clk_before_dec, 2);
}
#else
audio_codec_clock_del(AUDIO_TONE_MODE);
#endif
if (file_dec->list[file_dec->idx]) {
name = (const char *)file_dec->list[file_dec->idx];
} else if (file_dec->idx) {
name = (const char *)file_dec->list[file_dec->idx - 1];
}
if (file_dec->file) {
fclose(file_dec->file);
}
tone_file_dec_release();
tone_dec_end_handler(AUDIO_DEC_EVENT_END, name);
log_info("tone_file_list_stop out 1\n");
/* audio_pwm_stop(); */
set_state(0);
return 0;
}
/*static const u8 pcm_wav_header[] = {
'R', 'I', 'F', 'F', //rid
0xff, 0xff, 0xff, 0xff, //file length
'W', 'A', 'V', 'E', //wid
'f', 'm', 't', ' ', //fid
0x14, 0x00, 0x00, 0x00, //format size
0x01, 0x00, //format tag
0x01, 0x00, //channel num
0x80, 0x3e, 0x00, 0x00, //sr 16K
0x00, 0x7d, 0x00, 0x00, //avgbyte
0x02, 0x00, //blockalign
0x10, 0x00, //persample
0x02, 0x00,
0x00, 0x00,
'f', 'a', 'c', 't', //f2id
0x40, 0x00, 0x00, 0x00, //flen
0xff, 0xff, 0xff, 0xff, //datalen
'd', 'a', 't', 'a', //"data"
0xff, 0xff, 0xff, 0xff, //sameple size
};*/
int audio_decoder_find_coding_type(struct audio_decoder_task *task, u32 coding_type);
int tone_list_play_start(const char **list, u8 preemption, u8 tws)
{
int err;
u8 file_name[16];
char *format = NULL;
FILE *file = NULL;
int index = 0;
if (IS_REPEAT_BEGIN(list[0])) {
index = 1;
}
printf(">>> %s %d\n", __func__, __LINE__);
file = fopen(list[index], "r");
if (!file) {
return -EINVAL;
}
printf(">>> %s %d\n", __func__, __LINE__);
fget_name(file, file_name, 16);
format = get_file_ext_name((char *)file_name);
file_dec = zalloc(sizeof(*file_dec));
file_dec->list = list;
file_dec->idx = index;
file_dec->file = file;
file_dec->tws = tws;
if (index == 1) {
file_dec->loop = TONE_REPEAT_COUNT(list[0]);
}
#if 0
if (!preemption) {
file_dec->dec_mix = 1;
tone_dec->wait.protect = 1;
}
#endif
tone_dec->wait.priority = 3;
tone_dec->wait.preemption = preemption;
printf(">>> %s %d\n", __func__, __LINE__);
/*AAC提示音默认打断播放*/
if (ASCII_StrCmpNoCase(format, "aac", 3) == 0) {
printf("aac tone,preemption = 1\n");
tone_dec->wait.preemption = 1;
tone_dec->wait.format = AUDIO_CODING_AAC;
} else {
#if TONE_FILE_DEC_MIX
fadsf
if (tone_dec->wait.preemption == 0) {
/*支持叠加的提示音解码文件格式*/
if ((ASCII_StrCmpNoCase(format, "wav", 3) == 0) || \
(ASCII_StrCmpNoCase(format, "mp3", 3) == 0) || \
(ASCII_StrCmpNoCase(format, "wtg", 3) == 0)) {
// 叠加播放
file_dec->dec_mix = 1;
/*tone_dec->wait.protect = 1;*/ //提示音播放不用来做低优先级的背景音
tone_dec->wait.preemption = 0;
}
} else {
file_dec->dec_mix = 0;
}
#endif
}
tone_dec->wait.handler = tone_wait_res_handler;
printf(">>> %s %d\n", __func__, __LINE__);
err = audio_decoder_task_add_wait(&decode_task, &tone_dec->wait);
printf(">>> %s %d\n", __func__, __LINE__);
#if 0
if (!err && file_dec->start == 0) {
/*decoder中有该解码器则强制使用打断方式防止overlay冲突*/
if (audio_decoder_find_coding_type(&decode_task, tone_file_format_match(format))) {
tone_dec->wait.preemption = 1;
err = audio_decoder_task_add_wait(&decode_task, &tone_dec->wait);
} else {
err = tone_file_dec_start();
}
}
#endif
printf(">>> %s %d\n", __func__, __LINE__);
if (err) {
if (tone_dec) {
audio_decoder_task_del_wait(&decode_task, &tone_dec->wait);
}
} else {
if (file_dec->dec_mix && !file_dec->start) {
err = tone_file_dec_start();
}
}
printf(">>> %s %d\n", __func__, __LINE__);
return err;
}
static int __tone_file_list_play(const char **list, u8 preemption, u8 tws)
{
int i = 0;
int err = 0;
if (!list) {
return -EINVAL;
}
printf(">>> %s %d\n", __func__, __LINE__);
if (tone_dec == NULL) {
tone_dec = zalloc(sizeof(*tone_dec));
if (tone_dec == NULL) {
log_error("tone dec zalloc failed");
return -ENOMEM;
}
}
printf(">>> %s %d\n", __func__, __LINE__);
while (list[i] != NULL) {
i++;
}
printf(">>> %s %d\n", __func__, __LINE__);
char **p = malloc(4 * (i + 1));
memcpy(p, list, 4 * (i + 1));
tone_dec->list[tone_dec->w_index++] = (const char **)p;
if (tone_dec->w_index >= TONE_LIST_MAX_NUM) {
tone_dec->w_index = 0;
}
printf(">>> %s %d\n", __func__, __LINE__);
tone_dec->list_cnt++;
tone_dec->preemption = preemption;
if (tone_dec->list_cnt == 1) {
err = tone_list_play_start(tone_dec->list[tone_dec->r_index], tone_dec->preemption, tws);
if (err == -EINVAL) {
free(p);
free(tone_dec);
tone_dec = NULL;
}
return err;
} else {
puts("tone_file_add_tail\n");
}
printf(">>> %s %d\n", __func__, __LINE__);
return 0;
}
int tone_file_list_play(const char **list, u8 preemption)
{
return __tone_file_list_play(list, preemption, 1);
}
int tone_file_list_play_with_callback(const char **list, u8 preemption, void (*user_evt_handler)(void *priv), void *priv)
{
int i = 0;
int err = 0;
putchar('A');
if (!list) {
return -EINVAL;
}
putchar('B');
if (tone_dec == NULL) {
tone_dec = zalloc(sizeof(*tone_dec));
if (tone_dec == NULL) {
log_error("tone dec zalloc failed");
return -ENOMEM;
}
}
putchar('C');
while (list[i] != NULL) {
i++;
}
char **p = malloc(4 * (i + 1));
memcpy(p, list, 4 * (i + 1));
tone_dec->list[tone_dec->w_index++] = (const char **)p;
if (tone_dec->w_index >= TONE_LIST_MAX_NUM) {
tone_dec->w_index = 0;
}
putchar('D');
if (user_evt_handler) {
tone_set_user_event_handler(tone_dec, user_evt_handler, priv);
}
tone_dec->list_cnt++;
tone_dec->preemption = preemption;
if (tone_dec->list_cnt == 1) {
err = tone_list_play_start(tone_dec->list[tone_dec->r_index], tone_dec->preemption, 1);
if (err == -EINVAL) {
free(p);
free(tone_dec);
tone_dec = NULL;
}
return err;
} else {
puts("tone_file_add_tail\n");
}
return 0;
}
static void tone_stop(u8 force);
int tone_play(const char *name, u8 preemption)
{
if (tone_dec) {
log_info("tone dec busy now,tone stop first");
tone_stop(0);
}
single_file[0] = (char *)name;
single_file[1] = NULL;
return tone_file_list_play((const char **)single_file, preemption);
}
int tone_play_no_tws(const char *name, u8 preemption)
{
if (tone_dec) {
log_info("tone dec busy now,tone stop first");
tone_stop(0);
}
single_file[0] = (char *)name;
single_file[1] = NULL;
return __tone_file_list_play((const char **)single_file, preemption, 0);
}
int tone_play_with_callback(const char *name, u8 preemption, void (*user_evt_handler)(void *priv), void *priv)
{
if (tone_dec) {
tone_event_clear();
log_info("tone dec busy now,tone stop first");
tone_stop(0);
}
single_file[0] = (char *)name;
single_file[1] = NULL;
return tone_file_list_play_with_callback((const char **)single_file, preemption, user_evt_handler, priv);
}
int tone_play_add(const char *name, u8 preemption)
{
if (tone_dec) {
log_info("tone dec busy now,tone file add next");
//tone_stop(0);
}
single_file[0] = (char *)name;
single_file[1] = NULL;
return tone_file_list_play((const char **)single_file, preemption);
}
const char *get_playing_tone_name(u8 index)
{
if (tone_dec) {
const char **list = tone_dec->list[tone_dec->r_index + index];
if (list) {
return list[0];
}
}
return 0;
}
static void tone_stop(u8 force)
{
if (tone_dec == NULL) {
return;
}
if (force) {
tone_file_list_clean(1);
}
tone_file_list_stop(0);
tone_dec_release();
}
static u8 audio_tone_idle_query()
{
if (tone_dec) {
return 0;
}
return 1;
}
REGISTER_LP_TARGET(audio_tone_lp_target) = {
.name = "audio_tone",
.is_idle = audio_tone_idle_query,
};
#if 0 //(USE_DMA_TONE)
static volatile u8 tone_play_falg = 0; //用于播放提示音后,作相应的动作
void set_tone_play_falg(u8 flag)
{
tone_play_falg = flag;
}
u8 get_tone_play_flag(void)
{
return tone_play_falg;
}
int tone_play_index_for_dma(u8 index, u8 flag)
{
set_tone_play_falg(flag);
return tone_play_index(index, 1);
}
static u32 dma_tone_arg_before = 0; //记录下按键的arg值
void set_dma_tone_arg_before(u32 arg)
{
dma_tone_arg_before = arg;
}
u32 get_dma_tone_arg_before(void)
{
return dma_tone_arg_before;
}
void clear_dma_tone_arg_before(void)
{
dma_tone_arg_before = 0;
}
#endif
static volatile s32 tone_play_end_cmd = TONE_PLAY_END_CB_CMD_NONE; //用于播放提示音后,作相应的动作
void tone_play_end_cb_cmd_set(int cmd)
{
tone_play_end_cmd = cmd;
}
s32 tone_play_end_cb_cmd_get(void)
{
return tone_play_end_cmd;
}
int tone_play_index_with_cb_cmd(u8 index, int flag)
{
tone_play_end_cb_cmd_set(flag);
return tone_play_index(index, 1);
}
static u32 tone_arg_storage = 0; //记录下按键的arg值
void tone_arg_store(u32 arg)
{
tone_arg_storage = arg;
}
u32 tone_arg_restore(void)
{
return tone_arg_storage;
}
void tone_arg_storage_clean(void)
{
tone_arg_storage = 0;
}
int tone_play_init(void)
{
os_mutex_create(&tone_mutex);
return 0;
}
int tone_play_stop(void)
{
log_info("tone_play_stop");
tone_stop(1);
return 0;
}
/*
*@brief:
*@return: 0
* 0
*@note:
*/
int tone_name_compare(const char *name)
{
if (tone_dec) {
if (file_dec) {
printf("file_name:%s,cmp_name:%s\n", file_dec->list[file_dec->idx], name);
return strcmp(name, file_dec->list[file_dec->idx]);
}
}
printf("tone_dec idle now\n");
return -1;
}