Files
AC707N/SDK/audio/framework/plugs/source/pc_spk_file.c
T
2025-12-03 11:12:34 +08:00

378 lines
10 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".pc_spk_file.data.bss")
#pragma data_seg(".pc_spk_file.data")
#pragma const_seg(".pc_spk_file.text.const")
#pragma code_seg(".pc_spk_file.text")
#endif
#include "source_node.h"
#include "media/audio_splicing.h"
#include "audio_config.h"
#include "jlstream.h"
#include "pc_spk_file.h"
#include "app_config.h"
#include "effects/effects_adj.h"
#include "gpio_config.h"
#include "sync/audio_clk_sync.h"
#include "clock_manager/clock_manager.h"
#include "spinlock.h"
#include "circular_buf.h"
#include "pc_spk_player.h"
#include "uac_stream.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
/* #define PC_SPK_CACHE_BUF_LEN (1024 * 2) */
//足够缓存20ms的数据
#define PC_SPK_CACHE_BUF_LEN ((SPK_AUDIO_RATE/1000) * 4 * 20)
/* PC SPK 在线检测 */
#define PC_SPK_ONLINE_DET_EN 1
#define PC_SPK_ONLINE_DET_TIME 3 //50->20
#define SPK_PUSH_FRAME_NUM 5 //SPK一次push的帧数,单位:uac rx中断间隔
struct pc_spk_file_hdl {
void *source_node;
struct stream_node *node;
struct stream_snode *snode;
cbuffer_t spk_cache_cbuffer;
#if PC_SPK_ONLINE_DET_EN
u32 irq_cnt; //进中断++,用来给定时器判断是否中断没有起
u16 det_timer_id;
#endif
int sr;
u8 *cache_buf;
u8 start;
u8 data_run;
u32 timestamp;
};
static struct pc_spk_file_hdl *pc_spk = NULL;
struct pc_spk_fmt_t {
u8 init;
u8 channel;
u8 bit;
u32 sample_rate;
};
struct pc_spk_fmt_t pc_spk_fmt = {
.init = 0,
.channel = SPK_CHANNEL,
.bit = SPK_AUDIO_RES,
.sample_rate = SPK_AUDIO_RATE,
};
static DEFINE_SPINLOCK(pc_spk_lock);
void pc_spk_data_isr_cb(void *buf, u32 len)
{
struct pc_spk_file_hdl *hdl = pc_spk;
struct stream_frame *frame = NULL;
int wlen = 0;
if (!hdl) {
#if TCFG_KBOX_1T3_MODE_EN
if (pc_spk_player_runing() == 0) {
//打开播放器
pcspk_open_player_by_taskq();
}
#else
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN)
if (!get_broadcast_role()) {
if (pc_spk_player_runing() == 0) {
//打开播放器
pcspk_open_player_by_taskq();
}
} else {
pc_mode_broadcast_deal_by_taskq(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 (pc_spk_player_runing() == 0) {
//打开播放器
pcspk_open_player_by_taskq();
}
} else {
pc_mode_broadcast_deal_by_taskq(LE_AUDIO_MUSIC_START);
}
#else
if (pc_spk_player_runing() == 0) {
//打开播放器
pcspk_open_player_by_taskq();
}
#endif
#endif
return;
}
if (!hdl->start || !len) { //增加0长帧的过滤,避免引起后续节点的写异常
return;
}
struct stream_node *source_node = hdl->source_node;
if (!hdl->cache_buf) {
int cache_buf_len = len * SPK_PUSH_FRAME_NUM * 4; //4块输出buf
//申请cbuffer
hdl->cache_buf = zalloc(cache_buf_len);
if (hdl->cache_buf) {
cbuf_init(&hdl->spk_cache_cbuffer, hdl->cache_buf, cache_buf_len);
}
}
if (cbuf_get_data_len(&hdl->spk_cache_cbuffer) == 0) {
hdl->timestamp = audio_jiffies_usec();
}
#if PC_SPK_ONLINE_DET_EN
hdl->irq_cnt++;
#endif
//1ms 起一次中断,一次长度192, 中断太快,需缓存
wlen = cbuf_write(&hdl->spk_cache_cbuffer, buf, len);
if (wlen != len) {
/*putchar('W');*/
}
u32 cache_len = cbuf_get_data_len(&hdl->spk_cache_cbuffer);
if (cache_len >= len * SPK_PUSH_FRAME_NUM) {
frame = source_plug_get_output_frame(source_node, cache_len);
if (!frame) {
return;
}
frame->len = cache_len;
#if 1
frame->flags = FRAME_FLAG_TIMESTAMP_ENABLE | FRAME_FLAG_PERIOD_SAMPLE | FRAME_FLAG_UPDATE_TIMESTAMP;
frame->timestamp = hdl->timestamp * TIMESTAMP_US_DENOMINATOR;
#else
frame->flags = FRAME_FLAG_SYS_TIMESTAMP_ENABLE;
frame->timestamp = hdl->timestamp;
#endif
cbuf_read(&hdl->spk_cache_cbuffer, frame->data, frame->len);
source_plug_put_output_frame(source_node, frame);
hdl->data_run = 1;
}
}
/* 定时器检测 pcspk 在线 */
static void pcspk_det_timer_cb(void *priv)
{
struct pc_spk_file_hdl *hdl = (struct pc_spk_file_hdl *)priv;
if (hdl) {
if (hdl->start) {
if (hdl->irq_cnt) {
hdl->irq_cnt = 0;
} else {
if (hdl->data_run) {
//已经往后面推数据突然中断没有起的情况
hdl->data_run = 0;
log_debug(">>>>>>> PCSPK LOST CONNECT <<<<<<<");
#if (LEA_BIG_CTRLER_TX_EN || LEA_BIG_CTRLER_RX_EN)
if (get_broadcast_role() == 1) {
//广播(发送端)
log_debug(">>[PC] spk lost audio stream, broadcast audio need suspend!\n");
pc_mode_broadcast_deal_by_taskq(LE_AUDIO_MUSIC_STOP);
} else {
pcspk_close_player_by_taskq();
}
#elif (TCFG_LE_AUDIO_APP_CONFIG & (LE_AUDIO_AURACAST_SOURCE_EN | LE_AUDIO_AURACAST_SINK_EN))
if (get_auracast_role() == 1) {
//广播(发送端)
log_debug(">>[PC] spk lost audio stream, broadcast audio need suspend!\n");
pc_mode_broadcast_deal_by_taskq(LE_AUDIO_MUSIC_STOP);
} else {
pcspk_close_player_by_taskq();
}
#else
pcspk_close_player_by_taskq();
#endif
}
}
}
}
}
/*
* 申请 pc_spk_file 结构体内存空间
*/
static void *pc_spk_file_init(void *source_node, struct stream_node *node)
{
struct pc_spk_file_hdl *hdl = NULL;
if (pc_spk != NULL) {
hdl = pc_spk;
} else {
hdl = zalloc(sizeof(*hdl));
}
if (!hdl) {
log_error("%s, %d, alloc memory failed!\n", __func__, __LINE__);
return NULL;
}
node->type |= NODE_TYPE_IRQ;
hdl->source_node = source_node;
hdl->node = node;
pc_spk = hdl;
return hdl;
}
static int pc_spk_ioc_get_fmt(struct pc_spk_file_hdl *hdl, struct stream_fmt *fmt)
{
fmt->coding_type = AUDIO_CODING_PCM;
if (pc_spk_fmt.channel == 2) {
fmt->channel_mode = AUDIO_CH_LR;
} else {
fmt->channel_mode = AUDIO_CH_L;
}
fmt->sample_rate = pc_spk_fmt.sample_rate;
fmt->bit_wide = (pc_spk_fmt.bit == 24) ? 1 : 0;
fmt->pcm_24bit_type = (pc_spk_fmt.bit == 24) ? PCM_24BIT_DATA_3BYTE : PCM_24BIT_DATA_4BYTE;
//log_debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>> fmt->bit_wide : %d\n", fmt->bit_wide);
return 0;
}
static int pc_spk_ioc_set_fmt(struct pc_spk_file_hdl *hdl, struct stream_fmt *fmt)
{
return -EINVAL;
}
//打开pcspk 在线检测定时器
static void pcspk_open_det_timer(void)
{
#if PC_SPK_ONLINE_DET_EN
struct pc_spk_file_hdl *hdl = pc_spk;
//申请定时器
if (hdl) {
if (!hdl->det_timer_id) {
hdl->det_timer_id = usr_timer_add(hdl, pcspk_det_timer_cb, PC_SPK_ONLINE_DET_TIME, 0);
}
}
#endif
}
//关闭 pcspk 在线检测定时器
static void pcspk_close_det_timer(void)
{
#if PC_SPK_ONLINE_DET_EN
struct pc_spk_file_hdl *hdl = pc_spk;
//申请定时器
if (hdl) {
if (hdl->det_timer_id) {
usr_timer_del(hdl->det_timer_id);
hdl->det_timer_id = 0;
}
}
#endif
}
#if 1
static int pc_spk_ioctl(void *_hdl, int cmd, int arg)
{
u32 i = 0;
int ret = 0;
struct pc_spk_file_hdl *hdl = (struct pc_spk_file_hdl *)_hdl;
switch (cmd) {
case NODE_IOC_GET_FMT:
pc_spk_ioc_get_fmt(hdl, (struct stream_fmt *)arg);
break;
case NODE_IOC_SET_FMT:
ret = pc_spk_ioc_set_fmt(hdl, (struct stream_fmt *)arg);
break;
case NODE_IOC_SET_PRIV_FMT:
ret = pc_spk_ioc_set_fmt(hdl, (struct stream_fmt *)arg);
break;
case NODE_IOC_START:
if (hdl->start == 0) {
pcspk_open_det_timer();
hdl->data_run = 0;
hdl->start = 1;
}
break;
case NODE_IOC_SUSPEND:
case NODE_IOC_STOP:
if (hdl->start) {
hdl->start = 0;
}
break;
}
return ret;
}
#endif
static void pc_spk_release(void *_hdl)
{
struct pc_spk_file_hdl *hdl = (struct pc_spk_file_hdl *)_hdl;
spin_lock(&pc_spk_lock);
if (!hdl) {
hdl = pc_spk;
if (!hdl) {
spin_unlock(&pc_spk_lock);
return;
}
}
pcspk_close_det_timer();
free(hdl->cache_buf);
hdl->cache_buf = NULL;
free(hdl);
hdl = NULL;
pc_spk = NULL;
spin_unlock(&pc_spk_lock);
}
u8 is_pc_spk_file_start(void)
{
struct pc_spk_file_hdl *hdl = pc_spk;
if (!hdl) {
return 0;
}
return (hdl->start);
}
// 设置pc mic 的数据格式,传入0不设置
void pc_spk_set_fmt(u8 channel, u8 bit, u32 sample_rate)
{
log_info("----------- Call %s, bit:%d, sr:%d\n", __func__, bit, sample_rate);
pc_spk_fmt.init = 1;
if (channel != 0) {
pc_spk_fmt.channel = channel;
}
if (bit != 0) {
pc_spk_fmt.bit = bit;
}
if (sample_rate != 0) {
pc_spk_fmt.sample_rate = sample_rate;
}
}
u32 pc_spk_get_fmt_sample_rate(void)
{
return pc_spk_fmt.sample_rate;
}
REGISTER_SOURCE_NODE_PLUG(pc_spk_file_plug) = {
.uuid = NODE_UUID_PC_SPK,
.init = pc_spk_file_init,
.ioctl = pc_spk_ioctl,
.release = pc_spk_release,
};
#endif