#ifdef SUPPORT_MS_EXTENSIONS #pragma bss_seg(".pc_mic_node.data.bss") #pragma data_seg(".pc_mic_node.data") #pragma const_seg(".pc_mic_node.text.const") #pragma code_seg(".pc_mic_node.text") #endif #include "jlstream.h" #include "media/audio_base.h" #include "sync/audio_syncts.h" #include "circular_buf.h" #include "audio_splicing.h" #include "app_config.h" #include "gpio.h" #include "audio_cvp.h" #include "media/audio_general.h" #include "pc_mic_recoder.h" #include "uac_stream.h" #include "effects/convert_data.h" #if TCFG_USB_SLAVE_AUDIO_MIC_ENABLE #define PC_MIC_BUF_SIZE (1024 * 4) #define PC_MIC_SINGLE2DUAL_BUF_LEN (1024 * 2) #define PC_MIC_3BYTE_24BIT_BUF_LEN (1024 * 3) //单转双buf的3/2倍 static u8 pc_mic_node_get_data_flag = 0; struct pc_mic_node_hdl { u8 start; u8 cache_flag; u8 iport_channel_mode; //保存输入节点的声道数 u8 iport_bit_width; //保存输入节点的位宽 u8 tmp_buf[PC_MIC_SINGLE2DUAL_BUF_LEN]; //单转双用到的数组 u8 pcm_3byte_24bit_buf[PC_MIC_3BYTE_24BIT_BUF_LEN]; //16bit转3byte_24bit的buf u32 input_rate; u32 output_rate; struct stream_node *node; struct stream_frame *frame; enum stream_scene scene; cbuffer_t pc_mic_cache_cbuffer; u8 *cache_buf; }; struct pc_mic_fmt_t { u8 init; u8 channel; u8 bit; u32 sample_rate; }; struct pc_mic_fmt_t pc_mic_fmt = { .init = 0, .channel = MIC_CHANNEL, .bit = MIC_AUDIO_RES, .sample_rate = MIC_AUDIO_RATE, }; static DEFINE_SPINLOCK(pc_mic_lock); //pc mic 驱动拿数接口 static int pc_mic_tx_handler(void *priv, void *buf, int len) { struct pc_mic_node_hdl *hdl = (struct pc_mic_node_hdl *)priv; int rlen = 0; /* spin_lock(&pc_mic_lock); */ if (hdl) { if (hdl->start == 1 && hdl->cache_flag == 1 && hdl->cache_buf) { rlen = cbuf_read(&hdl->pc_mic_cache_cbuffer, buf, len); } } /* spin_unlock(&pc_mic_lock); */ return rlen; } // 数据流节点回调,做数据缓存 __STREAM_CACHE_CODE static void pc_mic_handle_frame(struct stream_iport *iport, struct stream_note *note) { struct pc_mic_node_hdl *hdl = (struct pc_mic_node_hdl *)iport->private_data; /* struct stream_frame *frame = NULL; */ /* struct stream_node *node = iport->node; */ if (pc_mic_node_get_data_flag == 0) { pc_mic_node_get_data_flag = 1; } if (hdl->start == 0) { return; } while (1) { if (hdl->frame == NULL) { hdl->frame = jlstream_pull_frame(iport, NULL); if (!hdl->frame) { return; } hdl->frame->offset = 0; } s16 *data = (s16 *)(hdl->frame->data + hdl->frame->offset); u32 remain = hdl->frame->len - hdl->frame->offset; int wlen = 0; spin_lock(&pc_mic_lock); //声道处理 #if (MIC_CHANNEL == 1) //mic的声道是单声道 if (AUDIO_CH_NUM(hdl->iport_channel_mode) == 2) { //mic声道是单声道,输入声道是双声道,需要双转单 if (hdl->iport_bit_width) { pcm_dual_to_single_32bit(data, data, remain); } else { pcm_dual_to_single(data, data, remain); } remain /= 2; } #elif (MIC_CHANNEL == 2) //mic的声道是双声道 if (AUDIO_CH_NUM(hdl->iport_channel_mode) == 1) { //mic声道是双声道,输入声道是单声道,需要单转双 s16 *src = data; s16 *dst = (s16 *)(hdl->tmp_buf); remain = (remain > PC_MIC_SINGLE2DUAL_BUF_LEN) ? PC_MIC_SINGLE2DUAL_BUF_LEN : remain; if (hdl->iport_bit_width) { pcm_single_to_dual_32bit(dst, src, remain); } else { pcm_single_to_dual(dst, src, remain); } remain = remain * 2; data = (s16 *)(hdl->tmp_buf); } #endif //位宽处理 if (pc_mic_fmt.bit == 16) { if (hdl->iport_bit_width) { //输入位宽是4byte_24bit audio_convert_data_32bit_to_16bit_round((s32 *)data, (s16 *)data, remain / 4); remain /= 2; } } else if (pc_mic_fmt.bit == 24) { if (hdl->iport_bit_width) { //输入位宽是4byte_24bit audio_convert_data_4byte24bit_to_3byte24bit((s32 *)data, (s32 *)data, remain / 4); remain = remain * 3 / 4; } else { //输入位宽是16bit remain = (remain > PC_MIC_3BYTE_24BIT_BUF_LEN) ? PC_MIC_3BYTE_24BIT_BUF_LEN : remain; audio_convert_data_16bit_to_3byte24bit((s16 *)data, (s32 *)hdl->pcm_3byte_24bit_buf, remain / 2); remain = remain * 3 / 2; data = (s16 *)hdl->pcm_3byte_24bit_buf; } } wlen = cbuf_write(&hdl->pc_mic_cache_cbuffer, data, remain); if (wlen != remain) { putchar('w'); } if (hdl->cache_flag == 0) { if (cbuf_get_data_len(&hdl->pc_mic_cache_cbuffer) >= PC_MIC_BUF_SIZE / 2) { hdl->cache_flag = 1; } } jlstream_free_frame(hdl->frame); hdl->frame = NULL; spin_unlock(&pc_mic_lock); } } static void pc_mic_ioc_start(struct pc_mic_node_hdl *hdl) { spin_lock(&pc_mic_lock); if (hdl->start == 0) { y_printf("## Enter Func:%s, Line:%d\n", __func__, __LINE__); if (!hdl->cache_buf) { hdl->cache_buf = malloc(PC_MIC_BUF_SIZE); if (!hdl->cache_buf) { r_printf("Error, Func:%s, Line:%d\n", __func__, __LINE__); spin_unlock(&pc_mic_lock); return; } cbuf_init(&hdl->pc_mic_cache_cbuffer, hdl->cache_buf, PC_MIC_BUF_SIZE); set_uac_mic_tx_handler((void *)hdl, pc_mic_tx_handler); } hdl->cache_flag = 0; hdl->start = 1; } spin_unlock(&pc_mic_lock); } static void pc_mic_ioc_stop(struct pc_mic_node_hdl *hdl) { if (hdl->start == 1) { hdl->cache_flag = 0; hdl->start = 0; } pc_mic_node_get_data_flag = 0; } static void pc_mic_adapter_open_iport(struct stream_iport *iport) { iport->handle_frame = pc_mic_handle_frame; iport->private_data = iport->node->private_data; } static int pc_mic_ioc_negotiate(struct stream_iport *iport) { y_printf("## Enter Func : %s\n", __func__); int ret = NEGO_STA_ACCPTED; struct stream_fmt *in_fmt = &iport->prev->fmt; struct pc_mic_node_hdl *hdl = (struct pc_mic_node_hdl *)iport->private_data; u32 coding_type = in_fmt->coding_type; u8 channel_mode = in_fmt->channel_mode; int output_rate = in_fmt->sample_rate; u8 bit_width = in_fmt->bit_wide; if (hdl->scene != STREAM_SCENE_PC_MIC) { r_printf("## Error , Func:%s, Line:%d\n", __func__, __LINE__); ret = NEGO_STA_ABORT; } if (coding_type != AUDIO_CODING_PCM) { r_printf("## Error , Func:%s, Line:%d\n", __func__, __LINE__); ret = NEGO_STA_ABORT; } if (output_rate != pc_mic_get_fmt_sample_rate()) { in_fmt->sample_rate = pc_mic_get_fmt_sample_rate(); r_printf("## Error , Func:%s, Line:%d\n", __func__, __LINE__); /* ret = NEGO_STA_ABORT; */ ret = NEGO_STA_CONTINUE; } hdl->iport_channel_mode = channel_mode; hdl->output_rate = output_rate; hdl->iport_bit_width = bit_width; g_printf("## Func:%s, negotiate_state : %d, output_rate:%d, channel_mode:%d\n", __func__, ret, output_rate, channel_mode); return ret; } static int pc_mic_adapter_ioctl(struct stream_iport *iport, int cmd, int arg) { int ret = 0; struct pc_mic_node_hdl *hdl = (struct pc_mic_node_hdl *)iport->private_data; switch (cmd) { case NODE_IOC_OPEN_IPORT: pc_mic_adapter_open_iport(iport); break; case NODE_IOC_NEGOTIATE: *(int *)arg |= pc_mic_ioc_negotiate(iport); break; case NODE_IOC_SET_SCENE: hdl->scene = arg; break; case NODE_IOC_GET_DELAY: break; case NODE_IOC_START: pc_mic_ioc_start(hdl); break; case NODE_IOC_SUSPEND: case NODE_IOC_STOP: pc_mic_ioc_stop(hdl); break; case NODE_IOC_SYNCTS: break; default: break; } return ret; } static int pc_mic_adapter_bind(struct stream_node *node, u16 uuid) { spin_lock(&pc_mic_lock); struct pc_mic_node_hdl *hdl = zalloc(sizeof(*hdl)); ASSERT(hdl, "%s hdl = NULL!\n", __func__); hdl->node = node; node->private_data = hdl; spin_unlock(&pc_mic_lock); return 0; } static void pc_mic_adapter_release(struct stream_node *node) { struct pc_mic_node_hdl *hdl = (struct pc_mic_node_hdl *)node->private_data; if (hdl) { spin_lock(&pc_mic_lock); pc_mic_ioc_stop(hdl); if (hdl->cache_buf) { free(hdl->cache_buf); hdl->cache_buf = NULL; } free(hdl); hdl = NULL; spin_unlock(&pc_mic_lock); } } // 返回1代表数据流有跑起来 u8 pc_mic_get_node_state(void) { return pc_mic_node_get_data_flag; } // 设置pc mic 的数据格式,传入0不设置 void pc_mic_set_fmt(u8 channel, u8 bit, u32 sample_rate) { y_printf("----------- Call %s, bit:%d, sr:%d\n", __func__, bit, sample_rate); pc_mic_fmt.init = 1; if (channel != 0) { pc_mic_fmt.channel = channel; } if (bit != 0) { pc_mic_fmt.bit = bit; } if (sample_rate != 0) { pc_mic_fmt.sample_rate = sample_rate; } } u32 pc_mic_get_fmt_sample_rate(void) { y_printf("Mic Sr : %d\n", pc_mic_fmt.sample_rate); return pc_mic_fmt.sample_rate; } REGISTER_STREAM_NODE_ADAPTER(pc_mic_node_adapter) = { .name = "pc_mic", .uuid = NODE_UUID_PC_MIC, .bind = pc_mic_adapter_bind, .ioctl = pc_mic_adapter_ioctl, .release = pc_mic_adapter_release, }; #endif