This commit is contained in:
huxi
2025-12-03 11:12:34 +08:00
parent c23ae4f24c
commit bc195654bf
8163 changed files with 3799544 additions and 92 deletions
+37
View File
@@ -0,0 +1,37 @@
#ifndef A2DP_PLAYER_H
#define A2DP_PLAYER_H
#include "effect/effects_default_param.h"
int a2dp_player_open(u8 *btaddr);
int a2dp_player_open_for_jl_dongle(u8 *btaddr, u16 latency_msec, u8 dynamic_latency_en);
void a2dp_player_close(u8 *btaddr);
int a2dp_player_get_btaddr(u8 *btaddr);
int a2dp_player_runing();
bool a2dp_player_is_playing(u8 *bt_addr);
int a2dp_player_start_slience_detect(u8 *btaddr, void (*handler)(u8 *, bool), int msec);
void a2dp_player_tws_event_handler(int *msg);
void a2dp_play_close(u8 *bt_addr);
void a2dp_player_low_latency_enable(u8 enable);
extern void a2dp_file_low_latency_enable(u8 enable);
int a2dp_file_pitch_up();
int a2dp_file_pitch_down();
int a2dp_file_set_pitch(enum _pitch_level pitch_mode);
void a2dp_file_pitch_mode_init(enum _pitch_level pitch_mode);
void a2dp_player_reset(void);
#endif
@@ -0,0 +1,13 @@
#ifndef adda_loop_PLAYER_H
#define adda_loop_PLAYER_H
#include "effect/effects_default_param.h"
int adda_loop_player_open();
void adda_loop_player_close();
bool adda_loop_player_runing();
#endif
@@ -0,0 +1,50 @@
#ifndef _LE_AUDIO_PLAYER_H_
#define _LE_AUDIO_PLAYER_H_
enum AI_SERVICE {
AI_SERVICE_MEDIA,
AI_SERVICE_CALL_DOWNSTREAM,
AI_SERVICE_CALL_UPSTREAM,
AI_SERVICE_VOICE
};
struct ai_rx_player_param {
u8 type;
u8 channel_mode;
u16 frame_dms; //帧长时间,单位 deci-ms (ms/10)
u32 coding_type;
u32 sample_rate;
u32 bit_rate;
};
struct ai_rx_file_handle {
void *file;
void *bt_addr;
u8 start;
u8 source;
u8 reference;
struct stream_node *node;
u32 play_latency; //us
struct ai_rx_player_param param;
const struct stream_file_ops *file_ops;
};
struct ai_rx_cb {
enum stream_node_state(*get_frame_event_cb)(struct ai_rx_file_handle *hdl, struct stream_frame **pframe); // 事件回调
};
enum opus_dec_frame_len {
FRAME_LEN_40 = 0,
FRAME_LEN_80,
FRAME_LEN_160,
};
int ai_rx_player_open(void *file, u8 source, struct ai_rx_player_param *param);
void ai_rx_player_close(u8 source);
bool ai_rx_player_runing(u8 source);
#endif
@@ -0,0 +1,16 @@
#ifndef AI_VOICE_RECODER_H
#define AI_VOICE_RECODER_H
int ai_voice_recoder_open(u32 code_type, u8 ai_type);
void ai_voice_recoder_close();
#endif
@@ -0,0 +1,33 @@
#ifndef _AVI_AUDIO_PLAYER_H_
#define _AVI_AUDIO_PLAYER_H_
enum AVI_SERVICE {
AVI_SERVICE_MEDIA,
AVI_SERVICE_CALL_DOWNSTREAM,
AVI_SERVICE_CALL_UPSTREAM,
AVI_SERVICE_VOICE
};
struct avi_audio_player_param {
u8 type;
u8 channel_mode;
u16 frame_dms; //帧长时间,单位 deci-ms (ms/10)
u32 coding_type;
u32 sample_rate;
u32 bit_rate;
};
enum avi_dec_frame_len {
FRAME_LEN_40 = 0,
FRAME_LEN_80,
FRAME_LEN_160,
};
int avi_audio_player_open(void *file, u8 source, struct avi_audio_player_param *param);
void avi_audio_player_close(u8 source);
bool avi_audio_player_runing(u8 source);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef CVP_NODE_H
#define CVP_NODE_H
#include "audio_config.h"
#include "audio_cvp.h"
#include "effects/effects_adj.h"
#include "adc_file.h"
int cvp_node_param_cfg_read(void *priv, u8 ignore_subid);
int cvp_node_output_handle(s16 *data, u16 len);
int cvp_param_cfg_read(void);
u8 cvp_get_talk_mic_ch(void);
u8 cvp_get_talk_ref_mic_ch(void);
u8 cvp_get_talk_fb_mic_ch(void);
#endif/*CVP_NODE_H*/
@@ -0,0 +1,14 @@
#ifndef DEV_FLOW_PLAYER_H
#define DEV_FLOW_PLAYER_H
int dev_flow_player_open();
void dev_flow_player_close();
bool dev_flow_player_runing();
#endif
@@ -0,0 +1,15 @@
#ifndef DEV_FLOW_RECODER_H
#define DEV_FLOW_RECODER_H
int dev_flow_recoder_open(void);
void dev_flow_recoder_close(void);
bool dev_flow_recoder_runing(void);
#endif
+22
View File
@@ -0,0 +1,22 @@
#ifndef ESCO_PLAYER_H
#define ESCO_PLAYER_H
int esco_player_open(u8 *bt_addr);
void esco_player_close();
bool esco_player_runing();
int esco_player_get_btaddr(u8 *btaddr);
int esco_player_is_playing(u8 *btaddr);
int esco_player_start(u8 *bt_addr);
int esco_player_suspend(u8 *bt_addr);
#endif
@@ -0,0 +1,24 @@
#ifndef ESCO_RECODER_H
#define ESCO_RECODER_H
#define COMMON_SCO 0 //普通SCO
#define JL_DOGLE_ACL 1 //dongle ACL链路
int esco_recoder_open(u8 link_type, void *bt_addr);
void esco_recoder_close();
int esco_recoder_switch(u8 en);
int esco_recoder_reset(void);
#endif
+162
View File
@@ -0,0 +1,162 @@
#ifndef MUSIC_PLAYER_H
#define MUSIC_PLAYER_H
#include "generic/typedef.h"
#include "jlstream.h"
#include "music/music_decrypt.h"
#include "music/music_id3.h"
#include "app_config.h"
#include "audio_decoder.h"
#include "fs/fs.h"
#include "effect/effects_default_param.h"
#define MAX_FILE_NUM 20
#if (defined(TCFG_DEC_APE_ENABLE) && (TCFG_DEC_APE_ENABLE))
#define BREAKPOINT_DATA_LEN (2036 + 4)
#elif (defined(TCFG_DEC_FLAC_ENABLE) && (TCFG_DEC_FLAC_ENABLE))
#define BREAKPOINT_DATA_LEN 688
#elif (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE)
#define BREAKPOINT_DATA_LEN 536
#endif
#ifdef CONFIG_CPU_BR18
#ifndef BREAKPOINT_DATA_LEN
#define BREAKPOINT_DATA_LEN 80
#endif
#else
#ifndef BREAKPOINT_DATA_LEN
#define BREAKPOINT_DATA_LEN 32
#endif
#endif
typedef int (*music_player_cb_t)(void *, int parm, enum stream_event);
enum play_status {
FILE_PLAYER_STOP = 0x0, //播放结束
FILE_PLAYER_START, //播放中
FILE_PLAYER_PAUSE//播放暂停
};
struct file_player {
struct list_head entry;
u8 ref;
u8 index;
u8 player_id;
enum stream_scene scene;
enum stream_coexist coexist;
u32 coding_type;
struct jlstream *stream;
void *file;
const char *file_name_list[MAX_FILE_NUM + 1];
void *priv;
music_player_cb_t callback;
CIPHER mply_cipher; // 解密播放
#if TCFG_DEC_ID3_V1_ENABLE
MP3_ID3_OBJ *p_mp3_id3_v1; // id3_v1信息
#endif
#if TCFG_DEC_ID3_V2_ENABLE
MP3_ID3_OBJ *p_mp3_id3_v2; // id3_v2信息
#endif
#if FILE_DEC_REPEAT_EN
u8 repeat_num; // 无缝循环次数
struct fixphase_repair_obj repair_buf; // 无缝循环句柄
#endif
struct audio_dec_breakpoint *break_point;
u8 read_err;
u8 ab_repeat_status;
s8 music_speed_mode; //播放倍速
s8 music_pitch_mode; //变调模式
enum play_status status; //播放状态
u8 break_point_flag; //是否有播放器申请的断点
};
// AB点复读模式
enum {
AB_REPEAT_MODE_BP_A = 0x01,
AB_REPEAT_MODE_BP_B,
AB_REPEAT_MODE_CUR,
};
enum _speed_level {
PLAY_SPEED_0_5 = 0x0, //0.5倍速
PLAY_SPEED_0_75, //0.75倍速
PLAY_SPEED_1, // 1倍速
PLAY_SPEED_1_25, //1.25倍速
PLAY_SPEED_1_5, //1.5倍速
PLAY_SPEED_2, // 2倍速
PLAY_SPEED_3, // 3倍速
PLAY_SPEED_4, // 4倍速
};
int music_player_init(struct file_player *player, void *file, struct audio_dec_breakpoint *dbp);
/* ---------------------音乐播放API-----------------------------
*
* 音乐和其它音频之间默认采用叠加方式播放,可能由于资源限制而采用打断的方式播放
* 音乐和音乐之间默认不抢占,采用排队方式播放
*
* ---------------------------------------------------------*/
/*
* 播放单个音乐文件
*/
struct file_player *music_file_play(FILE *file, struct audio_dec_breakpoint *dbp);
/*
* 播放单个音乐文件,带有播放状态回调参数
*/
struct file_player *music_file_play_callback(FILE *file, void *priv,
music_player_cb_t callback,
struct audio_dec_breakpoint *dbp
);
/*
* 停止播放所有音乐
*/
void music_file_player_stop();
/*
* 返回是否有音乐在播放
*/
int music_player_runing();
//返回第一个打开的音乐播放器指针
struct file_player *get_music_file_player(void);
int music_file_player_pp(struct file_player *music_player);
int music_file_player_ff(u16 step_s, struct file_player *music_player);
int music_file_player_fr(u16 step_s, struct file_player *music_player);
int music_file_ab_repeat_switch(struct file_player *music_player);
int music_file_pitch_up(struct file_player *music_player);
int music_file_pitch_down(struct file_player *music_player);
int music_file_set_pitch(struct file_player *music_player, enum _pitch_level pitch_mode);
/*
* 加速音乐播放,设置成功返回当前倍速播放的speed值,失败则返回-1
*/
int music_file_speed_up(struct file_player *music_player); //倍速播放接口
/*
* 减速音乐播放,设置成功返回当前倍速播放的speed值,失败则返回-1
*/
int music_file_speed_down(struct file_player *music_player); //慢速播放接口
int music_file_get_breakpoints(struct audio_dec_breakpoint *bp, struct file_player *music_player);
int music_file_set_speed(struct file_player *music_player, enum _speed_level speed_mode); //设置播放速度
int music_file_get_player_status(struct file_player *music_player);
int music_file_get_cur_time(struct file_player *music_player);
int music_file_get_total_time(struct file_player *music_player);
int file_dec_set_start_dest_play(u32 start_time, u32 dest_time, u32(*cb)(void *), void *cb_priv, u32 coding_type, struct file_player *music_player);
int file_dec_set_start_play(u32 start_time, u32 coding_type);
#endif
@@ -0,0 +1,57 @@
#ifndef _FILE_RECODER_H_
#define _FILE_RECODER_H_
#include "jlstream.h"
#include "encoder_node.h"
#include "fs/fs.h"
#define AUDIO_RECORD_CUT_HEAD_TAIL_EN 1
#define RECODER_DEVICE_LOGO "sd0"
typedef void (*file_recorder_cb_t)(void *, enum stream_state);
struct file_recorder {
struct list_head entry;
void *file;
void *priv;
file_recorder_cb_t callback;
const struct stream_file_ops *fops;
struct jlstream *stream;
#if AUDIO_RECORD_CUT_HEAD_TAIL_EN
u8 head_size;
u16 cut_head_timer;
u32 cut_tail_size;
#endif
};
struct file_recorder *file_recorder_open(int pipeline_uuid, int snode_uuid);
int file_recorder_get_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt);
int file_recorder_set_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt);
FILE *file_recorder_open_file(struct file_recorder *recorder, const char *fname);
int file_recorder_set_file(struct file_recorder *recorder, void *file,
const struct stream_file_ops *fops);
void *file_recorder_change_file(struct file_recorder *recorder, void *new_file);
void file_recorder_set_callback(struct file_recorder *recorder, void *priv,
file_recorder_cb_t callback);
void file_recorder_seamless_set(struct file_recorder *recorder, struct seamless_recording *seamless);
int file_recorder_start(struct file_recorder *recorder);
int file_recorder_close(struct file_recorder *recorder, bool close_file);
int file_recorder_get_enc_time(struct file_recorder *recorder);
int file_recorder_stop(struct file_recorder *recorder, bool close_file);
int file_recorder_release(struct file_recorder *recorder);
#endif
+20
View File
@@ -0,0 +1,20 @@
#ifndef FM_PLAYER_H
#define FM_PLAYER_H
#include "effect/effects_default_param.h"
int fm_player_open();
void fm_player_close();
bool fm_player_runing();
int fm_file_pitch_up();
int fm_file_pitch_down();
int fm_file_set_pitch(enum _pitch_level pitch_mode);
void fm_file_pitch_mode_init(enum _pitch_level pitch_mode);
#endif
@@ -0,0 +1,22 @@
#ifndef LINEIN_PLAYER_H
#define LINEIN_PLAYER_H
#include "effect/effects_default_param.h"
int linein_player_open();
void linein_player_close();
bool linein_player_runing();
int linein_player_playing();
int linein_file_pitch_up();
int linein_file_pitch_down();
int linein_file_set_pitch(enum _pitch_level pitch_mode);
void linein_file_pitch_mode_init(enum _pitch_level pitch_mode);
#endif
@@ -0,0 +1,18 @@
#ifndef __PC_MIC_RECODER
#define __PC_MIC_RECODER
#include "cpu.h"
int pc_mic_recoder_open(void);
void pc_mic_recoder_close(void);
int pc_mic_recoder_open_by_taskq(void);
int pc_mic_recoder_close_by_taskq(void);
int pc_mic_recoder_restart_by_taskq(void);
int pc_mic_set_volume_by_taskq(u32 mic_vol);
extern u8 pc_mic_get_node_state(void);
extern void pc_mic_set_fmt(u8 channel, u8 bit, u32 sample_rate);
extern u32 pc_mic_get_fmt_sample_rate(void);
#endif
@@ -0,0 +1,18 @@
#ifndef __PC_RX_PLAYER_H
#define __PC_RX_PLAYER_H
#include "cpu.h"
int pc_spk_player_open(void);
void pc_spk_player_close(void);
int pcspk_close_player_by_taskq(void);
int pcspk_open_player_by_taskq(void);
int pcspk_restart_player_by_taskq(void);
int pcspk_set_volume_by_taskq(void);
bool pc_spk_player_runing();
#endif
@@ -0,0 +1,33 @@
/*************************************************************************************************/
/*!
* \file reference_time.h
*
* \brief 音频的参考时钟选择与设置
*
* Copyright (c) 2011-2022 ZhuHai Jieli Technology Co.,Ltd.
*
*/
/*************************************************************************************************/
#ifndef _REFERENCE_TIME_H_
#define _REFERENCE_TIME_H_
#include "typedef.h"
int audio_reference_clock_select(void *addr, u8 network);
u32 audio_reference_clock_time(void);
u32 audio_reference_network_clock_time(u8 network);
u8 is_audio_reference_clock_enable(void);
u8 audio_reference_clock_match(void *addr, u8 network);
u8 audio_reference_clock_network(void *addr);
void audio_reference_clock_exit(u8 id);
u32 audio_reference_clock_remapping(u8 now_network, u8 dst_network, u32 clock);
u8 audio_reference_network_exist(u8 reference);
#endif
+18
View File
@@ -0,0 +1,18 @@
#ifndef __RING_PLAYER_H
#define __RING_PLAYER_H
int play_ring_file(const char *file_name);
int play_ring_file_alone(const char *file_name);
int play_ring_file_with_callback(const char *file_name, void *priv, tone_player_cb_t callback);
int play_ring_file_alone_with_callback(const char *file_name, void *priv, tone_player_cb_t callback);
bool ring_player_runing();
void ring_player_stop();
#endif
+110
View File
@@ -0,0 +1,110 @@
#ifndef TONE_PLAYER_H
#define TONE_PLAYER_H
#include "generic/typedef.h"
#include "jlstream.h"
#define MAX_FILE_NUM 20
typedef int (*tone_player_cb_t)(void *, enum stream_event);
struct tone_player {
struct list_head entry;
u8 ref;
u8 index;
u8 player_id;
u8 channel_mode;
enum stream_scene scene;
enum stream_coexist coexist;
u16 fname_uuid;
u32 coding_type;
u32 sample_rate;
struct jlstream *stream;
void *file;
void *next_file;
const char *file_name_list[MAX_FILE_NUM + 1];
void *priv;
tone_player_cb_t callback;
};
int tone_player_init(struct tone_player *player, const char *file_name);
int tone_player_add(struct tone_player *player);
void tone_player_free(struct tone_player *player);
/* ---------------------提示音播放API-----------------------------
*
* 提示音和其它音频之间默认采用叠加方式播放,可能由于资源限制而采用打断的方式播放
* 提示音和提示音之间默认不抢占,采用排队方式播放
*
* ---------------------------------------------------------*/
/*
* 播放单个提示音文件
*/
int play_tone_file(const char *file_name);
/*
* 播放单个提示音文件,带有播放状态回调参数
*/
int play_tone_file_callback(const char *file_name, void *priv,
tone_player_cb_t callback);
/*
* 打断方式播放单个提示音文件
*/
int play_tone_file_alone(const char *file_name);
int play_tone_file_alone_callback(const char *file_name, void *priv,
tone_player_cb_t callback);
/*
* 播放文件列表,内部不会复制文件名,file_name[x]指向的文件名地址要求播放过程中有效
*/
int play_tone_files(const char *const file_name[], u8 file_num);
int play_tone_files_alone(const char *const file_name[], u8 file_num);
int play_tone_files_callback(const char *const file_name[], u8 file_num,
void *priv, tone_player_cb_t callback);
int play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
void *priv, tone_player_cb_t callback);
/*
* 停止播放所有提示音
*/
void tone_player_stop();
/*
* 返回是否有提示音在播放
*/
int tone_player_runing();
/*
* 播放按键音
*/
int play_key_tone_file(const char *file_name);
/*
* 提示音文件名转uuid, 全局的提示音播放结束事件中会有次参数,可用于识别是哪一个提示音
*/
u16 tone_player_get_fname_uuid(const char *fname);
#endif
@@ -0,0 +1,74 @@
#ifndef TWS_TONE_PLAYER_H
#define TWS_TONE_PLAYER_H
#include "tone_player.h"
#include "ring_player.h"
typedef void (*tws_tone_cb_func_t)(int priv, enum stream_event event);
struct tws_tone_callback {
int func_uuid;
tws_tone_cb_func_t callback;
const char *task_name;
};
extern const struct tws_tone_callback tws_tone_cb_begin[];
extern const struct tws_tone_callback tws_tone_cb_end[];
/*
* 注册TWS回调函数, 播放结束时主从都会调用
*/
#define REGISTER_TWS_TONE_CALLBACK(cb_stub) \
static const struct tws_tone_callback __tws_tone_##cb_stub sec(.tws_tone_callback)
/*---------------TWS同步播放提示音接口-----------------------
*
* delay_msec: 表示多少msec以后tws同时开始出声音
* 由于TWS每次通信有一定的时间间隔,环境无线干扰可能导致通信失败
* 建议delay_msec设置在300ms以上,以增加抗干扰的能力
*
* ---------------------------------------------------------*/
/*
* 默认叠加方式同步播放单个文件, 可能由于受资源限制而采样打断的方式播放
*/
int tws_play_tone_file(const char *file_name, int delay_msec);
int tws_play_tone_file_callback(const char *file_name, int delay_msec, u32 func_uuid);
/*
* 打断方式同步播放单个文件
*/
int tws_play_tone_file_alone(const char *file_name, int delay_msec);
int tws_play_tone_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid);
/*
* 同步播放文件列表
*/
int tws_play_tone_files(const char *const file_name[], u8 file_num, int delay_msec);
int tws_play_tone_files_callback(const char *const file_name[], u8 file_num,
int delay_msec, u32 func_uuid);
int tws_play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
int delay_msec, u32 func_uuid);
/*
* 同步播放铃声
*/
int tws_play_ring_file(const char *file_name, int delay_msec);
int tws_play_ring_file_callback(const char *file_name, int delay_msec, u32 func_uuid);
int tws_play_ring_file_alone(const char *file_name, int delay_msec);
int tws_play_ring_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid);
#endif
+336
View File
@@ -0,0 +1,336 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".a2dp_player.data.bss")
#pragma data_seg(".a2dp_player.data")
#pragma const_seg(".a2dp_player.text.const")
#pragma code_seg(".a2dp_player.text")
#endif
#include "jlstream.h"
#include "classic/tws_api.h"
#include "media/audio_base.h"
#include "a2dp_player.h"
#include "btstack/a2dp_media_codec.h"
#include "media/bt_audio_timestamp.h"
#include "effects/audio_pitchspeed.h"
#include "app_config.h"
#include "effects/audio_vbass.h"
#include "audio_config_def.h"
#if TCFG_AUDIO_DUT_ENABLE
#include "audio_dut_control.h"
#endif/*TCFG_AUDIO_DUT_ENABLE*/
#if (defined TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE) && TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE
#include "icsd_adt_app.h"
#endif
#if TCFG_SMART_VOICE_ENABLE
#include "smart_voice/smart_voice.h"
#endif
extern struct audio_dac_hdl dac_hdl;
struct a2dp_player {
u8 bt_addr[6];
u16 retry_timer;
s8 a2dp_pitch_mode;
struct jlstream *stream;
};
extern void dac_try_power_on_task_delete();
static struct a2dp_player *g_a2dp_player = NULL;
extern const int CONFIG_BTCTLER_TWS_ENABLE;
static void a2dp_player_callback(void *private_data, int event)
{
struct a2dp_player *player = g_a2dp_player;
printf("a2dp_callback: %d\n", event);
switch (event) {
case STREAM_EVENT_START:
#if AUDIO_VBASS_LINK_VOLUME
vbass_link_volume();
#endif
break;
}
}
static void a2dp_player_set_audio_channel(struct a2dp_player *player)
{
int channel = AUDIO_CH_MIX;
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
}
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, channel);
}
void a2dp_player_tws_event_handler(int *msg)
{
struct tws_event *evt = (struct tws_event *)msg;
u8 state = evt->args[1];
switch (evt->event) {
case TWS_EVENT_MONITOR_START:
if (!(state & TWS_STA_SBC_OPEN)) {
break;
}
case TWS_EVENT_CONNECTION_DETACH:
case TWS_EVENT_REMOVE_PAIRS:
if (g_a2dp_player) {
a2dp_player_set_audio_channel(g_a2dp_player);
}
break;
default:
break;
}
a2dp_tws_timestamp_event_handler(evt->event, evt->args);
}
static int a2dp_player_create(u8 *btaddr)
{
int uuid;
struct a2dp_player *player = g_a2dp_player;
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"a2dp");
if (player) {
if (player->stream) {
if (!memcmp(player->bt_addr, btaddr, 6)) {
return -EEXIST;
}
puts("a2dp_player_busy\n");
return -EBUSY;
}
if (player->retry_timer) {
sys_timer_del(player->retry_timer);
player->retry_timer = 0;
}
} else {
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
g_a2dp_player = player;
}
memcpy(player->bt_addr, btaddr, 6);
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_A2DP_RX);
if (!player->stream) {
printf("create a2dp stream faild\n");
return -EFAULT;
}
return 0;
}
void a2dp_player_low_latency_enable(u8 enable)
{
#if TCFG_USER_BT_CLASSIC_ENABLE
a2dp_file_low_latency_enable(enable);
#endif /* #if TCFG_USER_BT_CLASSIC_ENABLE */
}
static void retry_open_a2dp_player(void *p)
{
if (g_a2dp_player && !g_a2dp_player->stream) {
a2dp_player_open(g_a2dp_player->bt_addr);
}
}
static void retry_start_a2dp_player(void *p)
{
if (g_a2dp_player && g_a2dp_player->stream) {
int err = jlstream_start(g_a2dp_player->stream);
if (err == 0) {
dac_try_power_on_task_delete();
sys_timer_del(g_a2dp_player->retry_timer);
g_a2dp_player->retry_timer = 0;
}
}
}
int a2dp_player_open(u8 *btaddr)
{
int err;
#if (defined TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE) && TCFG_AUDIO_SPEAK_TO_CHAT_ENABLE
if (get_speak_to_chat_state() == AUDIO_ADT_CHAT) {
audio_speak_to_char_sync_suspend();
}
#endif
err = a2dp_player_create(btaddr);
if (err) {
if (err == -EFAULT) {
g_a2dp_player->retry_timer = sys_timer_add(NULL, retry_open_a2dp_player, 200);
}
return err;
}
struct a2dp_player *player = g_a2dp_player;
player->a2dp_pitch_mode = PITCH_0; //默认打开是原声调
jlstream_set_callback(player->stream, NULL, a2dp_player_callback);
jlstream_set_scene(player->stream, STREAM_SCENE_A2DP);
if (CONFIG_BTCTLER_TWS_ENABLE) {
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
int channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, channel);
}
}
err = jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE,
NODE_IOC_SET_BTADDR, (int)player->bt_addr);
if (err == 0) {
err = jlstream_start(player->stream);
if (err) {
g_a2dp_player->retry_timer = sys_timer_add(NULL, retry_start_a2dp_player, 200);
return 0;
} else {
dac_try_power_on_task_delete();
}
}
if (err) {
jlstream_release(player->stream);
free(player);
g_a2dp_player = NULL;
return err;
}
#if (TCFG_SMART_VOICE_ENABLE && TCFG_SMART_VOICE_USE_AEC)
audio_smart_voice_aec_open();
#endif
puts("a2dp_open_dec_file_suss\n");
return 0;
}
int a2dp_player_runing()
{
return g_a2dp_player ? 1 : 0;
}
int a2dp_player_get_btaddr(u8 *btaddr)
{
if (g_a2dp_player) {
memcpy(btaddr, g_a2dp_player->bt_addr, 6);
return 1;
}
return 0;
}
bool a2dp_player_is_playing(u8 *bt_addr)
{
if (g_a2dp_player && memcmp(bt_addr, g_a2dp_player->bt_addr, 6) == 0) {
return 1;
}
return 0;
}
int a2dp_player_start_slience_detect(u8 *btaddr, void (*handler)(u8 *, bool), int msec)
{
if (!g_a2dp_player || memcmp(g_a2dp_player->bt_addr, btaddr, 6)) {
return -EINVAL;
}
return 0;
}
void a2dp_player_close(u8 *btaddr)
{
struct a2dp_player *player = g_a2dp_player;
if (!player) {
return;
}
if (memcmp(player->bt_addr, btaddr, 6)) {
return;
}
if (player->retry_timer) {
sys_timer_del(player->retry_timer);
player->retry_timer = 0;
}
if (player->stream) {
jlstream_stop(player->stream, 100);
jlstream_release(player->stream);
}
free(player);
g_a2dp_player = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"a2dp");
#if (TCFG_SMART_VOICE_ENABLE && TCFG_SMART_VOICE_USE_AEC)
audio_smart_voice_aec_close();
#endif
}
//复位当前的数据流
void a2dp_player_reset(void)
{
u8 bt_addr[6];
if (g_a2dp_player) {
memcpy(bt_addr, g_a2dp_player->bt_addr, 6);
a2dp_player_close(bt_addr);
a2dp_player_open(bt_addr);
}
}
//变调接口
int a2dp_file_pitch_up()
{
struct a2dp_player *player = g_a2dp_player;
if (!player) {
return -1;
}
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
player->a2dp_pitch_mode++;
if (player->a2dp_pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
player->a2dp_pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
}
printf("play pitch up+++%d\n", player->a2dp_pitch_mode);
int ret = a2dp_file_set_pitch(player->a2dp_pitch_mode);
ret = (ret == true) ? player->a2dp_pitch_mode : -1;
return ret;
}
int a2dp_file_pitch_down()
{
struct a2dp_player *player = g_a2dp_player;
if (!player) {
return -1;
}
player->a2dp_pitch_mode--;
if (player->a2dp_pitch_mode < 0) {
player->a2dp_pitch_mode = 0;
}
printf("play pitch down---%d\n", player->a2dp_pitch_mode);
int ret = a2dp_file_set_pitch(player->a2dp_pitch_mode);
ret = (ret == true) ? player->a2dp_pitch_mode : -1;
return ret;
}
int a2dp_file_set_pitch(enum _pitch_level pitch_mode)
{
struct a2dp_player *player = g_a2dp_player;
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
if (pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
}
pitch_speed_param_tool_set pitch_param = {
.pitch = pitch_param_table[pitch_mode],
.speed = 1,
};
if (player) {
player->a2dp_pitch_mode = pitch_mode;
return jlstream_node_ioctl(player->stream, NODE_UUID_PITCH_SPEED, NODE_IOC_SET_PARAM, (int)&pitch_param);
}
return -1;
}
void a2dp_file_pitch_mode_init(enum _pitch_level pitch_mode)
{
struct a2dp_player *player = g_a2dp_player;
if (player) {
player->a2dp_pitch_mode = pitch_mode;
}
}
@@ -0,0 +1,137 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".adda_loop_player.data.bss")
#pragma data_seg(".adda_loop_player.data")
#pragma const_seg(".adda_loop_player.text.const")
#pragma code_seg(".adda_loop_player.text")
#endif
#include "jlstream.h"
#include "adda_loop_player.h"
#include "app_config.h"
#include "effects/audio_pitchspeed.h"
#include "audio_config_def.h"
#include "effects/audio_vbass.h"
#include "adc_file.h"
#include "effects/effects_adj.h"
struct adda_loop_player {
struct jlstream *stream;
int channel;
};
static struct adda_loop_player *g_adda_loop_player = NULL;
static void adda_loop_player_callback(void *private_data, int event)
{
struct adda_loop_player *player = g_adda_loop_player;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
break;
}
}
int adda_loop_dut_switch_channel(void)
{
if (g_adda_loop_player) {
g_adda_loop_player->channel = (g_adda_loop_player->channel == AUDIO_CH_L ? AUDIO_CH_R : AUDIO_CH_L);
int err = jlstream_ioctl(g_adda_loop_player->stream, NODE_IOC_SET_CHANNEL, g_adda_loop_player->channel);
/* printf("l:%x,%d\n",channel,err); */
return err;
} else {
return -EFAULT;
}
}
static int adda_loop_get_adc_num(void)
{
u8 ch_num = 0;
struct adc_file_cfg temp_cfg = {0};
char mode_index = 0;
char cfg_index = 0;//目标配置项序号
struct cfg_info info = {0};
int err = jlstream_read_form_node_info_base(mode_index, "adda_adc", cfg_index, &info);
if (err == 0) {
jlstream_read_form_cfg_data(&info, &temp_cfg);
} else {
printf("adda_adc_file read cfg data err !!!\n");
}
for (int i = 0; i < AUDIO_ADC_MIC_MAX_NUM; i++) {
if (temp_cfg.mic_en_map & BIT(i)) {
ch_num ++;
}
}
return ch_num;
}
int adda_loop_player_open()
{
int err;
struct adda_loop_player *player;
if (g_adda_loop_player) {
return 0;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"adda_loop");
if (uuid == 0) {
return -EFAULT;
}
player = malloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
//设置中断点数
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, AUDIO_ADC_IRQ_POINTS);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_NODE_CONFIG, adda_loop_get_adc_num());
jlstream_node_ioctl(player->stream, NODE_UUID_VOCAL_TRACK_SYNTHESIS, NODE_IOC_SET_PRIV_FMT, AUDIO_ADC_IRQ_POINTS);//四声道时,指定声道合并单个声道的点数
player->channel = AUDIO_CH_L;
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, player->channel);
jlstream_set_callback(player->stream, player->stream, adda_loop_player_callback);
jlstream_set_scene(player->stream, STREAM_SCENE_ADDA_LOOP);
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
g_adda_loop_player = player;
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
bool adda_loop_player_runing()
{
return g_adda_loop_player != NULL;
}
void adda_loop_player_close()
{
struct adda_loop_player *player = g_adda_loop_player;
if (!player) {
return;
}
jlstream_stop(player->stream, 50);
jlstream_release(player->stream);
free(player);
g_adda_loop_player = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"adda_loop");
}
+329
View File
@@ -0,0 +1,329 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".ai_rx_player.data.bss")
#pragma data_seg(".ai_rx_player.data")
#pragma const_seg(".ai_rx_player.text.const")
#pragma code_seg(".ai_rx_player.text")
#endif
#include "jlstream.h"
#include "media/audio_base.h"
#include "system/includes.h"
/* #include "sdk_config.h" */
#include "app_config.h"
#include "audio_config_def.h"
#include "ai_rx_player.h"
#include "jldemuxer.h"
/* #include "rcsp_translator.h" */
/* #include "classic/tws_api.h" */
#if TCFG_AI_RX_NODE_ENABLE
struct ai_rx_player {
struct jlstream *stream;
void *file;
struct list_head entry;
enum stream_scene scene;
u8 *bt_addr;
u8 read_err;
u8 source;
u8 type;
int channel; //记录当前是tws左声道还是右声道
};
extern int CONFIG_BTCTLER_TWS_ENABLE;
static struct list_head g_ai_rx_player_list = LIST_HEAD_INIT(g_ai_rx_player_list);
const struct stream_file_ops ai_file_ops;
#define list_for_each_ai_rx_player(p) \
list_for_each_entry(p, &g_ai_rx_player_list, entry)
static void ai_rx_player_callback(void *private_data, int event)
{
struct ai_rx_player *player = (struct ai_rx_player *)private_data;
printf("ai_rx_player_callback, event: %d\n", event);
switch (event) {
case STREAM_EVENT_START:
break;
}
}
static int ai_file_read(void *file, u8 *buf, int len)
{
int offset = 0;
struct ai_rx_player *player = (struct ai_rx_player *)file;
while (len) {
if (!player->file) {
break;
}
int rlen = 0;
#if TCFG_DEC_DECRYPT_ENABLE
u32 addr;
addr = ftell(player->file);
rlen = fread(buf + offset, len, 1, player->file);
if (rlen && (rlen <= len)) {
cryptanalysis_buff(&player->mply_cipher, buf + offset, addr, rlen); //解密了
}
#else
rlen = fread(buf + offset, len, 1, player->file);
#endif
if (rlen < 0 || rlen == 0) {
if (rlen == (-1)) {
player->read_err = 1; //file err
} else {
if (rlen != 0) {
player->read_err = 2; //dis err
}
}
break;
}
player->read_err = 0;
offset += rlen;
if ((len -= rlen) == 0) {
break;
}
}
return offset;
}
static int ai_file_seek(void *file, int offset, int fromwhere)
{
struct ai_rx_player *player = (struct ai_rx_player *)file;
return fseek(player->file, offset, fromwhere);
}
int ai_file_flen(void *file)
{
struct ai_rx_player *player = (struct ai_rx_player *)file;
u32 len = 0;
if (player->file) {
len = flen(player->file);
}
return len;
}
static int ai_file_close(void *file)
{
struct ai_rx_player *player = (struct ai_rx_player *)file;
if (player->file) {
fclose(player->file);
player->file = NULL;
}
return 0;
}
static int ai_file_get_fmt(void *file, struct stream_fmt *fmt)
{
u8 name[16];
struct ai_rx_player *player = (struct ai_rx_player *)file;
fget_name(player->file, name, 16);
struct stream_file_info info = {
.file = player,
.fname = (char *)name,
.ops = &ai_file_ops,
.scene = player->scene,
};
int err = jldemuxer_get_tone_file_fmt(&info, fmt);
return err;
}
const struct stream_file_ops ai_file_ops = {
.read = ai_file_read,
.seek = ai_file_seek,
.close = ai_file_close,
.get_fmt = ai_file_get_fmt,
};
int ai_rx_player_open(void *file, u8 source, struct ai_rx_player_param *param)
{
int err;
struct ai_rx_player *player;
u16 uuid = 0;
if (!param) {
printf("ai_rx_player param is NULL \n");
return -EFAULT;
}
u8 type = param->type;
list_for_each_ai_rx_player(player) {
if (player->source == source) {
printf("ai_rx_player id %x is opened\n", (u32)source);
return 0;
}
}
if (type == AI_SERVICE_CALL_DOWNSTREAM || type == AI_SERVICE_CALL_UPSTREAM) {
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_rx_call");
} else if (type == AI_SERVICE_MEDIA) {
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_rx_media");
} else {
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_voice");
}
if (uuid == 0) {
return -EFAULT;
}
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
player->file = (FILE *)file;
player->scene = STREAM_SCENE_OPUS;
if (type == AI_SERVICE_CALL_DOWNSTREAM) {
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AI_RX_ESCO_DOWN");
} else if (type == AI_SERVICE_CALL_UPSTREAM) {
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AI_RX_ESCO_UP");
} else {
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_AI_RX);
}
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
list_add_tail(&player->entry, &g_ai_rx_player_list);
/* player->bt_addr = bt_addr; */
player->source = source;
player->type = type;
jlstream_set_callback(player->stream, player, ai_rx_player_callback);
if (type == AI_SERVICE_CALL_DOWNSTREAM || type == AI_SERVICE_CALL_UPSTREAM) {
jlstream_set_scene(player->stream, STREAM_SCENE_ESCO);
} else if (type == AI_SERVICE_MEDIA) {
jlstream_set_scene(player->stream, STREAM_SCENE_A2DP);
} else {
jlstream_set_scene(player->stream, STREAM_SCENE_AI_VOICE);
}
#if 0
if (CONFIG_BTCTLER_TWS_ENABLE) {
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
player->channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, player->channel);
} else {
}
}
#endif
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, AUDIO_CH_MIX);
/* jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_BTADDR, (int)bt_addr); */
jlstream_set_scene(player->stream, player->scene);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PARAM, (int)source);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_FMT, (int)param);
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
NODE_IOC_SET_FILE_LEN, (int)ai_file_flen(player));
#if TCFG_DEC_OGG_OPUS_ENABLE
jlstream_set_dec_file(player->stream, player, &ai_file_ops);
#else
jlstream_set_dec_file(player->stream, player->file, &ai_file_ops);
#endif
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
bool ai_rx_player_runing(u8 source)
{
struct ai_rx_player *player;
list_for_each_ai_rx_player(player) {
if (player->source == source) {
return 1;
}
}
return 0;
}
void ai_rx_player_close(u8 source)
{
struct ai_rx_player *player;
u8 found = 0;
const char *pipeline;
list_for_each_ai_rx_player(player) {
if (player->source == source) {
found = 1;
break;
}
}
if (!found) {
return;
}
if (player->type == AI_SERVICE_CALL_DOWNSTREAM || player->type == AI_SERVICE_CALL_UPSTREAM) {
pipeline = "ai_rx_call";
} else if (player->type == AI_SERVICE_MEDIA) {
pipeline = "ai_rx_media";
} else {
pipeline = "ai_voice";
}
jlstream_stop(player->stream, 0);
jlstream_release(player->stream);
list_del(&player->entry);
free(player);
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)pipeline);
}
/************************测试代码******************************/
#if 0
#include "system/includes.h"
#define SD_ROOT_PATH "storage/sd0/C/"
#define FILE_NAME SD_ROOT_PATH"bd.ogg"
FILE *opus_debug = NULL;
FILE *ai_get_file()
{
opus_debug = fopen(FILE_NAME, "r");
if (opus_debug == NULL) {
ASSERT(0, "opus_debug %p ", opus_debug);
}
return opus_debug;
}
void ai_rx_debug()
{
struct ai_rx_player_param param = {0};
param.coding_type = AUDIO_CODING_OPUS;
param.channel_mode = AUDIO_CH_MIX;
param.sample_rate = 16000;
param.bit_rate = 16000;
param.type = AI_SERVICE_VOICE;
param.frame_dms = 200; //20ms一帧
extern FILE *ai_get_file();
ai_rx_player_open((void *)ai_get_file(), 0, &param);
extern void audio_app_volume_set(u8 state, s16 volume, u8 fade);
audio_app_volume_set(APP_AUDIO_STATE_MUSIC, 100, 1);
}
void ai_rx_close()
{
ai_rx_player_close(0);
fclose(opus_debug);
}
#endif
#endif /*TCFG_AI_RX_NODE_ENABLE*/
@@ -0,0 +1,295 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".avi_audio_player.data.bss")
#pragma data_seg(".avi_audio_player.data")
#pragma const_seg(".avi_audio_player.text.const")
#pragma code_seg(".avi_audio_player.text")
#endif
#include "jlstream.h"
#include "media/audio_base.h"
#include "system/includes.h"
/* #include "sdk_config.h" */
#include "app_config.h"
#include "audio_config_def.h"
#include "avi_audio_player.h"
//#include "avi_audio_player.h"
#include "jldemuxer.h"
/* #include "rcsp_translator.h" */
/* #include "classic/tws_api.h" */
#if TCFG_VIDEO_DIAL_ENABLE
struct avi_audio_player {
struct jlstream *stream;
void *file;
struct list_head entry;
enum stream_scene scene;
u8 *bt_addr;
u8 read_err;
u8 source;
u8 type;
int channel; //记录当前是tws左声道还是右声道
};
extern int CONFIG_BTCTLER_TWS_ENABLE;
static struct list_head g_avi_audio_player_list = LIST_HEAD_INIT(g_avi_audio_player_list);
const struct stream_file_ops avi_file_ops;
#define list_for_each_avi_audio_player(p) \
list_for_each_entry(p, &g_avi_audio_player_list, entry)
static void avi_audio_player_callback(void *private_data, int event)
{
struct avi_audio_player *player = (struct avi_audio_player *)private_data;
printf("avi_audio_player_callback, event: %d\n", event);
switch (event) {
case STREAM_EVENT_START:
break;
}
}
static int avi_file_read(void *file, u8 *buf, int len)
{
int offset = 0;
struct avi_audio_player *player = (struct avi_audio_player *)file;
while (len) {
if (!player->file) {
break;
}
int rlen = 0;
#if TCFG_DEC_DECRYPT_ENABLE
u32 addr;
addr = ftell(player->file);
rlen = fread(buf + offset, len, 1, player->file);
if (rlen && (rlen <= len)) {
cryptanalysis_buff(&player->mply_cipher, buf + offset, addr, rlen); //解密了
}
#else
rlen = fread(buf + offset, len, 1, player->file);
#endif
if (rlen < 0 || rlen == 0) {
if (rlen == (-1)) {
player->read_err = 1; //file err
} else {
if (rlen != 0) {
player->read_err = 2; //dis err
}
}
break;
}
player->read_err = 0;
offset += rlen;
if ((len -= rlen) == 0) {
break;
}
}
return offset;
}
static int avi_file_seek(void *file, int offset, int fromwhere)
{
struct avi_audio_player *player = (struct avi_audio_player *)file;
return fseek(player->file, offset, fromwhere);
}
int avi_file_flen(void *file)
{
struct avi_audio_player *player = (struct avi_audio_player *)file;
u32 len = 0;
if (player->file) {
len = flen(player->file);
}
return len;
}
static int avi_file_close(void *file)
{
struct avi_audio_player *player = (struct avi_audio_player *)file;
if (player->file) {
fclose(player->file);
player->file = NULL;
}
return 0;
}
static int avi_file_get_fmt(void *file, struct stream_fmt *fmt)
{
u8 name[16];
struct avi_audio_player *player = (struct avi_audio_player *)file;
fget_name(player->file, name, 16);
struct stream_file_info info = {
.file = player,
.fname = (char *)name,
.ops = &avi_file_ops,
.scene = player->scene,
};
int err = jldemuxer_get_tone_file_fmt(&info, fmt);
printf("avi_file_get_fmt%p, err: %d\n", fmt, err);
return err;
}
const struct stream_file_ops avi_file_ops = {
.read = avi_file_read,
.seek = avi_file_seek,
.close = avi_file_close,
.get_fmt = avi_file_get_fmt,
};
int avi_audio_player_open(void *file, u8 source, struct avi_audio_player_param *param)
{
printf("avi_audio_player_open, source: %x\n", source);
int err;
struct avi_audio_player *player;
u16 uuid = 0;
if (!param) {
printf("avi_audio_player param is NULL \n");
return -EFAULT;
}
u8 type = param->type;
list_for_each_avi_audio_player(player) {
if (player->source == source) {
printf("avi_audio_player id %x is opened\n", (u32)source);
return 0;
}
}
if (type == AVI_SERVICE_CALL_DOWNSTREAM || type == AVI_SERVICE_CALL_UPSTREAM) {
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"avi_rx_call");
} else if (type == AVI_SERVICE_MEDIA) {
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"avi_rx_media");
} else {
uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"avi_voice");
}
if (uuid == 0) {
return -EFAULT;
}
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
player->file = (FILE *)file;
player->scene = STREAM_SCENE_OPUS;
if (type == AVI_SERVICE_CALL_DOWNSTREAM) {
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AVI_RX_ESCO_DOWN");
} else if (type == AVI_SERVICE_CALL_UPSTREAM) {
player->stream = jlstream_pipeline_parse_by_node_name(uuid, "AVI_RX_ESCO_UP");
} else {
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_VIDEO_DEC);
}
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
list_add_tail(&player->entry, &g_avi_audio_player_list);
/* player->bt_addr = bt_addr; */
player->source = source;
player->type = type;
jlstream_set_callback(player->stream, player, avi_audio_player_callback);
if (type == AVI_SERVICE_CALL_DOWNSTREAM || type == AVI_SERVICE_CALL_UPSTREAM) {
jlstream_set_scene(player->stream, STREAM_SCENE_ESCO);
} else if (type == AVI_SERVICE_MEDIA) {
jlstream_set_scene(player->stream, STREAM_SCENE_A2DP);
} else {
jlstream_set_scene(player->stream, STREAM_SCENE_AI_VOICE);
}
#if 0
if (CONFIG_BTCTLER_TWS_ENABLE) {
if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) {
player->channel = tws_api_get_local_channel() == 'L' ? AUDIO_CH_L : AUDIO_CH_R;
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, player->channel);
} else {
}
}
#endif
jlstream_ioctl(player->stream, NODE_IOC_SET_CHANNEL, AUDIO_CH_MIX);
/* jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_BTADDR, (int)bt_addr); */
jlstream_set_scene(player->stream, player->scene);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PARAM, (int)source);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_FMT, (int)param);
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
NODE_IOC_SET_FILE_LEN, (int)avi_file_flen(player));
#if TCFG_DEC_OGG_OPUS_ENABLE
jlstream_set_dec_file(player->stream, player, &avi_file_ops);
#else
// jlstream_set_dec_file(player->stream, player->file, &avi_file_ops);
#endif
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
bool avi_audio_player_runing(u8 source)
{
struct avi_audio_player *player;
list_for_each_avi_audio_player(player) {
if (player->source == source) {
return 1;
}
}
return 0;
}
void avi_audio_player_close(u8 source)
{
struct avi_audio_player *player;
u8 found = 0;
const char *pipeline;
list_for_each_avi_audio_player(player) {
if (player->source == source) {
found = 1;
break;
}
}
if (!found) {
return;
}
if (player->type == AVI_SERVICE_CALL_DOWNSTREAM || player->type == AVI_SERVICE_CALL_UPSTREAM) {
pipeline = "avi_rx_call";
} else if (player->type == AVI_SERVICE_MEDIA) {
pipeline = "avi_rx_media";
} else {
pipeline = "avi_voice";
}
jlstream_stop(player->stream, 0);
jlstream_release(player->stream);
list_del(&player->entry);
free(player);
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)pipeline);
}
#endif /*TCFG_AVU_RX_NODE_ENABLE*/
@@ -0,0 +1,102 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".dev_flow_player.data.bss")
#pragma data_seg(".dev_flow_player.data")
#pragma const_seg(".dev_flow_player.text.const")
#pragma code_seg(".dev_flow_player.text")
#endif
#include "jlstream.h"
#include "app_config.h"
#include "audio_config_def.h"
#include "dev_flow_player.h"
struct dev_flow_player {
struct jlstream *stream;
};
static struct dev_flow_player *g_dev_flow_player = NULL;
static void dev_flow_player_callback(void *private_data, int event)
{
struct dev_flow_player *player = g_dev_flow_player;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
break;
}
}
//自定义数据流播放器 启动
int dev_flow_player_open(void)
{
int err;
struct dev_flow_player *player;
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"dev_flow");
if (uuid == 0) {
return -EFAULT;
}
player = malloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
/*
导入自定义音频流的源节点UUID,如下自定义源节点为NODE_UUID_SOURCE_DEV,
若是其他源节点,需使用对应节点的UUID,如ADC节点则为NODE_UUID_ADC
*/
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_SOURCE_DEV0);
/* player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_SOURCE_DEV1); */
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
//设置当前数据对应节点的特性
/* err = jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, arg); */
jlstream_set_callback(player->stream, player->stream, dev_flow_player_callback);
jlstream_set_scene(player->stream, STREAM_SCENE_DEV_FLOW);
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
g_dev_flow_player = player;
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
//自定义数据流播放器 查询是否活动
bool dev_flow_player_runing(void)
{
return g_dev_flow_player != NULL;
}
//自定义数据流播放器 关闭
void dev_flow_player_close(void)
{
struct dev_flow_player *player = g_dev_flow_player;
if (!player) {
return;
}
jlstream_stop(player->stream, 50);
jlstream_release(player->stream);
free(player);
g_dev_flow_player = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"dev_flow");
}
+165
View File
@@ -0,0 +1,165 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".esco_player.data.bss")
#pragma data_seg(".esco_player.data")
#pragma const_seg(".esco_player.text.const")
#pragma code_seg(".esco_player.text")
#endif
#include "jlstream.h"
#include "esco_player.h"
#include "app_config.h"
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
#include "icsd_adt_app.h"
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
struct esco_player {
u8 bt_addr[6];
u8 suspend;
struct jlstream *stream;
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
u8 icsd_adt_state;
#endif
};
static struct esco_player *g_esco_player = NULL;
static void esco_player_callback(void *private_data, int event)
{
struct esco_player *player = g_esco_player;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
break;
}
}
int esco_player_open(u8 *bt_addr)
{
int err;
struct esco_player *player;
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"esco");
if (uuid == 0) {
return -EFAULT;
}
player = malloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ESCO_RX);
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
#if TCFG_ESCO_DL_CVSD_SR_USE_16K
jlstream_node_ioctl(player->stream, NODE_UUID_BT_AUDIO_SYNC, NODE_IOC_SET_PRIV_FMT, TCFG_ESCO_DL_CVSD_SR_USE_16K);
#endif /*TCFG_ESCO_DL_CVSD_SR_USE_16K*/
jlstream_set_callback(player->stream, player->stream, esco_player_callback);
jlstream_set_scene(player->stream, STREAM_SCENE_ESCO);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_BTADDR, (int)bt_addr);
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
memcpy(player->bt_addr, bt_addr, 6);
g_esco_player = player;
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
/*通话前关闭adt*/
player->icsd_adt_state = audio_icsd_adt_is_running();
if (player->icsd_adt_state) {
audio_icsd_adt_close(0, 1);
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
bool esco_player_runing()
{
return g_esco_player != NULL;
}
int esco_player_get_btaddr(u8 *btaddr)
{
if (g_esco_player) {
memcpy(btaddr, g_esco_player->bt_addr, 6);
return 1;
}
return 0;
}
int esco_player_suspend(u8 *bt_addr)
{
if (g_esco_player && (memcmp(g_esco_player->bt_addr, bt_addr, 6) == 0)) {
/*jlstream_ioctl(g_esco_player->stream, NODE_IOC_SUSPEND, 0);*/
if (!g_esco_player->suspend) {
jlstream_stop(g_esco_player->stream, 0);
jlstream_release(g_esco_player->stream);
lmp_private_esco_suspend_resume(1);
}
}
return 0;
}
int esco_player_start(u8 *bt_addr)
{
if (g_esco_player && (memcmp(g_esco_player->bt_addr, bt_addr, 6) == 0)) {
/*jlstream_ioctl(g_esco_player->stream, NODE_IOC_START, 0);*/
if (g_esco_player->suspend) {
esco_player_close();
esco_player_open(bt_addr);
}
}
return 0;
}
/*
ESCO状态检测,
param:btaddr 目标蓝牙地址, 传NULL则只检查耳机状态
*/
int esco_player_is_playing(u8 *btaddr)
{
int cur_addr = 1;
if (btaddr && g_esco_player) { //当前蓝牙地址检测
cur_addr = (!memcmp(btaddr, g_esco_player->bt_addr, 6));
}
if (g_esco_player && cur_addr) {
return true;
}
return false;
}
void esco_player_close()
{
struct esco_player *player = g_esco_player;
if (!player) {
return;
}
jlstream_stop(player->stream, 0);
jlstream_release(player->stream);
#if TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN
if (player->icsd_adt_state) {
audio_icsd_adt_open(0);
}
#endif /*TCFG_AUDIO_ANC_ACOUSTIC_DETECTOR_EN*/
free(player);
g_esco_player = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"esco");
}
+838
View File
@@ -0,0 +1,838 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_player.data.bss")
#pragma data_seg(".file_player.data")
#pragma const_seg(".file_player.text.const")
#pragma code_seg(".file_player.text")
#endif
#include "file_player.h"
#include "fs/resfile.h"
#include "os/os_api.h"
#include "system/init.h"
#include "system/includes.h"
#include "app_config.h"
#include "fs/fs.h"
#include "effects/audio_pitchspeed.h"
#include "audio_decoder.h"
#include "jldemuxer.h"
#include "clock_manager/clock_manager.h"
#include "audio_config_def.h"
#include "effects/audio_vbass.h"
#if TCFG_APP_MUSIC_EN
struct music_file_player_hdl {
u8 player_id ;
OS_MUTEX mutex;
struct list_head head;
#if FILE_DEC_DEST_PLAY || FILE_DEC_REPEAT_EN
struct file_player *cur_player ; //当前的音乐播放器句柄
#endif
};
static struct music_file_player_hdl g_file_player;
static int music_file_player_start(struct file_player *);
const struct stream_file_ops music_file_ops;
__attribute__((weak))
void music_event_to_user(int event, u16 fname_uuid)
{
}
void music_player_free(struct file_player *player)
{
if (--player->ref == 0) {
if (player->break_point_flag == 1) {
free(player->break_point);
player->break_point = NULL;
player->break_point_flag = 0;
}
free(player);
#if FILE_DEC_DEST_PLAY || FILE_DEC_REPEAT_EN
g_file_player.cur_player = NULL;
#endif
}
}
extern FILE *music_player_get_file_hdl(void);
extern void music_player_remove_file_hdl(void);
extern int music_player_play_auto_next(void);
static void music_player_callback(void *_player_id, int event)
{
struct file_player *player;
printf("music_callback: %x, %d\n", event, (u8)_player_id);
switch (event) {
case STREAM_EVENT_START:
#if AUDIO_VBASS_LINK_VOLUME
vbass_link_volume();
#endif
if (list_empty(&(g_file_player.head))) { //先判断是否为空防止触发异常
break;
}
os_mutex_pend(&g_file_player.mutex, 0);
player = list_first_entry(&(g_file_player.head), struct file_player, entry);
if (player->player_id != (u8)_player_id) {
os_mutex_post(&g_file_player.mutex);
printf("player_id_not_match: %d\n", player->player_id);
break;
}
os_mutex_post(&g_file_player.mutex);
if (player->callback) {
player->callback(player->priv, 0, STREAM_EVENT_START);
}
break;
case STREAM_EVENT_PREEMPTED:
break;
case STREAM_EVENT_NEGOTIATE_FAILD:
case STREAM_EVENT_STOP:
if (list_empty(&(g_file_player.head))) { //先判断是否为空防止触发异常
break;
}
os_mutex_pend(&g_file_player.mutex, 0);
player = list_first_entry(&(g_file_player.head), struct file_player, entry);
if (player->player_id != (u8)_player_id) {
os_mutex_post(&g_file_player.mutex);
printf("player_id_not_match: %d\n", player->player_id);
break;
}
//list_del(&player->entry);
//jlstream_release(player->stream);
//if (!list_empty(&(g_file_player.head))) {
// struct file_player *p = list_first_entry(&(g_file_player.head), struct file_player, entry);
// music_file_player_start(p);
//}
os_mutex_post(&g_file_player.mutex);
if (player->callback) {
player->callback(player->priv, player->read_err, STREAM_EVENT_STOP);
}
//music_player_free(player);
/* int err = music_player_play_auto_next(); */
break;
}
}
static int music_file_read(void *file, u8 *buf, int len)
{
int offset = 0;
struct file_player *player = (struct file_player *)file;
while (len) {
if (!player->file) {
break;
}
int rlen = 0;
#if TCFG_DEC_DECRYPT_ENABLE
u32 addr;
addr = ftell(player->file);
rlen = fread(buf + offset, len, 1, player->file);
if (rlen && (rlen <= len)) {
cryptanalysis_buff(&player->mply_cipher, buf + offset, addr, rlen); //解密了
}
#else
rlen = fread(buf + offset, len, 1, player->file);
#endif
if (rlen < 0 || rlen == 0) {
if (rlen == (-1)) {
player->read_err = 1; //file err
} else {
if (rlen != 0) {
player->read_err = 2; //dis err
}
}
break;
}
player->read_err = 0;
offset += rlen;
if ((len -= rlen) == 0) {
break;
}
}
return offset;
}
static int music_file_seek(void *file, int offset, int fromwhere)
{
struct file_player *player = (struct file_player *)file;
return fseek(player->file, offset, fromwhere);
}
int music_file_flen(void *file)
{
struct file_player *player = (struct file_player *)file;
u32 len = 0;
if (player->file) {
len = flen(player->file);
}
return len;
}
static int music_file_close(void *file)
{
struct file_player *player = (struct file_player *)file;
if (player->file) {
if (music_player_get_file_hdl()) {
fclose(player->file);
music_player_remove_file_hdl();
}
player->file = NULL;
}
return 0;
}
static int music_file_get_fmt(void *file, struct stream_fmt *fmt)
{
u8 name[16];
struct file_player *player = (struct file_player *)file;
fget_name(player->file, name, 16);
struct stream_file_info info = {
.file = player,
.fname = (char *)name,
.ops = &music_file_ops,
.scene = player->scene,
};
int err = jldemuxer_get_tone_file_fmt(&info, fmt);
return err;
}
const struct stream_file_ops music_file_ops = {
.read = music_file_read,
.seek = music_file_seek,
.close = music_file_close,
.get_fmt = music_file_get_fmt,
};
int music_file_player_pp(struct file_player *music_player)
{
if (music_player && music_player->stream) {
jlstream_pp_toggle(music_player->stream, 50);
if (music_player->status != FILE_PLAYER_STOP) {
music_player->status = ((music_player->status == FILE_PLAYER_START) ? FILE_PLAYER_PAUSE : FILE_PLAYER_START);
}
return 0;
} else {
return -1;
}
}
int music_file_player_ff(u16 step_s, struct file_player *music_player)
{
if (music_player && music_player->stream) {
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_FF, step_s);
return 0;
} else {
return -1;
}
}
int music_file_player_fr(u16 step_s, struct file_player *music_player)
{
if (music_player && music_player->stream) {
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_FR, step_s);
return 0;
} else {
return -1;
}
}
int music_file_get_cur_time(struct file_player *music_player)
{
os_mutex_pend(&g_file_player.mutex, 0);
if (list_empty(&(g_file_player.head))) { //先判断是否为空
os_mutex_post(&g_file_player.mutex);
return -1;
}
if (!music_player) {
music_player = list_first_entry(&(g_file_player.head), struct file_player, entry);
}
if (music_player && music_player->stream) {
int ret = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_GET_CUR_TIME, 0);
os_mutex_post(&g_file_player.mutex);
return ret;
}
os_mutex_post(&g_file_player.mutex);
return -1;
}
int music_file_get_total_time(struct file_player *music_player)
{
if (music_player && music_player->stream) {
return jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_GET_TOTAL_TIME, 0);
}
return -1;
}
int music_file_get_player_status(struct file_player *music_player)
{
enum play_status status = FILE_PLAYER_STOP; //播放结束
if (!(list_empty(&(g_file_player.head))) && music_player && music_player->stream) {
return music_player->status;
}
return status;
}
//变调接口
int music_file_pitch_up(struct file_player *music_player)
{
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
music_player->music_pitch_mode ++;
if (music_player->music_pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
music_player->music_pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
}
printf("play pitch up+++%d\n", music_player->music_pitch_mode);
int ret = music_file_set_pitch(music_player, music_player->music_pitch_mode);
ret = (ret == true) ? music_player->music_pitch_mode : -1;
return ret;
}
int music_file_pitch_down(struct file_player *music_player)
{
music_player->music_pitch_mode --;
if (music_player->music_pitch_mode < 0) {
music_player->music_pitch_mode = 0;
}
printf("play pitch down---%d\n", music_player->music_pitch_mode);
int ret = music_file_set_pitch(music_player, music_player->music_pitch_mode);
ret = (ret == true) ? music_player->music_pitch_mode : -1;
return ret;
}
int music_file_set_pitch(struct file_player *music_player, enum _pitch_level pitch_mode)
{
float pitch_param_table[] = {-12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12};
if (pitch_mode > ARRAY_SIZE(pitch_param_table) - 1) {
pitch_mode = ARRAY_SIZE(pitch_param_table) - 1;
}
pitch_speed_param_tool_set pitch_param = {
.pitch = pitch_param_table[pitch_mode],
.speed = 1,
};
if (music_player) {
music_player->music_pitch_mode = pitch_mode;
return jlstream_node_ioctl(music_player->stream, NODE_UUID_PITCH_SPEED, NODE_IOC_SET_PARAM, (int)&pitch_param);
}
return -1;
}
int music_file_speed_up(struct file_player *music_player) //倍速播放接口
{
float speed_param_table[] = {0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0};
music_player->music_speed_mode ++;
if (music_player->music_speed_mode > ARRAY_SIZE(speed_param_table) - 1) {
music_player->music_speed_mode = ARRAY_SIZE(speed_param_table) - 1;
}
printf("play speed up+++%d\n", music_player->music_speed_mode);
int ret = music_file_set_speed(music_player, music_player->music_speed_mode);
ret = (ret == true) ? music_player->music_speed_mode : -1;
return ret;
}
int music_file_speed_down(struct file_player *music_player) //慢速播放接口
{
music_player->music_speed_mode --;
if (music_player->music_speed_mode < 0) {
music_player->music_speed_mode = 0;
}
printf("play speed down---%d\n", music_player->music_speed_mode);
int ret = music_file_set_speed(music_player, music_player->music_speed_mode);
ret = (ret == true) ? music_player->music_speed_mode : -1;
return ret;
}
int music_file_set_speed(struct file_player *music_player, enum _speed_level speed_mode) //设置播放速度
{
float speed_param_table[] = {0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 3.0, 4.0};
if (speed_mode > ARRAY_SIZE(speed_param_table) - 1) {
speed_mode = ARRAY_SIZE(speed_param_table) - 1;
}
pitch_speed_param_tool_set speed_param = {
.pitch = 0,
.speed = speed_param_table[speed_mode],
};
if (music_player) {
printf("set play speed ---%d, %d\n", music_player->music_speed_mode, (int)(speed_param_table[music_player->music_speed_mode] * 100));
music_player->music_speed_mode = speed_mode;
return jlstream_node_ioctl(music_player->stream, NODE_UUID_PITCH_SPEED, NODE_IOC_SET_PARAM, (int)&speed_param);
}
return -1;
}
#if FILE_DEC_AB_REPEAT_EN
#define AUDIO_AB_REPEAT_CODING_TYPE (AUDIO_CODING_MP3 | AUDIO_CODING_WMA | AUDIO_CODING_WAV | AUDIO_CODING_FLAC | AUDIO_CODING_APE | AUDIO_CODING_DTS)
enum {
AB_REPEAT_STA_NON = 0,
AB_REPEAT_STA_ASTA,
AB_REPEAT_STA_BSTA,
};
static u8 ab_repeat_status = AB_REPEAT_STA_NON; // AB复读状态
/*----------------------------------------------------------------------------*/
/**@brief 设置AB点复读命令
@param ab_cmd: 命令
@param ab_mode: 参数
@return 1: 设置成功 0:设置失败
@note
*/
/*----------------------------------------------------------------------------*/
static int music_file_ab_repeat_set(int ab_cmd, int ab_mode, struct file_player *music_player)
{
int err = false;
if (!music_player) {
return false;
}
printf("ab repat, cmd:0x%x, mode:%d \n", ab_cmd, ab_mode);
struct audio_ab_repeat_mode_param rpt = {0};
rpt.value = ab_mode;
switch (ab_cmd) {
case AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A:
printf(" SET BREAKPOINT A");
err = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_SET_BP_A, (int)&rpt);
break;
case AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B:
printf(" SET BREAKPOINT B");
err = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_SET_BP_B, (int)&rpt);
break;
case AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE:
printf(" CANCEL AB REPEAT");
err = jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_SET_AB_REPEAT, (int)&rpt);
break;
default:
break;
}
return err;
}
/*----------------------------------------------------------------------------*/
/**@brief 切换AB点复读状态
@param
@return true:成功
@note
*/
/*----------------------------------------------------------------------------*/
int music_file_ab_repeat_switch(struct file_player *music_player)
{
if (!music_player) {
return false;
}
switch (music_player->ab_repeat_status) {
case AB_REPEAT_STA_NON:
if (music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A, 0, music_player)) {
music_player->ab_repeat_status = AB_REPEAT_STA_ASTA;
}
break;
case AB_REPEAT_STA_ASTA:
if (music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, 0, music_player)) {
music_player->ab_repeat_status = AB_REPEAT_STA_BSTA;
}
break;
case AB_REPEAT_STA_BSTA:
if (music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, AB_REPEAT_MODE_CUR, music_player)) {
music_player->ab_repeat_status = AB_REPEAT_STA_NON;
}
break;
}
printf("music_file_ab_repeat_switch = %d\n", music_player->ab_repeat_status);
return true;
}
/*----------------------------------------------------------------------------*/
/**@brief 关闭AB点复读
@param
@return true:成功
@note
*/
/*----------------------------------------------------------------------------*/
int music_file_ab_repeat_close(struct file_player *music_player)
{
if (!music_player) {
return false;
}
if (music_player->ab_repeat_status == AB_REPEAT_STA_NON) {
return true;
}
if (music_player->ab_repeat_status == AB_REPEAT_STA_ASTA) {
struct stream_fmt fmt;
jlstream_node_ioctl(music_player->stream, NODE_UUID_SOURCE, NODE_IOC_GET_FMT, (int)&fmt);
switch (fmt.coding_type) {
case AUDIO_CODING_FLAC:
case AUDIO_CODING_DTS:
case AUDIO_CODING_APE:
music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, 0, music_player);
break;
}
}
music_file_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, AB_REPEAT_MODE_CUR, music_player);
music_player->ab_repeat_status = AB_REPEAT_STA_NON;
return true;
}
#endif /*FILE_DEC_AB_REPEAT_EN*/
int music_file_get_breakpoints(struct audio_dec_breakpoint *bp, struct file_player *music_player)
{
if (music_player) {
return jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_GET_BP, (int)bp);
}
return -1;
}
#if FILE_DEC_REPEAT_EN //无缝循环播放
/*----------------------------------------------------------------------------*/
/**@brief 循环播放回调接口
@param *priv: 私有参数
@return 0:循环播放
@return 非0:结束循环
@note
*/
/*----------------------------------------------------------------------------*/
static int file_dec_repeat_cb(void *priv)
{
struct file_player *music_player = priv;
y_printf("file_dec_repeat_cb\n");
if (music_player->repeat_num) {
music_player->repeat_num--;
} else {
printf("file_dec_repeat_cb end\n");
return -1;
}
return 0;
}
/*----------------------------------------------------------------------------*/
/**@brief 设置循环播放次数
@param repeat_num: 循环次数
@return true:成功
@return false:失败
@note
*/
/*----------------------------------------------------------------------------*/
static struct audio_repeat_mode_param rep = {0};
int file_dec_repeat_set(u8 repeat_num, u32 coding_type)
{
struct file_player *music_player = g_file_player.cur_player; //当前的音乐播放器句柄
if (!music_player) {
return false;
}
switch (music_player->stream->coding_type) {
case AUDIO_CODING_MP3:
case AUDIO_CODING_WAV: {
music_player->repeat_num = repeat_num;
/* struct audio_repeat_mode_param rep = {0}; */
rep.flag = 1; //使能
rep.headcut_frame = 2; //依据需求砍掉前面几帧,仅mp3格式有效
rep.tailcut_frame = 2; //依据需求砍掉后面几帧,仅mp3格式有效
rep.repeat_callback = file_dec_repeat_cb;
rep.callback_priv = music_player;
rep.repair_buf = &music_player->repair_buf;
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_REPEAT, (int)&rep);
/* audio_decoder_ioctrl(&dec->file_dec.decoder, AUDIO_IOCTRL_CMD_REPEAT_PLAY, &rep); */
}
return true;
}
return false;
}
#endif
#if FILE_DEC_DEST_PLAY
/*----------------------------------------------------------------------------*/
/**@brief 跳到指定位置开始播放,播放到目标时间后回调
@param start_time: 要跳转过去播放的起始时间
@param dest_time: 要跳转过去播放的目标时间
@param *cb: 到达目标时间后回调
@param *cb_priv: 回调参数
@return true:成功
@return false:失败
@note
*/
/*----------------------------------------------------------------------------*/
struct audio_dest_time_play_param param = {0};
int file_dec_set_start_dest_play(u32 start_time, u32 dest_time, u32(*cb)(void *), void *cb_priv, u32 coding_type, struct file_player *music_player)
{
if (!music_player) {
return false;
}
switch (coding_type) {
case AUDIO_CODING_MP3: {
/* struct audio_dest_time_play_param param = {0}; */
param.start_time = start_time;
param.dest_time = dest_time;
param.callback_func = cb;
param.callback_priv = cb_priv;
jlstream_node_ioctl(music_player->stream, NODE_UUID_DECODER, NODE_IOC_DECODER_DEST_PLAY, (int)&param);
}
return true;
}
return false;
}
/*----------------------------------------------------------------------------*/
/**@brief 跳到指定位置开始播放
@param start_time: 要跳转过去播放的起始时间
@return true:成功
@return false:失败
@note
*/
/*----------------------------------------------------------------------------*/
int file_dec_set_start_play(u32 start_time, u32 coding_type)
{
return file_dec_set_start_dest_play(start_time, 0x7fffffff, NULL, NULL, g_file_player.cur_player->stream->coding_type, g_file_player.cur_player);
}
#endif
static int music_file_player_start(struct file_player *player)
{
int err = -EINVAL;
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"music");
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_MUSIC);
if (!player->stream) {
goto __exit0;
}
#if TCFG_USER_EMITTER_ENABLE
extern u8 *get_cur_connect_emitter_mac_addr(void);
void *bt_addr = get_cur_connect_emitter_mac_addr();
if (!bt_addr) {
printf("========================= err bt_addr null");
} else {
jlstream_node_ioctl(player->stream, NODE_UUID_A2DP_TX, NODE_IOC_SET_BTADDR, (int)bt_addr);
}
#endif
int player_id = player->player_id;
jlstream_set_callback(player->stream, (void *)player_id, music_player_callback);
jlstream_set_scene(player->stream, player->scene);
jlstream_set_coexist(player->stream, player->coexist);
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
NODE_IOC_SET_BP, (int)player->break_point);
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
NODE_IOC_SET_FILE_LEN, (int)music_file_flen(player));
if (player->callback) {
err = player->callback(player->priv, 0, STREAM_EVENT_INIT);
if (err) {
goto __exit1;
}
}
jlstream_set_dec_file(player->stream, player, &music_file_ops);
err = jlstream_start(player->stream);
if (player->stream->coding_type == AUDIO_CODING_MP3) {
#if TCFG_DEC_ID3_V1_ENABLE
if (player->p_mp3_id3_v1) {
id3_obj_post(&player->p_mp3_id3_v1);
}
player->p_mp3_id3_v1 = id3_v1_obj_get(player->file);
#endif
#if TCFG_DEC_ID3_V2_ENABLE
if (player->p_mp3_id3_v2) {
id3_obj_post(&player->p_mp3_id3_v2);
}
player->p_mp3_id3_v2 = id3_v2_obj_get(player->file);
#endif
}
if (err) {
goto __exit1;
}
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
list_del(&player->entry);
if (player->callback) {
/* err = player->callback(player->priv, 0,STREAM_EVENT_NONE); */
}
music_player_free(player);
return err;
}
int music_player_init(struct file_player *player, void *file, struct audio_dec_breakpoint *dbp)
{
player->ref = 1;
if (!file) {
printf("music_player_faild\n");
return -EINVAL;
}
player->file = file;
player->scene = STREAM_SCENE_MUSIC;
player->player_id = g_file_player.player_id++;
player->coexist = STREAM_COEXIST_AUTO;
if (dbp == NULL) {
player->break_point = zalloc(sizeof(struct audio_dec_breakpoint) + BREAKPOINT_DATA_LEN);
player->break_point->data_len = BREAKPOINT_DATA_LEN;
player->break_point_flag = 1;
} else {
player->break_point = dbp;
player->break_point_flag = 0;
}
player->music_speed_mode = PLAY_SPEED_1; //固定开始的时候使用1倍速播放 */
player->music_pitch_mode = PITCH_0; //固定开始时不变调
#if TCFG_DEC_DECRYPT_ENABLE
cipher_init(&player->mply_cipher, TCFG_DEC_DECRYPT_KEY);
void cipher_check_decode_file(CIPHER * pcipher, void *file);
cipher_check_decode_file(&player->mply_cipher, file);
#endif
INIT_LIST_HEAD(&player->entry);
return 0;
}
static struct file_player *music_player_create(void *file, struct audio_dec_breakpoint *dbp)
{
struct file_player *player;
player = zalloc(sizeof(*player));
if (!player) {
return NULL;
}
#if FILE_DEC_DEST_PLAY || FILE_DEC_REPEAT_EN
g_file_player.cur_player = player;
#endif
int err = music_player_init(player, file, dbp);
if (err) {
music_player_free(player);
return NULL;
}
return player;
}
struct file_player *music_player_add(struct file_player *player)
{
os_mutex_pend(&g_file_player.mutex, 0);
if (list_empty(&(g_file_player.head))) {
int err = music_file_player_start(player);
if (err) {
os_mutex_post(&g_file_player.mutex);
return NULL;
}
player->status = FILE_PLAYER_START;
}
list_add_tail(&player->entry, &(g_file_player.head));
os_mutex_post(&g_file_player.mutex);
return player;
}
struct file_player *music_file_play(FILE *file, struct audio_dec_breakpoint *dbp)
{
struct file_player *player;
player = music_player_create(file, dbp);
if (!player) {
return NULL;
}
return music_player_add(player);
}
struct file_player *music_file_play_callback(FILE *file, void *priv, music_player_cb_t callback, struct audio_dec_breakpoint *dbp)
{
struct file_player *player;
player = music_player_create(file, dbp);
if (!player) {
return NULL;
}
player->priv = priv;
player->callback = callback;
return music_player_add(player);
}
int music_player_runing()
{
local_irq_disable();
int ret = list_empty(&(g_file_player.head)) ? 0 : 1;
local_irq_enable();
return ret;
}
void music_file_player_stop()
{
struct file_player *player, *n;
os_mutex_pend(&g_file_player.mutex, 0);
list_for_each_entry_safe(player, n, &(g_file_player.head), entry) {
__list_del_entry(&player->entry);
if (player->stream) {
jlstream_stop(player->stream, 50);
jlstream_release(player->stream);
}
#if TCFG_DEC_ID3_V1_ENABLE
if (player->p_mp3_id3_v1) {
id3_obj_post(&player->p_mp3_id3_v1);
}
#endif
#if TCFG_DEC_ID3_V2_ENABLE
if (player->p_mp3_id3_v2) {
id3_obj_post(&player->p_mp3_id3_v2);
}
#endif
music_player_free(player);
}
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"music");
os_mutex_post(&g_file_player.mutex);
}
struct file_player *get_music_file_player(void) //返回第一个打开的音乐播放器指针
{
struct file_player *player = NULL;
os_mutex_pend(&g_file_player.mutex, 0);
if (list_empty(&(g_file_player.head))) { //先判断是否为空
os_mutex_post(&g_file_player.mutex);
return NULL;
}
player = list_first_entry(&(g_file_player.head), struct file_player, entry);
os_mutex_post(&g_file_player.mutex);
return player;
}
static int __music_player_init()
{
INIT_LIST_HEAD(&g_file_player.head);
os_mutex_create(&g_file_player.mutex);
return 0;
}
__initcall(__music_player_init);
#endif
@@ -0,0 +1,106 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".key_tone_player.data.bss")
#pragma data_seg(".key_tone_player.data")
#pragma const_seg(".key_tone_player.text.const")
#pragma code_seg(".key_tone_player.text")
#endif
#include "tone_player.h"
#include "os/os_api.h"
#include "system/init.h"
#include "app_config.h"
static struct tone_player *g_player = NULL;
static OS_MUTEX g_mutex;
static u8 g_play_cnt = 0;
extern const struct stream_file_ops tone_file_ops;
static void key_tone_player_callback(void *_player_id, int event)
{
switch (event) {
case STREAM_EVENT_START:
break;
case STREAM_EVENT_PREEMPTED:
break;
case STREAM_EVENT_NEGOTIATE_FAILD:
case STREAM_EVENT_STOP:
struct tone_player *player = g_player;
if (!player || player->player_id != (u8)_player_id) {
break;
}
if (g_play_cnt) {
g_play_cnt--;
int err = jlstream_start(player->stream);
if (err == 0) {
break;
}
g_play_cnt = 0;
}
g_player = NULL;
jlstream_release(player->stream);
free(player);
break;
}
}
static int key_tone_player_start(struct tone_player *player)
{
int err = -EINVAL;
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"tone");
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_KEY_TONE);
if (!player->stream) {
goto __exit;
}
int player_id = player->player_id;
jlstream_set_callback(player->stream, (void *)player_id, key_tone_player_callback);
jlstream_set_scene(player->stream, player->scene);
jlstream_set_dec_file(player->stream, player, &tone_file_ops);
err = jlstream_start(player->stream);
if (err) {
goto __exit;
}
g_player = player;
return 0;
__exit:
if (player->stream) {
jlstream_release(player->stream);
}
if (player->file) {
resfile_close(player->file);
player->file = NULL;
}
free(player);
return err;
}
int play_key_tone_file(const char *file_name)
{
struct tone_player *player;
if (g_player) {
if (g_play_cnt < 10) {
g_play_cnt++;
}
return 0;
}
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
int err = tone_player_init(player, file_name);
if (err) {
free(player);
return err;
}
player->scene = STREAM_SCENE_KEY_TONE;
return key_tone_player_start(player);
}
+306
View File
@@ -0,0 +1,306 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".pc_spk_player.data.bss")
#pragma data_seg(".pc_spk_player.data")
#pragma const_seg(".pc_spk_player.text.const")
#pragma code_seg(".pc_spk_player.text")
#endif
#include "jlstream.h"
#include "sdk_config.h"
#include "system/timer.h"
#include "system/includes.h"
#include "pc_spk_player.h"
#include "pc_spk_file.h"
#include "app_config.h"
#include "app_main.h"
#include "effects/audio_pitchspeed.h"
#include "effect/effects_default_param.h"
#include "audio_config.h"
#include "scene_switch.h"
#include "uac_stream.h"
#include "audio_cvp.h"
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN)
#include "le_broadcast.h"
#include "app_le_broadcast.h"
#endif
#if (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
#include "app_le_auracast.h"
#endif
#define LOG_TAG_CONST USB
#define LOG_TAG "[pcspk]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
/* #define LOG_INFO_ENABLE */
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
typedef enum {
PC_SPK_STA_CLOSE,
PC_SPK_STA_WAIT_CLOSE,
PC_SPK_STA_OPEN,
PC_SPK_STA_WAIT_OPEN,
} pc_spk_state_t;
pc_spk_state_t g_pc_spk_state;
struct pc_spk_player {
struct jlstream *stream;
s8 pc_spk_pitch_mode;
};
static struct pc_spk_player *g_pc_spk_player = NULL;
extern void dac_try_power_on_task_delete();
static void pc_spk_player_callback(void *private_data, int event)
{
struct pc_spk_player *player = g_pc_spk_player;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
#if TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE)
//先开pc mic,后开spk,需要取消忽略外部数据,重启aec
if (audio_aec_status()) {
audio_aec_reboot(0);
audio_cvp_ref_data_align_reset();
}
#endif
if (app_get_current_mode()->name == APP_MODE_PC) {
s16 cur_vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
u16 l_vol = 0, r_vol = 0;
uac_speaker_stream_get_volume(&l_vol, &r_vol);
if (cur_vol != (r_vol + l_vol) / 2) {
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, (r_vol + l_vol) / 2, 1);
}
}
#if TCFG_VOCAL_REMOVER_NODE_ENABLE
musci_vocal_remover_update_parm();
#endif
break;
}
}
/*
* @description: 打开 pc spk 数据流
* @return0 - 成功。其它值失败
* @node:
*/
int pc_spk_player_open(void)
{
u32 rets_addr;
__asm__ volatile("%0 = rets ;" : "=r"(rets_addr));
int err = 0;
struct pc_spk_player *player = NULL;;
if (g_pc_spk_player || !app_in_mode(APP_MODE_PC)) {
return 0;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"pc_spk");
if (uuid == 0) {
return -EFAULT;
}
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
player->pc_spk_pitch_mode = PITCH_0;
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_PC_SPK);
if (!player->stream) {
err = -ENOMEM;
goto __exit0;
}
u16 l_vol = 0, r_vol = 0;
uac_speaker_stream_get_volume(&l_vol, &r_vol);
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, (r_vol + l_vol) / 2, 1);
jlstream_node_ioctl(player->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 192);
jlstream_set_callback(player->stream, player->stream, pc_spk_player_callback);
jlstream_set_scene(player->stream, STREAM_SCENE_PC_SPK);
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
} else {
dac_try_power_on_task_delete();
}
g_pc_spk_state = PC_SPK_STA_OPEN;
g_pc_spk_player = player;
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
free(player);
return err;
}
// 返回1说明player 在运行
bool pc_spk_player_runing()
{
return g_pc_spk_player != NULL;
}
/*
* @description: 关闭spk 数据流
* @return
* @node:
*/
void pc_spk_player_close(void)
{
struct pc_spk_player *player = g_pc_spk_player;
if (!player) {
if (g_pc_spk_state == PC_SPK_STA_WAIT_OPEN || g_pc_spk_state == PC_SPK_STA_OPEN) {
//可能在切到其它模式瞬间有spk音频起来,打开spk采用的是信号量方式打开,导致关闭spk的动作比打开的动作更提前
log_debug("err, [%s], player_wait_open_flag:1!\n", __func__);
pcspk_close_player_by_taskq();
}
return;
}
#if 0//pc + bt 通过mixer叠加的环境, 因usbrx已经停止,无法驱动数据流。需手动提前将当前的mixer ch关闭
struct mixer_ch_pause pause = {0};
pause.ch_idx = 7;
jlstream_set_node_param(NODE_UUID_MIXER, "MIXER27", &pause, sizeof(pause));
#endif
jlstream_stop(player->stream, 0);
jlstream_release(player->stream);
free(player);
player = NULL;
g_pc_spk_player = NULL;
#if TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE)
if (audio_aec_status()) {
//忽略参考数据
audio_cvp_ioctl(CVP_OUTWAY_REF_IGNORE, 1, NULL);
audio_cvp_ref_data_align_reset();
}
#endif
jlstream_event_notify(STREAM_EVENT_CLOSE_PLAYER, (int)"pc_spk");
g_pc_spk_state = PC_SPK_STA_CLOSE;
}
static void pc_spk_player_restert(void)
{
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN)
if (!get_broadcast_role()) {
if (g_pc_spk_state == PC_SPK_STA_OPEN) {
pc_spk_player_close();
pc_spk_player_open();
}
} else { //广播模式则重启广播数据流
le_audio_scene_deal(LE_AUDIO_MUSIC_STOP);
le_audio_scene_deal(LE_AUDIO_MUSIC_START);
}
#elif (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
if (!get_auracast_role()) {
if (g_pc_spk_state == PC_SPK_STA_OPEN) {
pc_spk_player_close();
pc_spk_player_open();
}
} else { //广播模式则重启广播数据流
le_audio_scene_deal(LE_AUDIO_MUSIC_STOP);
le_audio_scene_deal(LE_AUDIO_MUSIC_START);
}
#else
if (g_pc_spk_state == PC_SPK_STA_OPEN) {
pc_spk_player_close();
pc_spk_player_open();
}
#endif
}
int pcspk_close_player_by_taskq(void)
{
int msg[2];
int ret = 0;
if (g_pc_spk_state == PC_SPK_STA_OPEN ||
g_pc_spk_state == PC_SPK_STA_WAIT_OPEN) {
g_pc_spk_state = PC_SPK_STA_WAIT_CLOSE;
msg[0] = (int)pc_spk_player_close;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
}
return ret;
}
int pcspk_open_player_by_taskq(void)
{
int msg[2];
int ret = 0;
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN) && !TCFG_KBOX_1T3_MODE_EN
if ((g_pc_spk_state == PC_SPK_STA_CLOSE ||
g_pc_spk_state == PC_SPK_STA_WAIT_CLOSE) && !get_broadcast_role()) {
#elif (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
if ((g_pc_spk_state == PC_SPK_STA_CLOSE ||
g_pc_spk_state == PC_SPK_STA_WAIT_CLOSE) && !get_auracast_role()) {
#else
if (g_pc_spk_state == PC_SPK_STA_CLOSE ||
g_pc_spk_state == PC_SPK_STA_WAIT_CLOSE) {
#endif
g_pc_spk_state = PC_SPK_STA_WAIT_OPEN;
msg[0] = (int)pc_spk_player_open;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
}
return ret;
}
int pcspk_restart_player_by_taskq(void)
{
int msg[2];
int ret = 0;
msg[0] = (int)pc_spk_player_restert;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
return ret;
}
static void pc_spk_set_volume(void)
{
if (app_get_current_mode()->name == APP_MODE_PC) {
s16 cur_vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
u16 l_vol = 0, r_vol = 0;
uac_speaker_stream_get_volume(&l_vol, &r_vol);
if (cur_vol != ((l_vol + r_vol) / 2)) {
app_audio_set_volume(APP_AUDIO_STATE_MUSIC, ((l_vol + r_vol) / 2), 1);
log_debug(">>> pc vol: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE));
}
}
}
int pcspk_set_volume_by_taskq(void)
{
int msg[2];
int ret = -1;
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
msg[0] = (int)pc_spk_set_volume;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
#endif
return ret;
}
#else
bool pc_spk_player_runing()
{
return 0;
}
#endif
+285
View File
@@ -0,0 +1,285 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".reference_time.data.bss")
#pragma data_seg(".reference_time.data")
#pragma const_seg(".reference_time.text.const")
#pragma code_seg(".reference_time.text")
#endif
/*************************************************************************************************/
/*!
* \file reference_time.c
*
* \brief 提供音频参考时钟选择的接口函数实体与管理
*
* Copyright (c) 2011-2022 ZhuHai Jieli Technology Co.,Ltd.
*
*/
/*************************************************************************************************/
#include "reference_time.h"
#include "system/includes.h"
/* #include "le_audio_stream.h" */
/*
* 关于优先级选择:
* 手机的网络时钟优先级最高,无手机网络的情况下选择TWS网络
*/
static LIST_HEAD(reference_head);
static u8 local_network = 0xff;
static u8 local_net_addr[6];
static u8 local_network_id = 1;
extern const int LE_AUDIO_TIME_ENABLE;
struct reference_clock {
u8 id;
u8 network;
union {
u8 net_addr[6];
void *le_addr;
};
struct list_head entry;
};
extern void bt_audio_reference_clock_select(void *addr, u8 network);
extern u32 bt_audio_reference_clock_time(u8 network);
extern u32 bt_audio_reference_clock_remapping(void *src_addr, u8 src_network, void *dst_addr, u8 dst_network, u32 clock);
extern u8 bt_audio_reference_link_exist(void *addr, u8 network);
//le audio相关函数弱定义
__attribute__((weak))
int le_audio_stream_clock_select(void *le_audio)
{
printf("empty fun %s\n", __FUNCTION__);
return 0;
}
__attribute__((weak))
u32 le_audio_stream_current_time(void *le_audio)
{
printf("empty fun %s\n", __FUNCTION__);
return 0;
}
__attribute__((weak))
int le_audio_stream_get_latch_time(void *le_audio, u32 *time, u16 *us_1_12th, u32 *event)
{
printf("empty fun %s\n", __FUNCTION__);
return 0;
}
__attribute__((weak))
void le_audio_stream_latch_time_enable(void *le_audio)
{
printf("empty fun %s\n", __FUNCTION__);
}
int audio_reference_clock_select(void *addr, u8 network)
{
struct reference_clock *reference_clock = (struct reference_clock *)zalloc(sizeof(struct reference_clock));
struct reference_clock *clk;
u8 reset_clock = 1;
local_irq_disable();
if (network > 2) {
local_irq_enable();
free(reference_clock);
return 0;
}
if (list_empty(&reference_head) || network == 0) {
reference_clock->network = network;
if (LE_AUDIO_TIME_ENABLE && network == 2) {
reference_clock->le_addr = addr;
} else {
if (addr == NULL) {
memset(reference_clock->net_addr, 0x0, sizeof(reference_clock->net_addr));
} else {
memcpy(reference_clock->net_addr, addr, sizeof(reference_clock->net_addr));
}
}
} else {
clk = list_first_entry(&reference_head, struct reference_clock, entry);
if (clk->network == 0 && bt_audio_reference_link_exist(clk->net_addr, clk->network)) {
reference_clock->network = clk->network;
memcpy(reference_clock->net_addr, clk->net_addr, sizeof(reference_clock->net_addr));
reset_clock = 0;
} else {
reference_clock->network = network;
if (LE_AUDIO_TIME_ENABLE && network == 2) {
reference_clock->le_addr = addr;
} else {
if (addr == NULL) {
memset(reference_clock->net_addr, 0x0, sizeof(reference_clock->net_addr));
} else {
memcpy(reference_clock->net_addr, addr, sizeof(reference_clock->net_addr));
}
}
}
}
list_add(&reference_clock->entry, &reference_head);
reference_clock->id = local_network_id;
if (++local_network_id == 0) {
local_network_id++;
}
local_irq_enable();
if (reset_clock) {
if (LE_AUDIO_TIME_ENABLE && reference_clock->network == 2) {
le_audio_stream_clock_select(reference_clock->le_addr);
} else {
bt_audio_reference_clock_select(reference_clock->net_addr, reference_clock->network);
}
}
return reference_clock->id;
}
u32 audio_reference_clock_time(void)
{
if (!list_empty(&reference_head)) {
struct reference_clock *clk;
clk = list_first_entry(&reference_head, struct reference_clock, entry);
if (LE_AUDIO_TIME_ENABLE && clk->network == 2) {
return le_audio_stream_current_time(clk->le_addr);
}
return bt_audio_reference_clock_time(clk->network);
}
return bt_audio_reference_clock_time(local_network);
}
u32 audio_reference_network_clock_time(u8 network)
{
return bt_audio_reference_clock_time(network);
}
u8 audio_reference_network_exist(u8 id)
{
struct reference_clock *clk;
local_irq_disable();
list_for_each_entry(clk, &reference_head, entry) {
if (clk->id == id) {
goto exist_detect;
}
}
local_irq_enable();
return 0;
exist_detect:
local_irq_enable();
return bt_audio_reference_link_exist(clk->net_addr, clk->network);
}
int le_audio_get_reference_latch_time(u32 *time, u16 *us_1_12th, u32 *event)
{
if (!LE_AUDIO_TIME_ENABLE) {
return 0;
}
if (!list_empty(&reference_head)) {
struct reference_clock *clk;
clk = list_first_entry(&reference_head, struct reference_clock, entry);
if (clk->network == 2) {
le_audio_stream_get_latch_time(clk->le_addr, time, us_1_12th, event);
}
}
return 0;
}
void le_audio_reference_time_latch_enable(void)
{
if (!LE_AUDIO_TIME_ENABLE) {
return;
}
if (!list_empty(&reference_head)) {
struct reference_clock *clk;
clk = list_first_entry(&reference_head, struct reference_clock, entry);
if (clk->network == 2) {
le_audio_stream_latch_time_enable(clk->le_addr);
}
}
}
u8 is_audio_reference_clock_enable(void)
{
return 0;
/*return local_network == 0xff ? 0 : 1;*/
}
u8 audio_reference_clock_network(void *addr)
{
struct reference_clock *clk;
if (list_empty(&reference_head)) {
return -1;
}
clk = list_first_entry(&reference_head, struct reference_clock, entry);
if (clk->network != 2 && addr) {
memcpy(addr, clk->net_addr, 6);
}
return clk->network;
}
u8 audio_reference_clock_match(void *addr, u8 network)
{
struct reference_clock *clk;
if (list_empty(&reference_head)) {
return 0;
}
clk = list_first_entry(&reference_head, struct reference_clock, entry);
if (clk->network == network) {
if (network == 0) {
if (addr && memcmp(clk->net_addr, addr, 6) == 0) {
return 1;
}
return 0;
}
return 1;
}
return 0;
}
u32 audio_reference_clock_remapping(u8 now_network, u8 dst_network, u32 clock)
{
void *now_addr = NULL;
void *dst_addr = NULL;
struct reference_clock *clk;
local_irq_disable();
list_for_each_entry(clk, &reference_head, entry) {
if (!now_addr && clk->network == now_network) {
now_addr = clk->net_addr;
}
if (!dst_addr && clk->network == dst_network) {
dst_addr = clk->net_addr;
}
}
local_irq_enable();
return bt_audio_reference_clock_remapping(now_addr, now_network, dst_addr, dst_network, clock);
}
void audio_reference_clock_exit(u8 id)
{
struct reference_clock *clk;
local_irq_disable();
list_for_each_entry(clk, &reference_head, entry) {
if (clk->id == id) {
goto delete;
}
}
local_irq_enable();
return;
delete:
list_del(&clk->entry);
free(clk);
if (!list_empty(&reference_head)) {
/*clk = list_first_entry(&reference_head, struct reference_clock, entry);*/
/*bt_audio_reference_clock_select(clk->net_addr, clk->network);*/
}
local_irq_enable();
}
+190
View File
@@ -0,0 +1,190 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".ring_player.data.bss")
#pragma data_seg(".ring_player.data")
#pragma const_seg(".ring_player.text.const")
#pragma code_seg(".ring_player.text")
#endif
#include "tone_player.h"
#include "os/os_api.h"
#include "system/init.h"
#include "app_config.h"
static struct tone_player *g_ring_player = NULL;
static OS_MUTEX g_ring_mutex;
extern const struct stream_file_ops tone_file_ops;
static void ring_player_callback(void *_player_id, int event)
{
struct tone_player *player = g_ring_player;
switch (event) {
case STREAM_EVENT_START:
os_mutex_pend(&g_ring_mutex, 0);
if (player && player->player_id == (u8)_player_id) {
if (player->callback) {
player->callback(player->priv, STREAM_EVENT_START);
}
}
os_mutex_post(&g_ring_mutex);
break;
case STREAM_EVENT_PREEMPTED:
break;
case STREAM_EVENT_NEGOTIATE_FAILD:
case STREAM_EVENT_STOP:
os_mutex_pend(&g_ring_mutex, 0);
if (!player || player->player_id != (u8)_player_id) {
os_mutex_post(&g_ring_mutex);
break;
}
g_ring_player = NULL;
jlstream_release(player->stream);
os_mutex_post(&g_ring_mutex);
tone_player_free(player);
break;
}
}
int ring_player_start(struct tone_player *player)
{
int err = -EINVAL;
if (g_ring_player) {
goto __exit;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ring");
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_RING);
if (!player->stream) {
goto __exit;
}
int player_id = player->player_id;
jlstream_set_callback(player->stream, (void *)player_id, ring_player_callback);
jlstream_set_scene(player->stream, player->scene);
jlstream_set_coexist(player->stream, player->coexist);
if (player->callback) {
err = player->callback(player->priv, STREAM_EVENT_INIT);
if (err) {
goto __exit;
}
}
jlstream_set_dec_file(player->stream, player, &tone_file_ops);
err = jlstream_start(player->stream);
if (err) {
goto __exit;
}
g_ring_player = player;
return 0;
__exit:
if (player->stream) {
jlstream_release(player->stream);
}
tone_player_free(player);
return err;
}
static int __play_ring_file(const char *file_name, enum stream_coexist coexist)
{
struct tone_player *player;
if (g_ring_player) {
return -EBUSY;
}
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
int err = tone_player_init(player, file_name);
if (err) {
tone_player_free(player);
return err;
}
player->scene = STREAM_SCENE_RING;
player->coexist = coexist;
return ring_player_start(player);
}
int play_ring_file(const char *file_name)
{
return __play_ring_file(file_name, STREAM_COEXIST_AUTO);
}
int play_ring_file_alone(const char *file_name)
{
return __play_ring_file(file_name, STREAM_COEXIST_DISABLE);
}
static int __play_ring_file_with_calllback(const char *file_name, enum stream_coexist coexist, void *priv, tone_player_cb_t callback)
{
struct tone_player *player;
if (g_ring_player) {
return -EBUSY;
}
player = zalloc(sizeof(*player));
if (!player) {
return -ENOMEM;
}
int err = tone_player_init(player, file_name);
if (err) {
tone_player_free(player);
return err;
}
player->priv = priv;
player->callback = callback;
player->scene = STREAM_SCENE_RING;
player->coexist = coexist;
return ring_player_start(player);
}
int play_ring_file_with_callback(const char *file_name, void *priv, tone_player_cb_t callback)
{
return __play_ring_file_with_calllback(file_name, STREAM_COEXIST_AUTO, priv, callback);
}
int play_ring_file_alone_with_callback(const char *file_name, void *priv, tone_player_cb_t callback)
{
return __play_ring_file_with_calllback(file_name, STREAM_COEXIST_DISABLE, priv, callback);
}
int ring_player_runing()
{
return g_ring_player ? 1 : 0;
}
void ring_player_stop()
{
os_mutex_pend(&g_ring_mutex, 0);
struct tone_player *player = g_ring_player;
if (player) {
if (player->stream) {
jlstream_stop(player->stream, 50);
jlstream_release(player->stream);
}
g_ring_player = NULL;
}
os_mutex_post(&g_ring_mutex);
if (player) {
tone_player_free(player);
}
}
static int __ring_player_init()
{
os_mutex_create(&g_ring_mutex);
return 0;
}
__initcall(__ring_player_init);
+637
View File
@@ -0,0 +1,637 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".tone_player.data.bss")
#pragma data_seg(".tone_player.data")
#pragma const_seg(".tone_player.text.const")
#pragma code_seg(".tone_player.text")
#endif
#include "tone_player.h"
#include "fs/resfile.h"
#include "os/os_api.h"
#include "system/init.h"
#include "decoder_node.h"
#include "jldemuxer.h"
#include "app_config.h"
extern const struct decoder_plug_ops decoder_plug_begin[];
extern const struct decoder_plug_ops decoder_plug_end[];
const struct stream_file_ops tone_file_ops;
static u8 g_player_id = 0;
static OS_MUTEX g_tone_mutex;
static struct list_head g_head = LIST_HEAD_INIT(g_head);
static int tone_player_start(struct tone_player *);
static int tone_file_close(void *file);
__attribute__((weak))
void tone_event_to_user(int event, u16 fname_uuid)
{
}
static void *open_next_file(struct tone_player *player)
{
if (player->next_file) {
void *file = player->next_file;
player->next_file = NULL;
return file;
}
int index = ++player->index;
do {
if (player->file_name_list[index]) {
char file_path[48];
strcpy(file_path, FLASH_RES_PATH);
strcpy(file_path + strlen(FLASH_RES_PATH), player->file_name_list[index]);
void *file = resfile_open(file_path);
if (file) {
player->index = index;
return file;
}
index++;
} else {
player->index = 0;
break;
}
} while (index != player->index);
return NULL;
}
static int tone_player_post_asyc_callback(tone_player_cb_t callback, void *cb_priv)
{
int msg[4];
msg[0] = (int)callback;
msg[1] = 2;
msg[2] = (int)cb_priv;
msg[3] = (int)STREAM_EVENT_STOP;
return os_taskq_post_type("app_core", Q_CALLBACK, 4, msg);
}
void tone_player_free(struct tone_player *player)
{
int fname_uuid = player->fname_uuid;
void *cb_priv = player->priv;
tone_player_cb_t callback = player->callback;
if (--player->ref == 0) {
tone_file_close(player);
free(player);
}
if (callback) {
/* callback(cb_priv, STREAM_EVENT_STOP); */
tone_player_post_asyc_callback(callback, cb_priv);
} else {
tone_event_to_user(STREAM_EVENT_STOP, fname_uuid);
}
}
static void tone_player_callback(void *_player_id, int event)
{
void *file = NULL;
struct tone_player *player;
printf("tone_callback: %x, %d\n", event, (u8)_player_id);
switch (event) {
case STREAM_EVENT_START:
os_mutex_pend(&g_tone_mutex, 0);
if (list_empty(&g_head)) { //先判断是否为空防止触发异常
os_mutex_post(&g_tone_mutex);
break;
}
player = list_first_entry(&g_head, struct tone_player, entry);
if (player->player_id == (u8)_player_id) {
if (player->callback) {
player->callback(player->priv, STREAM_EVENT_START);
}
}
os_mutex_post(&g_tone_mutex);
break;
case STREAM_EVENT_PREEMPTED:
case STREAM_EVENT_NEGOTIATE_FAILD:
/*
* 提示音被抢占或者参数协商失败,直接结束播放
*/
case STREAM_EVENT_STOP:
os_mutex_pend(&g_tone_mutex, 0);
if (list_empty(&g_head)) { //先判断是否为空防止触发异常
os_mutex_post(&g_tone_mutex);
break;
}
player = list_first_entry(&g_head, struct tone_player, entry);
if (player->player_id != (u8)_player_id) {
os_mutex_post(&g_tone_mutex);
printf("player_id_not_match: %d\n", player->player_id);
break;
}
if (event == STREAM_EVENT_STOP) {
/*
* 打开文件列表的下一个文件,重新启动解码
*/
while (1) {
file = open_next_file(player);
if (!file) {
break;
}
resfile_close(player->file);
player->file = file;
int err = jlstream_start(player->stream);
if (err == 0) {
break;
}
}
}
if (!file) {
jlstream_release(player->stream);
list_del(&player->entry);
if (!list_empty(&g_head)) {
struct tone_player *p;
p = list_first_entry(&g_head, struct tone_player, entry);
tone_player_start(p);
}
tone_player_free(player);
}
os_mutex_post(&g_tone_mutex);
break;
}
}
static int tone_file_read(void *p_file, u8 *buf, int len)
{
int offset = 0;
struct tone_player *player = (struct tone_player *)p_file;
while (len) {
if (!player->file) {
break;
}
int rlen = resfile_read(player->file, buf + offset, len);
if (rlen < 0) {
break;
}
offset += rlen;
if ((len -= rlen) == 0) {
break;
}
if (player->scene == STREAM_SCENE_RING) {
if (player->coding_type == AUDIO_CODING_WTGV2) {
//WTS拼接提示音时,去掉头1byte
resfile_seek(player->file, 1, RESFILE_SEEK_SET);
} else {
resfile_seek(player->file, 0, RESFILE_SEEK_SET);
if (player->coding_type == AUDIO_CODING_MP3) {
break;
}
}
continue;
}
if (player->next_file) {
break;
}
/*
* 打开文件列表中的下一个文件,检查format是否和当前文件相同
* 如果相同就继读下一个文件, 可以保证TWS同步播放文件列表情况下的音频同步
*/
int index = player->index;
void *file = open_next_file(player);
if (!file) {
player->index = index;
break;
}
char name[16];
resfile_get_name(file, name, 16);
struct stream_file_ops file_ops = {
.read = (int (*)(void *, u8 *, int))resfile_read,
.seek = (int (*)(void *, int, int))resfile_seek,
};
struct stream_file_info file_info = {
.file = file,
.fname = name,
.ops = &file_ops,
};
struct stream_fmt fmt;
int err = jldemuxer_get_tone_file_fmt(&file_info, &fmt);
if (err == 0) {
if (player->coding_type == fmt.coding_type &&
player->sample_rate == fmt.sample_rate &&
player->channel_mode == fmt.channel_mode) {
resfile_close(player->file);
player->file = file;
if (player->coding_type == AUDIO_CODING_WTGV2) {
//WTS拼接提示音时,去掉头1byte
resfile_seek(player->file, 1, RESFILE_SEEK_SET);
}
continue;
}
}
player->next_file = file;
break;
}
return offset;
}
static int tone_file_seek(void *file, int offset, int fromwhere)
{
struct tone_player *player = (struct tone_player *)file;
return resfile_seek(player->file, offset, fromwhere);
}
static int tone_file_flen(void *file)
{
struct tone_player *player = (struct tone_player *)file;
u32 len = 0;
if (player->file) {
len = resfile_get_len(player->file);
}
return len;
}
static int tone_file_close(void *file)
{
struct tone_player *player = (struct tone_player *)file;
if (player->file) {
resfile_close(player->file);
player->file = NULL;
}
if (player->next_file) {
resfile_close(player->next_file);
player->next_file = NULL;
}
return 0;
}
static int tone_file_get_fmt(void *file, struct stream_fmt *fmt)
{
struct tone_player *player = (struct tone_player *)file;
char name[16];
resfile_get_name(player->file, name, 16);
struct stream_file_info file_info = {
.file = player,
.fname = name,
.ops = &tone_file_ops,
};
int err = jldemuxer_get_tone_file_fmt(&file_info, fmt);
if (err) {
player->coding_type = AUDIO_CODING_UNKNOW;
return err;
}
player->coding_type = fmt->coding_type;
player->sample_rate = fmt->sample_rate;
player->channel_mode = fmt->channel_mode;
return 0;
}
const struct stream_file_ops tone_file_ops = {
.read = tone_file_read,
.seek = tone_file_seek,
.close = tone_file_close,
.get_fmt = tone_file_get_fmt,
};
int tone_player_get_cur_time(struct tone_player *player)
{
os_mutex_pend(&g_tone_mutex, 0);
if (list_empty(&(g_head))) { //先判断是否为空
os_mutex_post(&g_tone_mutex);
return -1;
}
if (!player) {
player = list_first_entry(&g_head, struct tone_player, entry);
}
if (player && player->stream) {
int ret = jlstream_node_ioctl(player->stream, NODE_UUID_DECODER, NODE_IOC_GET_CUR_TIME, 0);
os_mutex_post(&g_tone_mutex);
return ret;
}
os_mutex_post(&g_tone_mutex);
return -1;
}
int tone_player_get_total_time(struct tone_player *player)
{
os_mutex_pend(&g_tone_mutex, 0);
if (list_empty(&(g_head))) { //先判断是否为空
os_mutex_post(&g_tone_mutex);
return -1;
}
if (!player) {
player = list_first_entry(&g_head, struct tone_player, entry);
}
if (player && player->stream) {
int ret = jlstream_node_ioctl(player->stream, NODE_UUID_DECODER, NODE_IOC_GET_TOTAL_TIME, 0);
os_mutex_post(&g_tone_mutex);
return ret;
}
os_mutex_post(&g_tone_mutex);
return -1;
}
static int tone_player_start(struct tone_player *player)
{
int err = -EINVAL;
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"tone");
player->stream = jlstream_pipeline_parse(uuid, NODE_UUID_TONE);
if (!player->stream) {
goto __exit0;
}
int player_id = player->player_id;
jlstream_set_callback(player->stream, (void *)player_id, tone_player_callback);
jlstream_set_scene(player->stream, player->scene);
jlstream_set_coexist(player->stream, player->coexist);
jlstream_node_ioctl(player->stream, NODE_UUID_DECODER,
NODE_IOC_SET_FILE_LEN, (int)tone_file_flen(player));
if (player->callback) {
err = player->callback(player->priv, STREAM_EVENT_INIT);
if (err) {
goto __exit1;
}
}
jlstream_set_dec_file(player->stream, player, &tone_file_ops);
err = jlstream_start(player->stream);
if (err) {
goto __exit1;
}
return 0;
__exit1:
jlstream_release(player->stream);
__exit0:
list_del(&player->entry);
tone_player_free(player);
return err;
}
int tone_player_init(struct tone_player *player, const char *file_name)
{
void *file = NULL;
int fname_uuid = 0;
player->ref = 1;
if (file_name) {
char file_path[64];
strcpy(file_path, FLASH_RES_PATH);
strcpy(file_path + strlen(FLASH_RES_PATH), file_name);
file = resfile_open(file_path);
if (!file) {
printf("tone_player_faild: %s\n", file_name);
return -EINVAL;
}
fname_uuid = JBHash((u8 *)file_name, strlen(file_name));
printf("tone_player: %s\n", file_name);
}
player->file = file;
player->scene = STREAM_SCENE_TONE;
player->player_id = g_player_id++;
player->fname_uuid = fname_uuid;
player->coexist = STREAM_COEXIST_AUTO;
INIT_LIST_HEAD(&player->entry);
return 0;
}
static struct tone_player *tone_player_create(const char *file_name)
{
struct tone_player *player;
player = zalloc(sizeof(*player));
if (!player) {
return NULL;
}
int err = tone_player_init(player, file_name);
if (err) {
tone_player_free(player);
return NULL;
}
return player;
}
int tone_player_add(struct tone_player *player)
{
os_mutex_pend(&g_tone_mutex, 0);
if (list_empty(&g_head)) {
int err = tone_player_start(player);
if (err) {
os_mutex_post(&g_tone_mutex);
return err;
}
}
list_add_tail(&player->entry, &g_head);
os_mutex_post(&g_tone_mutex);
return 0;
}
int play_tone_file(const char *file_name)
{
struct tone_player *player;
player = tone_player_create(file_name);
if (!player) {
return -ENOMEM;
}
return tone_player_add(player);
}
int play_tone_file_callback(const char *file_name, void *priv, tone_player_cb_t callback)
{
struct tone_player *player;
player = tone_player_create(file_name);
if (!player) {
if (callback) {
callback(priv, STREAM_EVENT_STOP);
}
return -ENOMEM;
}
player->priv = priv;
player->callback = callback;
return tone_player_add(player);
}
static struct tone_player *tone_files_create(const char *const file_name[], u8 file_num)
{
struct tone_player *player;
if (file_num > MAX_FILE_NUM) {
return NULL;
}
player = tone_player_create(file_name[0]);
if (!player) {
return NULL;
}
for (int i = 0; i < file_num; i++) {
player->file_name_list[i] = file_name[i];
}
return player;
}
int play_tone_files(const char *const file_name[], u8 file_num)
{
struct tone_player *player;
player = tone_files_create(file_name, file_num);
if (!player) {
return -EFAULT;
}
return tone_player_add(player);
}
int play_tone_files_alone(const char *const file_name[], u8 file_num)
{
struct tone_player *player;
player = tone_files_create(file_name, file_num);
if (!player) {
return -EFAULT;
}
player->coexist = STREAM_COEXIST_DISABLE;
return tone_player_add(player);
}
int play_tone_files_callback(const char *const file_name[], u8 file_num,
void *priv, tone_player_cb_t callback)
{
struct tone_player *player;
player = tone_files_create(file_name, file_num);
if (!player) {
if (callback) {
callback(priv, STREAM_EVENT_STOP);
}
return -EFAULT;
}
player->priv = priv;
player->callback = callback;
return tone_player_add(player);
}
int play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
void *priv, tone_player_cb_t callback)
{
struct tone_player *player;
player = tone_files_create(file_name, file_num);
if (!player) {
if (callback) {
callback(priv, STREAM_EVENT_STOP);
}
return -EFAULT;
}
player->priv = priv;
player->callback = callback;
player->coexist = STREAM_COEXIST_DISABLE;
return tone_player_add(player);
}
int play_tone_file_alone(const char *file_name)
{
struct tone_player *player;
player = tone_player_create(file_name);
if (!player) {
return -ENOMEM;
}
player->coexist = STREAM_COEXIST_DISABLE;
return tone_player_add(player);
}
int play_tone_file_alone_callback(const char *file_name, void *priv,
tone_player_cb_t callback)
{
struct tone_player *player;
player = tone_player_create(file_name);
if (!player) {
callback(priv, STREAM_EVENT_STOP);
return -ENOMEM;
}
player->coexist = STREAM_COEXIST_DISABLE;
player->priv = priv;
player->callback = callback;
return tone_player_add(player);
}
int tone_player_runing()
{
local_irq_disable();
int ret = list_empty(&g_head) ? 0 : 1;
local_irq_enable();
return ret;
}
void tone_player_stop()
{
struct tone_player *player, *n;
os_mutex_pend(&g_tone_mutex, 0);
list_for_each_entry_safe(player, n, &g_head, entry) {
__list_del_entry(&player->entry);
if (player->stream) {
jlstream_stop(player->stream, 50);
jlstream_release(player->stream);
}
tone_player_free(player);
}
os_mutex_post(&g_tone_mutex);
}
u16 tone_player_get_fname_uuid(const char *fname)
{
return JBHash((u8 *)fname, strlen(fname));
}
static int __tone_player_init()
{
os_mutex_create(&g_tone_mutex);
return 0;
}
__initcall(__tone_player_init);
@@ -0,0 +1,426 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".tws_tone_player.data.bss")
#pragma data_seg(".tws_tone_player.data")
#pragma const_seg(".tws_tone_player.text.const")
#pragma code_seg(".tws_tone_player.text")
#endif
#include "tws_tone_player.h"
#include "os/os_api.h"
#include "system/init.h"
#include "system/timer.h"
#include "fs/resfile.h"
#include "sync/audio_syncts.h"
#include "media/bt_audio_timestamp.h"
#include "reference_time.h"
#include "classic/tws_api.h"
#include "app_config.h"
#if TCFG_USER_TWS_ENABLE
#define MAX_FNAME_LEN 32
struct tws_tone_message {
enum stream_scene scene;
enum stream_coexist coexist;
u8 file_num;
u8 network;
u8 reference_clk;
u8 net_addr[6];
u32 timestamp;
u32 tws_timestamp;
u32 func_uuid;
char name[MAX_FILE_NUM][MAX_FNAME_LEN];
};
struct tws_tone_file {
enum stream_scene scene;
enum stream_coexist coexist;
u16 delay_time;
u32 func_uuid;
char name[MAX_FNAME_LEN];
};
struct tws_tone_player {
struct tone_player player;
u8 reference;
u8 network;
u8 net_addr[6];
u32 timestamp;
u32 tws_timestamp;
u32 func_uuid;
char file_list[MAX_FILE_NUM][MAX_FNAME_LEN];
};
static u8 g_tws_tone_adding = 0;
static void tws_tone_reference_clock_close(u8 id);
static void tws_play_tone_try_timeout(void *arg);
extern int ring_player_start(struct tone_player *player);
static int tws_player_callback(int fname_uuid, u32 func_uuid, enum stream_event event)
{
const struct tws_tone_callback *p;
for (p = tws_tone_cb_begin; p < tws_tone_cb_end; p++) {
if (p->func_uuid == func_uuid) {
if (p->callback) {
p->callback(fname_uuid, event);
}
break;
}
}
return 0;
}
static int tws_files_callback(void *priv, enum stream_event event)
{
return tws_player_callback(0, (u32)priv, event);
}
static void play_timestamp_init(struct tws_tone_player *player)
{
if (!player->timestamp) {
return;
}
if (!player->reference) {
player->reference = audio_reference_clock_select(player->net_addr,
player->network);
if (!player->reference) {
return;
}
}
if (!audio_reference_network_exist(player->reference) && player->network == 0) {
audio_reference_clock_exit(player->reference);
player->network = 1;
player->reference = audio_reference_clock_select(NULL, player->network);
player->timestamp = player->tws_timestamp;
}
u8 current_network = audio_reference_clock_network(NULL);
if (current_network != (u8) - 1 && player->network != current_network) {
audio_reference_clock_exit(player->reference);
player->timestamp = audio_reference_clock_remapping(player->network,
current_network, player->timestamp);
current_network = audio_reference_clock_network(player->net_addr);
player->reference = audio_reference_clock_select(current_network == 0 ?
player->net_addr : NULL, current_network);
}
if (player->timestamp && player->timestamp != (u32) - 1) {
jlstream_node_ioctl(player->player.stream, NODE_UUID_DECODER,
NODE_IOC_SET_TIME_STAMP, player->timestamp);
}
}
static int tws_tone_player_callback(void *_player, enum stream_event event)
{
int err = 0;
struct tws_tone_player *player = (struct tws_tone_player *)_player;
switch (event) {
case STREAM_EVENT_INIT:
play_timestamp_init(player);
break;
case STREAM_EVENT_START:
if (player->func_uuid) {
tws_player_callback(player->player.fname_uuid, player->func_uuid, event);
}
break;
case STREAM_EVENT_STOP:
if (player->reference) {
tws_tone_reference_clock_close(player->reference);
}
int func_uuid = player->func_uuid;
int fname_uuid = player->player.fname_uuid;
free(player);
if (func_uuid) {
tws_player_callback(fname_uuid, func_uuid, event);
}
break;
default:
break;
}
return 0;
}
static void tws_tone_player_add_timeout(void *arg)
{
struct tws_tone_player *player = (struct tws_tone_player *)arg;
int offset = 30 * 1000 / 625;
player->timestamp += offset;
player->tws_timestamp += offset;
if (!tone_player_runing()) {
tone_player_add(&player->player);
g_tws_tone_adding = 0;
} else {
sys_timeout_add((void *)player, tws_tone_player_add_timeout, 30);
}
}
static void tws_tone_play_in_task(struct tws_tone_message *msg)
{
struct tws_tone_player *player;
const char *file_name = msg->name[0];
printf("tws_tone_play: %x, %s\n", msg->timestamp, file_name);
player = zalloc(sizeof(*player));
if (!player) {
goto __exit0;
}
for (int i = 0; i < msg->file_num; i++) {
strcpy(player->file_list[i], msg->name[i]);
player->player.file_name_list[i] = player->file_list[i];
}
int err = tone_player_init(&player->player, player->file_list[0]);
if (err) {
free(player);
goto __exit0;
}
player->player.ref = 2;
player->player.priv = player;
player->player.callback = tws_tone_player_callback;
player->player.scene = msg->scene;
player->player.coexist = msg->coexist;
player->func_uuid = msg->func_uuid;
player->timestamp = msg->timestamp;
player->tws_timestamp = msg->tws_timestamp;
player->network = msg->network;
player->reference = msg->reference_clk;
memcpy(player->net_addr, msg->net_addr, 6);
if (msg->scene == STREAM_SCENE_RING) {
ring_player_start(&player->player);
} else {
if (!tone_player_runing()) {
tone_player_add(&player->player);
g_tws_tone_adding = 0;
} else {
sys_timeout_add((void *)player, tws_tone_player_add_timeout, 30);
}
}
goto __exit1;
__exit0:
g_tws_tone_adding = 0;
tws_tone_reference_clock_close(msg->reference_clk);
__exit1:
free(msg);
}
static void tws_tone_file_data_in_irq(void *data, u16 len, bool rx)
{
int msg[4];
u8 *buf = malloc(len);
if (!buf) {
goto __err;
}
memcpy(buf, data, len);
msg[0] = (int)tws_tone_play_in_task;
msg[1] = 1;
msg[2] = (int)buf;
if (rx) {
((struct tws_tone_message *)buf)->reference_clk = 0;
}
int err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg);
if (err == OS_ERR_NONE) {
return;
}
if (buf) {
free(buf);
buf = NULL;
}
if (rx) {
return;
}
__err:
g_tws_tone_adding = 0;
struct tws_tone_message *tmsg = (struct tws_tone_message *)data;
tws_tone_reference_clock_close(tmsg->reference_clk);
}
REGISTER_TWS_FUNC_STUB(tws_tone_player_stub) = {
.func_id = 0xE70A68F2,
.func = tws_tone_file_data_in_irq,
};
static void tws_tone_reference_clock_setup(struct tws_tone_message *msg)
{
msg->reference_clk = audio_reference_clock_select(NULL, 1);
msg->network = audio_reference_clock_network(msg->net_addr);
}
static void tws_tone_reference_clock_close(u8 id)
{
audio_reference_clock_exit(id);
}
static int __tws_play_tone_file(const char *const file_list[], u8 file_num,
int delay_msec, enum stream_scene scene,
enum stream_coexist coexist,
u32 func_uuid)
{
struct tws_tone_message msg;
if (tws_api_is_sniff_state()) {
tws_api_tx_unsniff_req();
delay_msec += 1000;
}
if (scene == STREAM_SCENE_TONE &&
(tone_player_runing() || g_tws_tone_adding)) {
struct tws_tone_file *file = zalloc(sizeof(*file));
if (file) {
strcpy(file->name, file_list[0]);
file->delay_time = delay_msec;
file->scene = scene;
file->coexist = coexist;
file->func_uuid = func_uuid;
sys_timeout_add((void *)file, tws_play_tone_try_timeout, 200);
}
return 0;
}
int slot = (delay_msec + 1) * 1000 / 625;
tws_tone_reference_clock_setup(&msg);
msg.timestamp = audio_reference_clock_time() + slot;
msg.tws_timestamp = audio_reference_network_clock_time(1) + slot;
msg.scene = scene;
msg.coexist = coexist;
msg.func_uuid = func_uuid;
msg.file_num = file_num;
for (int i = 0; i < file_num; i++) {
strcpy(msg.name[i], file_list[i]);
}
int data_len = offsetof(struct tws_tone_message, name) + file_num * MAX_FNAME_LEN;
printf("tws_play_tone_file: %x, %s, %d\n", msg.network, file_list[0], data_len);
int err = tws_api_send_data_to_sibling(&msg, data_len, 0xE70A68F2);
if (scene == STREAM_SCENE_TONE) {
g_tws_tone_adding = err == 0 ? 1 : 0;
}
if (err) {
tws_tone_reference_clock_close(msg.reference_clk);
if (scene == STREAM_SCENE_RING) {
err = play_ring_file(file_list[0]);
} else {
if (coexist == STREAM_COEXIST_AUTO) {
err = play_tone_files_callback(file_list, file_num, (void *)func_uuid,
tws_files_callback);
} else {
if (file_num == 1) {
err = play_tone_file_alone_callback(file_list[0], (void *)func_uuid,
tws_files_callback);
} else {
err = play_tone_files_callback(file_list, file_num, (void *)func_uuid,
tws_files_callback);
}
}
}
}
return err;
}
static void tws_play_tone_try_timeout(void *arg)
{
struct tws_tone_file *file = (struct tws_tone_file *)arg;
if (file) {
const char *fname = file->name;
__tws_play_tone_file(&fname, 1, file->delay_time,
file->scene, file->coexist, file->func_uuid);
free(file);
}
}
int tws_play_tone_file(const char *file_name, int delay_msec)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
STREAM_COEXIST_AUTO, 0);
}
int tws_play_tone_file_callback(const char *file_name, int delay_msec, u32 func_uuid)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
STREAM_COEXIST_AUTO, func_uuid);
}
int tws_play_ring_file(const char *file_name, int delay_msec)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
STREAM_COEXIST_AUTO, 0);
}
int tws_play_ring_file_alone(const char *file_name, int delay_msec)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
STREAM_COEXIST_DISABLE, 0);
}
int tws_play_ring_file_callback(const char *file_name, int delay_msec, u32 func_uuid)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
STREAM_COEXIST_AUTO, func_uuid);
}
int tws_play_ring_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_RING,
STREAM_COEXIST_DISABLE, func_uuid);
}
int tws_play_tone_files_callback(const char *const file_name[], u8 file_num,
int delay_msec, u32 func_uuid)
{
return __tws_play_tone_file(file_name, file_num, delay_msec, STREAM_SCENE_TONE,
STREAM_COEXIST_AUTO, func_uuid);
}
int tws_play_tone_files_alone_callback(const char *const file_name[], u8 file_num,
int delay_msec, u32 func_uuid)
{
return __tws_play_tone_file(file_name, file_num, delay_msec, STREAM_SCENE_TONE,
STREAM_COEXIST_DISABLE, func_uuid);
}
int tws_play_tone_file_alone(const char *file_name, int delay_msec)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
STREAM_COEXIST_DISABLE, 0);
}
int tws_play_tone_file_alone_callback(const char *file_name, int delay_msec, u32 func_uuid)
{
return __tws_play_tone_file(&file_name, 1, delay_msec, STREAM_SCENE_TONE,
STREAM_COEXIST_DISABLE, func_uuid);
}
static int tws_tone_player_init()
{
return 0;
}
__initcall(tws_tone_player_init);
#endif
@@ -0,0 +1,196 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".ai_voice_recoder.data.bss")
#pragma data_seg(".ai_voice_recoder.data")
#pragma const_seg(".ai_voice_recoder.text.const")
#pragma code_seg(".ai_voice_recoder.text")
#endif
#include "jlstream.h"
#include "system/includes.h"
#include "ai_voice_recoder.h"
#include "encoder_node.h"
#include "asm/dac.h"
#include "audio_cvp.h"
#if TCFG_AI_VOICE_ENABLE
struct ai_voice_recoder {
struct jlstream *stream;
};
extern struct audio_dac_hdl dac_hdl;
static struct ai_voice_recoder *g_ai_voice_recoder = NULL;
static void ai_voice_recoder_callback(void *private_data, int event)
{
struct ai_voice_recoder *recoder = g_ai_voice_recoder;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
break;
}
}
void ai_voice_recoder_set_ai_tx_node_func(int (*func)(u8 *, u32))
{
struct ai_voice_recoder *recoder = g_ai_voice_recoder;
if (recoder && recoder->stream) {
jlstream_node_ioctl(recoder->stream, NODE_UUID_AI_TX, NODE_IOC_SET_PRIV_FMT, (int)func);
}
}
int ai_voice_recoder_open(u32 code_type, u8 ai_type)
{
int err;
struct stream_fmt fmt;
struct encoder_fmt enc_fmt;
struct ai_voice_recoder *recoder;
u16 source_uuid = 0;
if (g_ai_voice_recoder) {
return -EBUSY;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"ai_voice");
if (uuid == 0) {
return -EFAULT;
}
recoder = malloc(sizeof(*recoder));
if (!recoder) {
return -ENOMEM;
}
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
if (!recoder->stream) {
err = -ENOMEM;
goto __exit0;
}
switch (code_type) {
case AUDIO_CODING_OPUS:
// bitrate
// 16000,32000,64000 这三个码率分别对应非ogg解码库
// 的 OPUS_SRINDEX 值为0,1,2
// format
// 0:百度_无头.
// 1:酷狗_eng+range.
// 2:ogg封装,pc软件可播放.
// 3:size+rangeFinal. 源码可兼容版本.
// complexity
// 0|1|2|3 3质量最好.速度要求最高.
// frame_ms (由frame_dms / 10得出)
// 20|40|60|80|100 ms.
// sample_rate
// sample_rate=16k ignore
//
// 注意
// 1. struct encoder_fmt是配置编码器私有参数
// 有效的参数:
// complexity, format, frame_dms
// 不起效的参数:
// bit_rate, sample_rate, ch_num, bit_width
// 不起效参数只用作阅读,需要修改请到音频流程图的”编码器“节点修改
enc_fmt.bit_rate = 16000;
enc_fmt.complexity = 0;
enc_fmt.sample_rate = 16000;
/* enc_fmt.format = (ai_type >> 6); //传入的ai_type实参是bit7:6,用于选择封装格式,兼容以前调用的接口 */
enc_fmt.format = (ai_type); //传入的ai_type实参是bit7:6,用于选择封装格式,兼容以前调用的接口
printf("[msg]%s-%d>>>>>>>>>>>enc_fmt.format=%d", __FUNCTION__, __LINE__, enc_fmt.format);
enc_fmt.frame_dms = 20 * 10;//与工具保持一致,要乘以10,表示20ms
fmt.coding_type = AUDIO_CODING_OPUS;
fmt.sample_rate = 16000;
fmt.bit_rate = 16000;
fmt.channel_mode = AUDIO_CH_MIX;
break;
case AUDIO_CODING_SPEEX:
enc_fmt.quality = 5;
enc_fmt.complexity = 2;
enc_fmt.sample_rate = 16000;
fmt.sample_rate = 16000;
fmt.coding_type = AUDIO_CODING_SPEEX;
break;
case AUDIO_CODING_PCM:
fmt.sample_rate = 16000;
fmt.coding_type = AUDIO_CODING_PCM;
break;
default:
printf("do not support this type !!!\n");
err = -ENOMEM;
goto __exit1;
break;
}
printf("coding_type %x", code_type);
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_PRIV_FMT, (int)(&enc_fmt));
err += jlstream_node_ioctl(recoder->stream, NODE_UUID_AI_TX, NODE_IOC_SET_FMT, (int)(&fmt));
//设置ADC的中断点数
if (code_type == AUDIO_CODING_PCM) {
err += jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 80);
} else {
err += jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 320);
}
if (err) {
goto __exit1;
}
u16 node_uuid = get_cvp_node_uuid();
u32 ref_sr = audio_dac_get_sample_rate(&dac_hdl);
if (node_uuid) {
#if !(TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE))
#if (TCFG_ESCO_DL_CVSD_SR_USE_16K > 1)
jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
#endif
#endif
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_PRIV_FMT, source_uuid);
if (err && (err != -ENOENT)) { //兼容没有cvp节点的情况
goto __exit1;
}
jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256);
}
jlstream_set_callback(recoder->stream, recoder->stream, ai_voice_recoder_callback);
jlstream_set_scene(recoder->stream, STREAM_SCENE_AI_VOICE);
err = jlstream_start(recoder->stream);
if (err) {
goto __exit1;
}
printf("ai voice recoder open succ\n");
g_ai_voice_recoder = recoder;
return 0;
__exit1:
jlstream_release(recoder->stream);
__exit0:
free(recoder);
return err;
}
void ai_voice_recoder_close()
{
struct ai_voice_recoder *recoder = g_ai_voice_recoder;
if (!recoder) {
return;
}
jlstream_stop(recoder->stream, 0);
jlstream_release(recoder->stream);
free(recoder);
g_ai_voice_recoder = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"ai_voice");
}
static u8 ai_voice_record_idle_query(void)
{
return g_ai_voice_recoder ? 0 : 1;
}
REGISTER_LP_TARGET(ai_voice_record_lp_target) = {
.name = "ai_voice",
.is_idle = ai_voice_record_idle_query,
};
#endif
@@ -0,0 +1,109 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".dev_flow_recoder.data.bss")
#pragma data_seg(".dev_flow_recoder.data")
#pragma const_seg(".dev_flow_recoder.text.const")
#pragma code_seg(".dev_flow_recoder.text")
#endif
#include "jlstream.h"
#include "dev_flow_recoder.h"
struct dev_flow_recoder {
struct jlstream *stream;
};
static struct dev_flow_recoder *g_dev_flow_recoder = NULL;
static void dev_flow_recoder_callback(void *private_data, int event)
{
struct dev_flow_recoder *recoder = g_dev_flow_recoder;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
break;
}
}
//自定义数据流recoder 启动
int dev_flow_recoder_open(void)
{
int err = 0;
struct dev_flow_recoder *recoder;
if (g_dev_flow_recoder) {
return -EBUSY;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"dev_flow");
if (uuid == 0) {
return -EFAULT;
}
recoder = malloc(sizeof(*recoder));
if (!recoder) {
return -ENOMEM;
}
/*
导入自定义音频流的源节点UUID,如下ADC节点为NODE_UUID_ADC,
若是其他源节点,需使用对应节点的UUID
*/
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
if (!recoder->stream) {
err = -ENOMEM;
goto __exit0;
}
/*-----以下用于设置当前数据对应节点的特性-----*/
//设置当前数据流-自定义输出节点的参数
/* struct stream_fmt fmt = {0}; */
/* err = jlstream_node_ioctl(recoder->stream, NODE_UUID_SINK_DEV, NODE_IOC_SET_FMT, (int)(&fmt)); */
//设置当前数据流-ADC的中断点数
/* err += jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256); */
if (err) {
goto __exit1;
}
jlstream_set_callback(recoder->stream, recoder->stream, dev_flow_recoder_callback);
jlstream_set_scene(recoder->stream, STREAM_SCENE_DEV_FLOW);
err = jlstream_start(recoder->stream);
if (err) {
goto __exit1;
}
g_dev_flow_recoder = recoder;
return 0;
__exit1:
jlstream_release(recoder->stream);
__exit0:
free(recoder);
return err;
}
//自定义数据流recoder 查询是否活动
bool dev_flow_recoder_runing(void)
{
return g_dev_flow_recoder != NULL;
}
//自定义数据流recoder 关闭
void dev_flow_recoder_close(void)
{
struct dev_flow_recoder *recoder = g_dev_flow_recoder;
if (!recoder) {
return;
}
jlstream_stop(recoder->stream, 0);
jlstream_release(recoder->stream);
free(recoder);
g_dev_flow_recoder = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"dev_flow");
}
+191
View File
@@ -0,0 +1,191 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".esco_recoder.data.bss")
#pragma data_seg(".esco_recoder.data")
#pragma const_seg(".esco_recoder.text.const")
#pragma code_seg(".esco_recoder.text")
#endif
#include "jlstream.h"
#include "esco_recoder.h"
#include "encoder_node.h"
#include "media/includes.h"
#include "app_config.h"
#include "audio_cvp.h"
#include "esco_player.h"
#if TCFG_AUDIO_DUT_ENABLE
#include "audio_dut_control.h"
#endif
extern struct audio_dac_hdl dac_hdl;
struct esco_recoder {
struct jlstream *stream;
};
static struct esco_recoder *g_esco_recoder = NULL;
static void esco_recoder_callback(void *private_data, int event)
{
struct esco_recoder *recoder = g_esco_recoder;
struct jlstream *stream = (struct jlstream *)private_data;
switch (event) {
case STREAM_EVENT_START:
break;
}
}
int esco_recoder_open(u8 link_type, void *bt_addr)
{
int err;
struct encoder_fmt enc_fmt;
struct esco_recoder *recoder;
u16 source_uuid = 0;
if (g_esco_recoder) {
return -EBUSY;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"esco");
if (uuid == 0) {
return -EFAULT;
}
recoder = malloc(sizeof(*recoder));
if (!recoder) {
return -ENOMEM;
}
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
source_uuid = NODE_UUID_ADC;
if (!recoder->stream) {
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_PDM_MIC);
source_uuid = NODE_UUID_PDM_MIC;
}
if (!recoder->stream) {
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_IIS0_RX);
source_uuid = NODE_UUID_IIS0_RX;
}
if (!recoder->stream) {
err = -ENOMEM;
goto __exit0;
}
//设置ADC的中断点数
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256);
if (err) {
goto __exit1;
}
jlstream_node_ioctl(recoder->stream, NODE_UUID_ESCO_TX, NODE_IOC_SET_BTADDR, (int)bt_addr);
//设置源节点是哪个
u16 node_uuid = get_cvp_node_uuid();
u32 ref_sr = audio_dac_get_sample_rate(&dac_hdl);
if (node_uuid) {
#if !(TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE))
#if (TCFG_ESCO_DL_CVSD_SR_USE_16K > 1)
jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
#endif
#endif
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_PRIV_FMT, source_uuid);
if (err && (err != -ENOENT)) { //兼容没有cvp节点的情况
goto __exit1;
}
}
if (link_type == JL_DOGLE_ACL) { //连接方式为ACL msbc 编码需要用软件; aec 参考采样率为48000;
enc_fmt.sw_hw_option = 1; //连接方式时ACL msbc 编码需要用软件
//设置编码参数
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_PRIV_FMT, (int)(&enc_fmt));
//根据回音消除的类型,将配置传递到对应的节点
if (node_uuid) {
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
}
} else {
#if (defined CONFIG_CPU_BR35)
enc_fmt.sw_hw_option = 1; //br35 msbc 编码需要用软件
//设置编码参数
err = jlstream_node_ioctl(recoder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_PRIV_FMT, (int)(&enc_fmt));
#endif
}
if (err && (err != -ENOENT)) { //兼容没有节点的情况
goto __exit1;
}
jlstream_set_callback(recoder->stream, recoder->stream, esco_recoder_callback);
jlstream_set_scene(recoder->stream, STREAM_SCENE_ESCO);
err = jlstream_start(recoder->stream);
if (err) {
goto __exit1;
}
g_esco_recoder = recoder;
return 0;
__exit1:
jlstream_release(recoder->stream);
__exit0:
free(recoder);
return err;
}
void esco_recoder_close()
{
struct esco_recoder *recoder = g_esco_recoder;
if (!recoder) {
return;
}
jlstream_stop(recoder->stream, 0);
jlstream_release(recoder->stream);
free(recoder);
g_esco_recoder = NULL;
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"esco");
#if TCFG_AUDIO_DUT_ENABLE
//退出通话默认设置为算法模式
cvp_dut_mode_set(CVP_DUT_MODE_ALGORITHM);
#endif
}
extern bool esco_player_runing();
int esco_recoder_switch(u8 en)
{
if (!esco_player_runing()) {
printf("esco player close now, non-operational!");
return 1;
}
if (en) {
//固定LINK_SCO类型,dongle不跑switch
u8 bt_addr[6];
esco_player_get_btaddr(bt_addr);
esco_recoder_open(COMMON_SCO, bt_addr);
} else {
esco_recoder_close();
}
return 0;
}
//esco_recoder复位流程,目前提供产测使用
int esco_recoder_reset(void)
{
if (!esco_player_runing()) {
printf("esco player close now, non-operational!");
return 1;
}
u8 bt_addr[6];
//产测流程,固定LINK_SCO类型
esco_recoder_close();
esco_player_get_btaddr(bt_addr);
esco_recoder_open(COMMON_SCO, bt_addr);
return 0;
}
+242
View File
@@ -0,0 +1,242 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".file_recorder.data.bss")
#pragma data_seg(".file_recorder.data")
#pragma const_seg(".file_recorder.text.const")
#pragma code_seg(".file_recorder.text")
#endif
#include "file_recorder.h"
#include "media/includes.h"
#include "app_config.h"
#if TCFG_APP_RECORD_EN || TCFG_MIX_RECORD_ENABLE
static struct list_head g_recorder_head = LIST_HEAD_INIT(g_recorder_head);
static void file_recorder_callback(void *private_data, int event)
{
struct file_recorder *recorder, *n;
printf("file_recorder_callback: %x \n", event);
list_for_each_entry_safe(recorder, n, &g_recorder_head, entry) {
if (recorder->stream->id == (int)private_data) {
if (recorder->callback) {
recorder->callback(recorder->priv, event);
}
break;
}
}
}
struct file_recorder *file_recorder_open(int pipeline_uuid, int snode_uuid)
{
struct file_recorder *recorder;
struct jlstream *stream;
recorder = zalloc(sizeof(*recorder));
if (!recorder) {
return NULL;
}
stream = jlstream_pipeline_parse(pipeline_uuid, snode_uuid);
if (!stream) {
free(recorder);
return NULL;
}
recorder->stream = stream;
jlstream_node_ioctl(stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, 256);
jlstream_set_scene(stream, STREAM_SCENE_RECODER);
jlstream_add_thread(stream, NULL);
int id = stream->id;
jlstream_set_callback(stream, (void *)id, file_recorder_callback);
list_add(&recorder->entry, &g_recorder_head);
return recorder;
}
static int recorder_fread(void *_recorder, u8 *buf, int len)
{
struct file_recorder *recorder = (struct file_recorder *)_recorder;
if (!recorder->file) {
return 0;
}
if (recorder->fops) {
return recorder->fops->read(recorder->file, buf, len);
}
return fread(buf, len, 1, (FILE *)recorder->file);
}
static int recorder_fseek(void *_recorder, int offset, int from)
{
struct file_recorder *recorder = (struct file_recorder *)_recorder;
if (!recorder->file) {
return 0;
}
if (recorder->fops) {
return recorder->fops->seek(recorder->file, offset, from);
}
return fseek((FILE *)recorder->file, offset, from);
}
static int recorder_fwrite(void *_recorder, u8 *buf, int len)
{
int wlen;
struct file_recorder *recorder = (struct file_recorder *)_recorder;
if (!recorder->file) {
return 0;
}
if (recorder->fops) {
wlen = recorder->fops->write(recorder->file, buf, len);
} else {
wlen = fwrite(buf, len, 1, (FILE *)recorder->file);
}
return wlen;
}
static int recorder_fclose(void *_recorder)
{
struct file_recorder *recorder = (struct file_recorder *)_recorder;
if (!recorder->file) {
return 0;
}
#if AUDIO_RECORD_CUT_HEAD_TAIL_EN
int f_len = ftell((FILE *)recorder->file);
if ((recorder->cut_tail_size) && ((f_len - recorder->head_size) > recorder->cut_tail_size)) {
f_len -= recorder->cut_tail_size;
fseek(recorder->file, f_len, SEEK_SET);
}
#endif
if (recorder->fops) {
if (!recorder->fops->close) {
return -EINVAL;
}
return recorder->fops->close(recorder->file);
}
return fclose((FILE *)recorder->file);
}
static const struct stream_file_ops recorder_fops = {
.read = recorder_fread,
.seek = recorder_fseek,
.write = recorder_fwrite,
};
FILE *file_recorder_open_file(struct file_recorder *recorder, const char *fname)
{
recorder->file = fopen(fname, "w+");
if (!recorder->file) {
printf("open file %s faild\n", fname);
return NULL;
}
jlstream_set_enc_file(recorder->stream, recorder, &recorder_fops);
printf("open file %s suss\n", fname);
return (FILE *)recorder->file;
}
int file_recorder_set_file(struct file_recorder *recorder, void *file,
const struct stream_file_ops *fops)
{
recorder->file = file;
recorder->fops = fops;
jlstream_set_enc_file(recorder->stream, recorder, &recorder_fops);
return 0;
}
void *file_recorder_change_file(struct file_recorder *recorder, void *new_file)
{
void *file = recorder->file;
recorder->file = new_file;
return file;
}
int file_recorder_get_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt)
{
return jlstream_ioctl(recorder->stream, NODE_IOC_GET_ENC_FMT, (int)fmt);
}
int file_recorder_set_fmt(struct file_recorder *recorder, struct stream_enc_fmt *fmt)
{
return jlstream_ioctl(recorder->stream, NODE_IOC_SET_ENC_FMT, (int)fmt);
}
void file_recorder_set_callback(struct file_recorder *recorder, void *priv,
file_recorder_cb_t callback)
{
recorder->priv = priv;
recorder->callback = callback;
}
void file_recorder_seamless_set(struct file_recorder *recorder, struct seamless_recording *seamless)
{
jlstream_node_ioctl(recorder->stream, NODE_UUID_ENCODER, NODE_IOC_SET_SEAMLESS, (int)seamless);
}
int file_recorder_start(struct file_recorder *recorder)
{
int err = jlstream_start(recorder->stream);
return err;
}
int file_recorder_stop(struct file_recorder *recorder, bool close_file)
{
int err = 0;
if (!recorder) {
return -EINVAL;
}
jlstream_stop(recorder->stream, 50);
if (close_file) {
err = recorder_fclose(recorder);
}
return err;
}
int file_recorder_release(struct file_recorder *recorder)
{
if (!recorder) {
return -EINVAL;
}
jlstream_release(recorder->stream);
list_del(&recorder->entry);
free(recorder);
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"recorder");
return 0;
}
int file_recorder_close(struct file_recorder *recorder, bool close_file)
{
int err = 0;
if (!recorder) {
return -EINVAL;
}
jlstream_stop(recorder->stream, 50);
jlstream_release(recorder->stream);
if (close_file) {
err = recorder_fclose(recorder);
}
list_del(&recorder->entry);
free(recorder);
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"recorder");
return err;
}
int file_recorder_get_enc_time(struct file_recorder *recorder)
{
int ret = 0;
if (recorder && recorder->file) {
ret = jlstream_node_ioctl(recorder->stream, NODE_UUID_ENCODER, NODE_IOC_GET_CUR_TIME, 0);
}
return ret;
}
#endif
@@ -0,0 +1,275 @@
#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".pc_mic_recoder.data.bss")
#pragma data_seg(".pc_mic_recoder.data")
#pragma const_seg(".pc_mic_recoder.text.const")
#pragma code_seg(".pc_mic_recoder.text")
#endif
#include "pc_mic_recoder.h"
#include "sdk_config.h"
#include "media/includes.h"
#include "jlstream.h"
#include "uac_stream.h"
#include "asm/dac.h"
#include "audio_config_def.h"
#include "app_config.h"
#include "app_main.h"
#include "volume_node.h"
#include "audio_cvp.h"
#include "pc_spk_player.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[pcmic]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
/* #define LOG_INFO_ENABLE */
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
extern struct audio_dac_hdl dac_hdl;
typedef enum {
PC_MIC_STA_CLOSE,
PC_MIC_STA_WAIT_CLOSE,
PC_MIC_STA_OPEN,
PC_MIC_STA_WAIT_OPEN,
} pc_mic_state_t;
pc_mic_state_t g_pc_mic_state;
struct pc_mic_recoder {
struct jlstream *stream;
};
static struct pc_mic_recoder *g_pc_mic_recoder = NULL;
static u8 pcmic_volume_wait_set_flag = 0;
static u8 pcm_mic_recoder_check = 0;
static OS_MUTEX mic_rec_mutex;
static int pcm_mic_recoder_init(void)
{
os_mutex_create(&mic_rec_mutex);
return 0;
}
__initcall(pcm_mic_recoder_init);
void pcm_mic_recoder_dump(int force_dump)
{
os_mutex_pend(&mic_rec_mutex, 0);
struct pc_mic_recoder *recoder = g_pc_mic_recoder;
if (recoder && recoder->stream) {
jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_FORCE_DUMP_PACKET, force_dump);
} else {
pcm_mic_recoder_check = force_dump;
}
os_mutex_post(&mic_rec_mutex);
}
static void pc_mic_recoder_callback(void *private_data, int event)
{
struct pc_mic_recoder *recoder = g_pc_mic_recoder;
struct jlstream *stream = (struct jlstream *)private_data;
u16 volume;
struct volume_cfg cfg;
int err;
switch (event) {
case STREAM_EVENT_START:
uac_mic_stream_get_volume(&volume);
cfg.bypass = VOLUME_NODE_CMD_SET_VOL;
cfg.cur_vol = volume;
err = jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, "Vol_PcMic", (void *)&cfg, sizeof(struct volume_cfg));
log_info(">>> pc mic vol: %d, ret:%d", volume, err);
#if TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE)
/*打开pc mic,没有开skp,忽略外部参考数据*/
printf("STREAM_EVENT_START");
if (!pc_spk_player_runing()) {
printf("CVP_OUTWAY_REF_IGNORE, 1");
audio_cvp_ioctl(CVP_OUTWAY_REF_IGNORE, 1, NULL);
}
#endif
break;
}
}
int pc_mic_recoder_open(void)
{
os_mutex_pend(&mic_rec_mutex, 0);
struct pc_mic_recoder *recoder = NULL;
u16 source_uuid;
if (g_pc_mic_recoder) {
log_error("## %s, pc mic recoder is busy!\n", __func__);
os_mutex_post(&mic_rec_mutex);
return -EBUSY;
}
u16 uuid = jlstream_event_notify(STREAM_EVENT_GET_PIPELINE_UUID, (int)"pc_mic");
if (uuid == 0) {
os_mutex_post(&mic_rec_mutex);
return -EFAULT;
}
recoder = zalloc(sizeof(*recoder));
if (!recoder) {
os_mutex_post(&mic_rec_mutex);
return -ENOMEM;
}
recoder->stream = jlstream_pipeline_parse(uuid, NODE_UUID_ADC);
source_uuid = NODE_UUID_ADC;
if (!recoder->stream) {
goto __exit0;
}
//设置ADC的中断点数
int err = jlstream_node_ioctl(recoder->stream, NODE_UUID_SOURCE, NODE_IOC_SET_PRIV_FMT, AUDIO_ADC_IRQ_POINTS);
if (err) {
goto __exit1;
}
u16 node_uuid = get_cvp_node_uuid();
//根据回音消除的类型,将配置传递到对应的节点
if (node_uuid) {
#if !(TCFG_AUDIO_CVP_OUTPUT_WAY_IIS_ENABLE && (defined TCFG_IIS_NODE_ENABLE))
u32 ref_sr = audio_dac_get_sample_rate(&dac_hdl);
jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_FMT, (int)ref_sr);
#endif
err = jlstream_node_ioctl(recoder->stream, node_uuid, NODE_IOC_SET_PRIV_FMT, source_uuid);
if (err && (err != -ENOENT)) { //兼容没有cvp节点的情况
goto __exit1;
}
}
jlstream_set_callback(recoder->stream, recoder->stream, pc_mic_recoder_callback);
jlstream_set_scene(recoder->stream, STREAM_SCENE_PC_MIC);
err = jlstream_start(recoder->stream);
if (err) {
goto __exit1;
}
g_pc_mic_state = PC_MIC_STA_OPEN;
g_pc_mic_recoder = recoder;
pcm_mic_recoder_dump(pcm_mic_recoder_check);
os_mutex_post(&mic_rec_mutex);
return 0;
__exit1:
jlstream_release(recoder->stream);
__exit0:
free(recoder);
os_mutex_post(&mic_rec_mutex);
return -ENOMEM;
}
void pc_mic_recoder_close(void)
{
os_mutex_pend(&mic_rec_mutex, 0);
struct pc_mic_recoder *recoder = g_pc_mic_recoder;
if (!recoder) {
os_mutex_post(&mic_rec_mutex);
return;
}
if (recoder->stream) {
jlstream_stop(recoder->stream, 0);
jlstream_release(recoder->stream);
}
free(recoder);
g_pc_mic_recoder = NULL;
pcm_mic_recoder_check = 0;
jlstream_event_notify(STREAM_EVENT_CLOSE_RECODER, (int)"pc_mic");
os_mutex_post(&mic_rec_mutex);
g_pc_mic_state = PC_MIC_STA_CLOSE;
}
//重启pc mic
static void pc_mic_recoder_restart(void)
{
if (g_pc_mic_state == PC_MIC_STA_OPEN) {
pc_mic_recoder_close();
pc_mic_recoder_open();
}
}
bool pc_mic_recoder_runing()
{
return g_pc_mic_recoder != NULL;
}
int pc_mic_recoder_open_by_taskq(void)
{
int msg[2];
int ret = 0;
if (g_pc_mic_state == PC_MIC_STA_CLOSE ||
g_pc_mic_state == PC_MIC_STA_WAIT_CLOSE) {
g_pc_mic_state = PC_MIC_STA_WAIT_OPEN;
msg[0] = (int)pc_mic_recoder_open;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
}
return ret;
}
int pc_mic_recoder_close_by_taskq(void)
{
int msg[2];
int ret = 0;
if (g_pc_mic_state == PC_MIC_STA_OPEN ||
g_pc_mic_state == PC_MIC_STA_WAIT_OPEN) {
g_pc_mic_state = PC_MIC_STA_WAIT_CLOSE;
msg[0] = (int)pc_mic_recoder_close;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
}
return ret;
}
int pc_mic_recoder_restart_by_taskq(void)
{
int msg[2];
int ret = 0;
msg[0] = (int)pc_mic_recoder_restart;
msg[1] = 0;
ret = os_taskq_post_type("app_core", Q_CALLBACK, 2, msg);
return ret;
}
static void pc_mic_set_volume(int mic_vol)
{
pcmic_volume_wait_set_flag = 0;
if (app_get_current_mode()->name == APP_MODE_PC) {
s16 volume = (u16)mic_vol;
struct volume_cfg cfg = {0};
cfg.bypass = VOLUME_NODE_CMD_SET_VOL;
cfg.cur_vol = volume;
int err = jlstream_set_node_param(NODE_UUID_VOLUME_CTRLER, "Vol_PcMic", (void *)&cfg, sizeof(struct volume_cfg));
log_debug(">>> pc mic vol: %d, ret:%d", mic_vol, err);
}
}
int pc_mic_set_volume_by_taskq(u32 mic_vol)
{
int ret = 0;
if (pcmic_volume_wait_set_flag == 0) {
int msg[3];
msg[0] = (int)pc_mic_set_volume;
msg[1] = 1;
msg[2] = (int)mic_vol;
ret = os_taskq_post_type("app_core", Q_CALLBACK, sizeof(msg) / sizeof(int), msg);
if (ret == 0) {
pcmic_volume_wait_set_flag = 1;
}
}
return ret;
}
#endif