/* * Copyright (c) 2024, sakumisu * * SPDX-License-Identifier: Apache-2.0 */ //#include "audio_server.h" #include "halAudio.h" #include "rtthread.h" #include "usb_audio.h" #include "usbd_audio.h" #include "usbd_core.h" #include "audio_v1_mic.h" #include "bf0_pm.h" #include "halAudio.h" #include "speex\speex_resampler.h" static HalBthUsbInstance theUSB = {0}; static uint8_t usb_accumulate_buffer[320]; static uint8_t downsampled_buffer[120]; static uint16_t usb_accumulated_size = 0; static struct rt_semaphore usb_audio_sem; static struct rt_mailbox Halbth_mailbox; static SpeexResamplerState* resampler_state = NULL; static bool resampler_initialized = false; static rt_uint32_t Usbmailbox_pool[32]; // 32个邮件 uint8_t read_buffer[AUDIO_OUT_PACKET]; uint8_t Write_buffer[AUDIO_IN_PACKET]; uint8_t micusb_read_buffer[AUDIO_OUT_PACKET*4]; uint8_t PlayFlag = 0; uint8_t g_rec_client = 0; static volatile bool tx_flag; static volatile bool Rx_flag; //扬声器 static uint32_t s_mic_sample_rate = AUDIO_FREQ; static struct usbd_interface intf0; static struct usbd_interface intf1; static struct usbd_interface intf2;//扬声器 audio_buffer_t ping_pong_buffers[2]; uint8_t active_buffer = 0; const uint8_t pcm_8k_16bit_mono_320bytes[320] = { // 采样点 0-19 (40字节) 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D, 0x00, 0x00, 0x5A, 0x82, 0x7F, 0xFF, 0x5A, 0x82, 0x00, 0x00, 0xA5, 0x7D, 0x80, 0x01, 0xA5, 0x7D }; #define USB_CFG_DEBUG 1 #if USB_CFG_DEBUG #define USB_DEBUG(fmt, ...) rt_kprintf("[USB_DEBUG] " fmt, ##__VA_ARGS__) #else #define USB_DEBUG(fmt, ...) do{}while(0) #endif RT_WEAK rt_err_t pm_scenario_start(pm_scenario_name_t scenario) { return 0; } #define USB_AUDIO_CONFIG_DESC_SIZ \ (unsigned long)(9 + AUDIO_AC_DESCRIPTOR_INIT_LEN(2) + \ AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC *2 + \ AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) * 2+ \ AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC * 2+ \ AUDIO_AS_DESCRIPTOR_INIT_LEN(1)* 2) #if 0 /*只适用单音频流接口*/ #define AUDIO_AC_SIZ \ (AUDIO_SIZEOF_AC_HEADER_DESC(1) + AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC + \ AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) + \ AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC) #endif #define AUDIO_AC_SIZ \ (AUDIO_SIZEOF_AC_HEADER_DESC(2) + AUDIO_SIZEOF_AC_INPUT_TERMINAL_DESC * 2 + \ AUDIO_SIZEOF_AC_FEATURE_UNIT_DESC(IN_CHANNEL_NUM, 1) * 2+ \ AUDIO_SIZEOF_AC_OUTPUT_TERMINAL_DESC * 2) static const uint8_t device_descriptor[] = { USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01), }; static const uint8_t config_descriptor_fs[] = { USB_CONFIG_DESCRIPTOR_INIT(USB_AUDIO_CONFIG_DESC_SIZ, 0x03, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER), AUDIO_AC_DESCRIPTOR_INIT(0x00, 0x03, AUDIO_AC_SIZ, 0x00, 0x01,0x02), AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x01, AUDIO_INTERM_MIC, IN_CHANNEL_NUM, INPUT_CH_ENABLE), AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_IN_FU_ID, 0x01, 0x01, INPUT_CTRL), AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x03, AUDIO_TERMINAL_STREAMING, AUDIO_IN_FU_ID), AUDIO_AC_INPUT_TERMINAL_DESCRIPTOR_INIT(0x04, AUDIO_TERMINAL_STREAMING, IN_CHANNEL_NUM, INPUT_CH_ENABLE), AUDIO_AC_FEATURE_UNIT_DESCRIPTOR_INIT(AUDIO_OUT_FU_ID, 0x04, 0x01, INPUT_CTRL), AUDIO_AC_OUTPUT_TERMINAL_DESCRIPTOR_INIT(0x06, AUDIO_OUTTERM_HEADPHONES, AUDIO_OUT_FU_ID), AUDIO_AS_DESCRIPTOR_INIT(0x01, 0x03, IN_CHANNEL_NUM, 2, 16, AUDIO_IN_EP, 0x05, AUDIO_IN_PACKET, EP_INTERVAL_FS, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)), AUDIO_AS_DESCRIPTOR_INIT(0x02, 0x04, IN_CHANNEL_NUM, 2, 16, AUDIO_OUT_EP, 0x05, AUDIO_OUT_PACKET, EP_INTERVAL_FS, AUDIO_SAMPLE_FREQ_3B(AUDIO_FREQ)), }; static const uint8_t device_quality_descriptor[] = { USB_DEVICE_QUALIFIER_DESCRIPTOR_INIT(USB_2_0, 0xEF, 0x02, 0x01, 0x01), }; static const char *string_descriptors[] = { (const char[]){0x09, 0x04}, /* Langid */ "HS52D", /* Manufacturer */ "HS52D AUDIO_Service", /* Product */ "2025092418", /* Serial Number */ }; static const uint8_t *device_descriptor_callback(uint8_t speed) { (void)speed; return device_descriptor; } static const uint8_t *config_descriptor_callback(uint8_t speed) { (void)speed; return config_descriptor_fs; } static const uint8_t *device_quality_descriptor_callback(uint8_t speed) { (void)speed; return device_quality_descriptor; } static const char *string_descriptor_callback(uint8_t speed, uint8_t index) { (void)speed; if (index >= (sizeof(string_descriptors) / sizeof(char *))) { return NULL; } return string_descriptors[index]; } const struct usb_descriptor audio_v1_descriptor = { .device_descriptor_callback = device_descriptor_callback, .config_descriptor_callback = config_descriptor_callback, .device_quality_descriptor_callback = device_quality_descriptor_callback, .string_descriptor_callback = string_descriptor_callback, }; // UAC commands for the mailbox enum uac_cmd { UAC_CMD_UNKNOWN = 0, UAC_CMD_OPEN = (1 << 0), UAC_CMD_CLOSE = (1 << 1), UAC_CMD_ADC = (1 << 2), UAC_CMD_DAC = (1 << 3) }; void debug_rtkprintf(uint8_t *buf, uint32_t size); static void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes); static void usbd_audio_speaker_callback(uint8_t busid, uint8_t ep, uint32_t nbytes); //扬声器端点传输完成回调 static struct usbd_endpoint audio_in_ep = {.ep_cb = usbd_audio_iso_callback, .ep_addr = AUDIO_IN_EP}; static struct usbd_endpoint audio_out_ep = {.ep_cb = usbd_audio_speaker_callback, .ep_addr = AUDIO_OUT_EP}; //扬声器端点设置 static struct audio_entity_info audio_entity_table[] = { {.bEntityId = AUDIO_IN_FU_ID, .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, .ep = AUDIO_IN_EP}, { .bEntityId = AUDIO_OUT_FU_ID, // 例如5 .bDescriptorSubtype = AUDIO_CONTROL_FEATURE_UNIT, .ep = AUDIO_OUT_EP // 输出端点 }, }; static void usbd_audio_mic_send_data(uint8_t busid) { // HAL_AUDIO_T *Instance = HalAudioInstance(); // uint32_t data_available; // // 检查AudioTxRingBuffer中是否有数据 // data_available = rt_ringbuffer_data_len(Instance->AudioTxRingBuffer); // if (data_available >= AUDIO_IN_PACKET) // { // rt_ringbuffer_get(Instance->AudioTxRingBuffer, Write_buffer, AUDIO_IN_PACKET); // usbd_ep_start_write(busid, AUDIO_IN_EP, Write_buffer, AUDIO_IN_PACKET); // } // else//静音 // { // rt_kprintf("In silence \n"); // memset(Write_buffer, 0, AUDIO_IN_PACKET); // usbd_ep_start_write(busid, AUDIO_IN_EP, Write_buffer, AUDIO_IN_PACKET); // } } /* extern function definition */ static void usbd_event_handler(uint8_t busid, uint8_t event) { (void)busid; switch (event) { case USBD_EVENT_RESET: USB_DEBUG("USB Reset - Bus reset detected, reinitializing endpoints\n"); break; case USBD_EVENT_CONNECTED: USB_DEBUG("USB Connected - Device connected to host\n"); break; case USBD_EVENT_DISCONNECTED: USB_DEBUG("USB Disconnected - Device removed from host\n"); break; case USBD_EVENT_RESUME: USB_DEBUG("USB Resume - Resumed from suspend state\n"); break; case USBD_EVENT_SUSPEND: USB_DEBUG("USB Suspend - Entered suspend state\n"); break; case USBD_EVENT_CONFIGURED: USB_DEBUG("USB Configured - Host has configured the device, ready for data transfer\n"); break; case USBD_EVENT_SET_REMOTE_WAKEUP: USB_DEBUG("USB Set Remote Wakeup - Host enabled remote wakeup feature\n"); break; case USBD_EVENT_CLR_REMOTE_WAKEUP: USB_DEBUG("USB Clear Remote Wakeup - Host disabled remote wakeup feature\n"); break; case USBD_EVENT_INIT: USB_DEBUG("USB Init - USB device initialized successfully\n"); break; default: USB_DEBUG("USB Unknown Event: 0x%02X - Unhandled USB event\n", event); break; } } void usbd_audio_set_volume(uint8_t busid, uint8_t ep, uint8_t ch, int volume) { (void)busid; (void)ch; if (ep == AUDIO_IN_EP) { } } int usbd_audio_get_volume(uint8_t busid, uint8_t ep, uint8_t ch) { (void)busid; (void)ch; if (ep == AUDIO_IN_EP) { return 1; } return 0; } void usbd_audio_set_mute(uint8_t busid, uint8_t ep, uint8_t ch, bool mute) { (void)busid; (void)ch; if (ep == AUDIO_IN_EP) { } } bool usbd_audio_get_mute(uint8_t busid, uint8_t ep, uint8_t ch) { (void)busid; (void)ch; if (ep == AUDIO_IN_EP) { } return false; } void usbd_audio_set_sampling_freq(uint8_t busid, uint8_t ep, uint32_t sampling_freq) { (void)busid; if (ep == AUDIO_IN_EP) { s_mic_sample_rate = sampling_freq; } } uint32_t usbd_audio_get_sampling_freq(uint8_t busid, uint8_t ep) { (void)busid; if (ep == AUDIO_IN_EP) { return s_mic_sample_rate; } return 0; } void usbd_audio_open(uint8_t busid, uint8_t intf) { (void)busid; (void)intf; theUSB.HalUsbBusId = busid; theUSB.intf = intf; if (intf == 1) { USB_DEBUG("USB Microphone Open \n"); } else if(intf == 2) { usbd_ep_start_read(theUSB.HalUsbBusId, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET); USB_DEBUG("USB Speaker Open \n"); } } void usbd_audio_close(uint8_t busid, uint8_t intf) { (void)busid; (void)intf; if (intf == 1) { USB_DEBUG("USB Microphone Close \n"); } else if(intf == 2) { USB_DEBUG("USB Speaker Close \n"); } } void usbspeak_entry(void *parameter) { rt_uint32_t cmd; int ret; HAL_AUDIO_T * Ins = HalAudioInstance(); while (1) { if (rt_sem_take(&usb_audio_sem, RT_WAITING_FOREVER) == RT_EOK) { memcpy(usb_accumulate_buffer + usb_accumulated_size, read_buffer, AUDIO_OUT_PACKET); usb_accumulated_size += AUDIO_OUT_PACKET; if (usb_accumulated_size >= 240) { ret = downsample_16k_to_8k_speex(usb_accumulate_buffer,240, downsampled_buffer); rt_kprintf("out_len : %d\n",ret); usb_accumulated_size = 0; memcpy(Ins->AudioProcessBuffer, downsampled_buffer, 120); //debug_rtkprintf(Ins->AudioProcessBuffer,120); HalAudioProcessReceived(NULL,120); } } usbd_ep_start_read(0, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET); } } // void usbspeak_entry(void *parameter) // { // HAL_AUDIO_T *Ins = HalAudioInstance(); // static uint32_t packet_count = 0; // static uint32_t process_count = 0; // while (1) // { // if (rt_sem_take(&usb_audio_sem, RT_WAITING_FOREVER) == RT_EOK) // { // packet_count++; // // 调试:偶尔打印数据包信息 // if (packet_count % 100 == 0) { // USB_DEBUG("Packet %lu: first 4 bytes: %02X %02X %02X %02X\n", // packet_count, read_buffer[0], read_buffer[1], // read_buffer[2], read_buffer[3]); // } // // 检查缓冲区边界 // if (usb_accumulated_size + AUDIO_OUT_PACKET > 320) { // USB_DEBUG("Buffer overflow! accumulated: %u\n", usb_accumulated_size); // usb_accumulated_size = 0; // 重置以防万一 // } // // 复制数据 // memcpy(usb_accumulate_buffer + usb_accumulated_size, read_buffer, AUDIO_OUT_PACKET); // usb_accumulated_size += AUDIO_OUT_PACKET; // // 处理完整的数据块 // if (usb_accumulated_size >= 240) // { // process_count++; // // 调试信息 // if (process_count % 50 == 0) { // USB_DEBUG("Processing block %lu, accumulated: %u bytes\n", // process_count, usb_accumulated_size); // } // downsample_16k_to_8k_filtered(usb_accumulate_buffer, downsampled_buffer); // // 调试降采样后的数据 // if (process_count % 50 == 0) { // int16_t* debug_pcm = (int16_t*)downsampled_buffer; // USB_DEBUG("Downsampled samples: %d, %d, %d, %d\n", // debug_pcm[0], debug_pcm[1], debug_pcm[2], debug_pcm[3]); // } // // 保留未处理的数据 // uint16_t remaining = usb_accumulated_size - 240; // if (remaining > 0) { // memmove(usb_accumulate_buffer, usb_accumulate_buffer + 240, remaining); // USB_DEBUG("Remaining data: %u bytes\n", remaining); // } // usb_accumulated_size = remaining; // memcpy(Ins->AudioProcessBuffer, downsampled_buffer, 120); // HalAudioProcessReceived(NULL, 120); // } // } // usbd_ep_start_read(0, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET); // } // } void audio_v1_init(uint8_t busid, uint32_t reg_base) { rt_err_t ret,result; ret = rt_sem_init(&usb_audio_sem, "usb_audio_sem", 0, RT_IPC_FLAG_FIFO); RT_ASSERT(ret == RT_EOK); result = rt_mb_init(&Halbth_mailbox, "bt_evt_mb", &Usbmailbox_pool[0], sizeof(Usbmailbox_pool) / sizeof(rt_uint32_t), RT_IPC_FLAG_FIFO); rt_thread_t tid = rt_thread_create("uac_task", usbspeak_entry, RT_NULL, 2048, 20, RT_THREAD_TICK_DEFAULT); if (tid != RT_NULL) { rt_thread_startup(tid); rt_kprintf("Usb_task thread started successfully.\n"); } else { rt_kprintf("Failed to create uac_task thread.\n"); return ; } usbd_desc_register(busid, &audio_v1_descriptor); usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf0, AUDIO_VERSION, audio_entity_table, 2)); usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf1, AUDIO_VERSION, audio_entity_table, 2)); usbd_add_interface(busid, usbd_audio_init_intf(busid, &intf2, AUDIO_VERSION, audio_entity_table, 2));//扬声器 usbd_add_endpoint(busid, &audio_in_ep); usbd_add_endpoint(busid, &audio_out_ep);//扬声器 usbd_initialize(busid, reg_base, usbd_event_handler); rt_kprintf("USBInit\n"); init_speex_resampler(); HalAudioInit(); } void debug_rtkprintf(uint8_t *buf, uint32_t size) { rt_kprintf("debug_rtkprintf\n"); for(uint32_t i = 0; i < size; i++) { rt_kprintf("%02X%s", buf[i], (i % 16 == 15) ? "\n" : " "); } rt_kprintf("\n"); } static bool UsbAudio_Rx_flag = false; static bool UsbAudio_Tx_flag = false; static void usbd_audio_iso_callback(uint8_t busid, uint8_t ep, uint32_t nbytes) { (void)busid; (void)ep; (void)nbytes; usbd_audio_mic_send_data(0); // 使用busid 0 } static void usbd_audio_speaker_callback(uint8_t busid, uint8_t ep,uint32_t nbytes) { static uint8_t num = 0; (void)busid; (void)ep; (void)nbytes; rt_kprintf("nbytes = %d\n",nbytes); rt_sem_release(&usb_audio_sem); } static void AudioSpeakerTest(int argc, char **argv) { usbd_ep_start_read(0, AUDIO_OUT_EP, read_buffer, AUDIO_OUT_PACKET); } MSH_CMD_EXPORT(AudioSpeakerTest, AudioSpeakerTest info) int init_speex_resampler(void) { int err = 0; if (resampler_initialized) { return 0; // 已经初始化 } resampler_state = speex_resampler_init(1, 16000, 8000, 5, &err); if (resampler_state == NULL || err != RESAMPLER_ERR_SUCCESS) { USB_DEBUG("Speex resampler init failed: %s\n", speex_resampler_strerror(err)); return -1; } speex_resampler_skip_zeros(resampler_state); resampler_initialized = true; USB_DEBUG("Speex resampler initialized: 16kHz -> 8kHz\n"); return 0; } int downsample_16k_to_8k_speex(const uint8_t* input_16k, uint32_t input_size, uint8_t* output_8k) { if (!resampler_initialized) { if (init_speex_resampler() != 0) { return -1; } } int input_samples = input_size / 2; const spx_int16_t *in = (const spx_int16_t *)input_16k; spx_int16_t *out = (spx_int16_t *)output_8k; spx_uint32_t in_len = input_samples; spx_uint32_t out_len = input_samples; int err = speex_resampler_process_int(resampler_state, 0, in, &in_len, out, &out_len); if (err != RESAMPLER_ERR_SUCCESS) { USB_DEBUG("Resampling failed: %s\n", speex_resampler_strerror(err)); return -1; } return out_len * 2; }