Files
AC707N/SDK/apps/common/device/usb/device/uac_stream.c
T
2025-12-03 11:12:34 +08:00

494 lines
13 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".usb.data.bss")
#pragma data_seg(".usb.data")
#pragma code_seg(".usb.text")
#pragma const_seg(".usb.text.const")
#pragma str_literal_override(".usb.text.const")
#endif
#include "app_config.h"
#include "system/includes.h"
#include "printf.h"
#include "usb/usb_config.h"
#include "usb/device/usb_stack.h"
#include "generic/circular_buf.h"
#include "system/event.h"
#include "usb/device/uac_audio.h"
#include "uac_stream.h"
#include "audio_config.h"
#include "pc_spk_player.h"
#include "pc_spk_file.h"
#include "pc_mic_recoder.h"
#include "app_msg.h"
#define LOG_TAG_CONST USB
#define LOG_TAG "[UAC]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
static volatile u8 speaker_stream_is_open = 0;
static volatile u8 mic_stream_is_open = 0;
struct uac_speaker_handle {
cbuffer_t cbuf;
volatile u8 need_resume;
u8 channel;
u32 samplerate;
u32 bitwidth;
u32 timestamp;
//void (*rx_handler)(int, void *, int);
};
static void (*uac_rx_handler)(int, void *, int) = NULL;
static u16 speaker_close_tid = 0;
static struct uac_speaker_handle *uac_speaker = NULL;
#if USB_MALLOC_ENABLE
#else
static struct uac_speaker_handle uac_speaker_handle SEC(.usb.data.bss.exchange);
#endif
u8 uac_audio_is_24bit_in_4byte()
{
return UAC_24BIT_IN_4BYTE;
}
void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int))
{
uac_rx_handler = rx_handler;
/* if (uac_speaker) { */
/* uac_speaker->rx_handler = rx_handler; */
/* } */
}
//这里起中断往后面推数
void uac_speaker_stream_write(const u8 *obuf, u32 len)
{
#if 0 //multiple channel test
if (uac_speaker) {
if (uac_speaker->channel == 4) {
s16 *ch0 = (s16 *)obuf;
s16 *ch1 = (s16 *)obuf;
ch1++;
for (int i = 0; i < len / 8; i++) {
ch0[i * 2] = ch0[i * 4];
ch1[i * 2] = ch0[i * 4 + 1];
}
len /= 2;
} else if (uac_speaker->channel == 6) {
s16 *ch0 = (s16 *)obuf;
s16 *ch1 = (s16 *)obuf;
ch1++;
for (int i = 0; i < len / 12; i++) {
ch0[i * 2] = ch0[i * 6];
ch1[i * 2] = ch0[i * 6 + 1];
}
len /= 3;
} else if (uac_speaker->channel == 8) {
s16 *ch0 = (s16 *)obuf;
s16 *ch1 = (s16 *)obuf;
ch1++;
for (int i = 0; i < len / 16; i++) {
ch0[i * 2] = ch0[i * 8];
ch1[i * 2] = ch0[i * 8 + 1];
}
len /= 4;
}
}
#endif
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
pc_spk_data_isr_cb((void *)obuf, len);
#endif
}
void uac_speaker_stream_get_volume(u16 *l_vol, u16 *r_vol)
{
uac_get_cur_vol(0, l_vol, r_vol);
}
u8 uac_speaker_stream_status(void)
{
return speaker_stream_is_open;
}
void uac_speaker_stream_open(u32 samplerate, u32 ch, u32 bitwidth)
{
u32 last_sr = 0;
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
last_sr = pc_spk_get_fmt_sample_rate();
#endif
if (speaker_stream_is_open) {
if (speaker_close_tid) {
sys_hi_timeout_del(speaker_close_tid);
speaker_close_tid = 0;
}
if (uac_speaker->samplerate != samplerate ||
uac_speaker->channel != ch ||
uac_speaker->bitwidth != bitwidth) {
uac_speaker->samplerate = samplerate;
uac_speaker->channel = ch;
uac_speaker->bitwidth = bitwidth;
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
pc_spk_set_fmt(ch, bitwidth, samplerate);
pcspk_restart_player_by_taskq();
#endif
}
uac_speaker->timestamp = jiffies;
return;
}
log_info("%s", __func__);
if (!uac_speaker) {
#if USB_MALLOC_ENABLE
uac_speaker = zalloc(sizeof(struct uac_speaker_handle));
if (!uac_speaker) {
return;
}
#else
uac_speaker = &uac_speaker_handle;
memset(uac_speaker, 0, sizeof(struct uac_speaker_handle));
#endif
}
//uac_speaker->rx_handler = NULL;
uac_speaker->channel = ch;
uac_speaker->samplerate = samplerate;
uac_speaker->bitwidth = bitwidth;
speaker_stream_is_open = 1;
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
log_info(">> Case : USB_AUDIO_PLAY_OPEN\n");
#if TCFG_USER_EMITTER_ENABLE
app_send_message(APP_MSG_PC_AUDIO_PLAY_OPEN, (int)((ch << 24) | samplerate));
#endif
pc_spk_set_fmt(ch, bitwidth, samplerate);
pcspk_open_player_by_taskq();
#endif
uac_speaker->timestamp = jiffies;
}
void uac_speaker_stream_close_delay(void *priv)
{
int release = (int)priv;
speaker_close_tid = 0;
if (speaker_stream_is_open == 0) {
return;
}
log_info("%s", __func__);
speaker_stream_is_open = 0;
if (uac_speaker) {
#if USB_MALLOC_ENABLE
free(uac_speaker);
#endif
uac_speaker = NULL;
}
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
log_info(">> Case : USB_AUDIO_PLAY_CLOSE\n");
if (release) {
pc_spk_player_close();
} else {
pcspk_close_player_by_taskq();
}
#if TCFG_USER_EMITTER_ENABLE
app_send_message(APP_MSG_PC_AUDIO_PLAY_CLOSE, 0);
#endif
#endif
}
void uac_speaker_stream_close(int release)
{
if (speaker_stream_is_open == 0) {
return;
}
if (uac_speaker) {
if (jiffies_to_msecs(jiffies - uac_speaker->timestamp) > 150 || release) {
if (speaker_close_tid) {
sys_hi_timeout_del(speaker_close_tid);
speaker_close_tid = 0;
}
uac_speaker_stream_close_delay((void *)release);
} else {
if (speaker_close_tid == 0) {
speaker_close_tid = sys_hi_timeout_add(NULL, uac_speaker_stream_close_delay, 150);
} else {
sys_hi_timeout_modify(speaker_close_tid, 150);
}
}
}
}
int uac_get_spk_vol()
{
int max_vol = app_audio_volume_max_query(AppVol_USB);
int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);
if (vol * 100 / max_vol < 100) {
return vol * 100 / max_vol;
} else {
return 99;
}
return 0;
}
void uac_mute_volume(u32 type, u32 l_vol, u32 r_vol)
{
static u32 last_spk_l_vol = (u32) - 1, last_spk_r_vol = (u32) - 1;
static u32 last_mic_vol = (u32) - 1;
switch (type) {
case MIC_FEATURE_UNIT_ID: //MIC
if (mic_stream_is_open == 0) {
return ;
}
if (l_vol == last_mic_vol) {
return;
}
last_mic_vol = l_vol;
pc_mic_set_volume_by_taskq(l_vol);
break;
case SPK_FEATURE_UNIT_ID: //SPK
if (speaker_stream_is_open == 0) {
return;
}
if (l_vol == last_spk_l_vol && r_vol == last_spk_r_vol) {
return;
}
last_spk_l_vol = l_vol;
last_spk_r_vol = r_vol;
//TODO
#if TCFG_USB_SLAVE_AUDIO_SPK_ENABLE
printf(">> PC, r_vol:%d, l_vol:%d\n", r_vol, l_vol);
/* app_audio_set_volume(APP_AUDIO_STATE_MUSIC, (r_vol + l_vol) / 2, 1); */
pcspk_set_volume_by_taskq();
#endif
break;
default:
break;
}
}
static int (*mic_tx_handler)(void *, void *, int) = NULL;
static void *mic_tx_handler_priv = NULL;
static u32 mic_close_tid = 0;
static u32 mic_samplerate;
static u32 mic_bitwidth;
static u8 mic_channel;
static u32 mic_timestamp;
int uac_mic_stream_read(u8 *buf, u32 len)
{
if (mic_stream_is_open == 0) {
memset(buf, 0, len);
return len;
}
#if 0//48K 1ksin
const s16 sin_48k[] ALIGNED(4) = {
0, 2139, 4240, 6270, 8192, 9974, 11585, 12998,
14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137,
14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139,
0, -2139, -4240, -6270, -8192, -9974, -11585, -12998,
-14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137,
-14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139
};
const u8 sin_16k[] ALIGNED(4) = {
0x00, 0x00, 0xFB, 0x30, 0x81, 0x5A, 0x41, 0x76,
0xFE, 0x7F, 0x41, 0x76, 0x82, 0x5A, 0xFC, 0x30,
0x00, 0x00, 0x04, 0xCF, 0x7E, 0xA5, 0xC0, 0x89,
0x01, 0x80, 0xBF, 0x89, 0x7E, 0xA5, 0x04, 0xCF,
};
s16 *sin_wav = NULL;
if (mic_samplerate == 48000) {
sin_wav = (s16 *)sin_48k;
} else if (mic_samplerate == 16000) {
sin_wav = (s16 *)sin_16k;
} else {
sin_wav = (s16 *)sin_48k;
/* ASSERT(0, "unsupport samplerate: %d", mic_samplerate); */
}
if (mic_channel == 1) {
memcpy(buf, sin_wav, len);
} else if (mic_channel == 2) {
u16 *l_ch = (u16 *)buf;
u16 *r_ch = (u16 *)buf;
r_ch++;
for (int i = 0; i < len / 4; i++) {
*l_ch = sin_wav[i];
*r_ch = sin_wav[i];
l_ch += 2;
r_ch += 2;
}
} else if (mic_channel == 4) {
u16 *ch0 = (u16 *)buf;
u16 *ch1 = (u16 *)buf;
u16 *ch2 = (u16 *)buf;
u16 *ch3 = (u16 *)buf;
ch1 += 1, ch2 += 2, ch3 += 3;
for (int i = 0; i < len / 8; i++) {
ch0[i * 4] = sin_wav[i];
ch1[i * 4] = sin_wav[i];
ch2[i * 4] = sin_wav[i];
ch3[i * 4] = sin_wav[i];
}
} else if (mic_channel == 8) {
u16 *ch0 = (u16 *)buf;
u16 *ch1 = (u16 *)buf;
u16 *ch2 = (u16 *)buf;
u16 *ch3 = (u16 *)buf;
u16 *ch4 = (u16 *)buf;
u16 *ch5 = (u16 *)buf;
u16 *ch6 = (u16 *)buf;
u16 *ch7 = (u16 *)buf;
ch1 += 1, ch2 += 2, ch3 += 3, ch4 += 4, ch5 += 5, ch6 += 6, ch7 += 7;
for (int i = 0; i < len / 16; i++) {
ch0[i * 8] = sin_wav[i];
ch1[i * 8] = sin_wav[i];
ch2[i * 8] = sin_wav[i];
ch3[i * 8] = sin_wav[i];
ch4[i * 8] = sin_wav[i];
ch5[i * 8] = sin_wav[i];
ch6[i * 8] = sin_wav[i];
ch7[i * 8] = sin_wav[i];
}
}
return len;
#else
if (mic_tx_handler) {
return mic_tx_handler(mic_tx_handler_priv, buf, len);
} else {
//putchar('N');
memset(buf, 0, len);
}
return len;
#endif
}
void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(void *, void *, int))
{
mic_tx_handler = tx_handler;
mic_tx_handler_priv = priv;
}
void uac_mic_stream_get_volume(u16 *vol)
{
*vol = uac_get_mic_vol(0);
}
u8 uac_get_mic_stream_status(void)
{
return mic_stream_is_open;
}
u32 uac_mic_stream_open(u32 samplerate, u32 ch, u32 bitwidth)
{
u32 last_sr = 0;
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
last_sr = pc_mic_get_fmt_sample_rate();
pc_mic_set_fmt(ch, bitwidth, samplerate);
#endif
if (mic_stream_is_open) {
if (mic_close_tid) {
sys_hi_timeout_del(mic_close_tid);
mic_close_tid = 0;
}
if (mic_samplerate != samplerate ||
mic_channel != ch ||
mic_bitwidth != bitwidth) {
mic_tx_handler = NULL; //添加测试
mic_samplerate = samplerate;
mic_bitwidth = bitwidth;
mic_channel = ch;
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
//重启mic recorder
pc_mic_recoder_restart_by_taskq();
#endif
}
mic_timestamp = jiffies;
return 0;
}
mic_tx_handler = NULL; //这里需要赋值为NULL
mic_samplerate = samplerate;
mic_bitwidth = bitwidth;
mic_channel = ch;
log_info("%s", __func__);
mic_stream_is_open = 1;
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
log_info("## Func:%s, Line:%d, Open Mic!!\n", __func__, __LINE__);
#if TCFG_USER_EMITTER_ENABLE
app_send_message(APP_MSG_PC_AUDIO_MIC_OPEN, (int)((ch << 24) | samplerate));
#endif
pc_mic_recoder_open_by_taskq();
#endif
mic_timestamp = jiffies;
return 0;
}
static void uac_mic_stream_close_delay(void *priv)
{
int release = (u8)priv;
mic_close_tid = 0;
log_info("%s", __func__);
mic_stream_is_open = 0;
#if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE
log_info("## Func:%s, Line:%d, Close Mic!!\n", __func__, __LINE__);
if (release) {
pc_mic_recoder_close();
} else {
pc_mic_recoder_close_by_taskq();
}
#if TCFG_USER_EMITTER_ENABLE
app_send_message(APP_MSG_PC_AUDIO_MIC_CLOSE, 0);
#endif
#endif
}
void uac_mic_stream_close(int release)
{
if (mic_stream_is_open == 0) {
return ;
}
//FIXME:
//未知原因出现频繁开关mic,导致出现audio或者蓝牙工作异常,
//收到mic关闭命令后延时150ms再发消息通知audio模块执行关闭动作
//如果在150ms之内继续收到usb下发的关闭命令,则继续推迟150ms。
if (jiffies_to_msecs(jiffies - mic_timestamp) >= 150 || release) {
if (mic_close_tid) {
sys_hi_timeout_del(mic_close_tid);
mic_close_tid = 0;
}
uac_mic_stream_close_delay((void *)release);
} else {
if (mic_close_tid == 0) {
mic_close_tid = sys_hi_timeout_add(NULL, uac_mic_stream_close_delay, 150);
} else {
sys_hi_timeout_modify(mic_close_tid, 150);
}
}
}