bt_app_core.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Unlicense OR CC0-1.0
  5. */
  6. #include <stdint.h>
  7. #include <string.h>
  8. #include <stdbool.h>
  9. #include "freertos/FreeRTOSConfig.h"
  10. #include "freertos/FreeRTOS.h"
  11. #include "freertos/queue.h"
  12. #include "freertos/semphr.h"
  13. #include "freertos/task.h"
  14. #include "esp_log.h"
  15. #include "bt_app_core.h"
  16. #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
  17. #include "driver/dac_continuous.h"
  18. #else
  19. #include "driver/i2s_std.h"
  20. #endif
  21. #include "freertos/ringbuf.h"
  22. #define RINGBUF_HIGHEST_WATER_LEVEL (32 * 1024)
  23. #define RINGBUF_PREFETCH_WATER_LEVEL (20 * 1024)
  24. enum {
  25. RINGBUFFER_MODE_PROCESSING, /* ringbuffer is buffering incoming audio data, I2S is working */
  26. RINGBUFFER_MODE_PREFETCHING, /* ringbuffer is buffering incoming audio data, I2S is waiting */
  27. RINGBUFFER_MODE_DROPPING /* ringbuffer is not buffering (dropping) incoming audio data, I2S is working */
  28. };
  29. extern uint8_t s_volume = 0;
  30. /*******************************
  31. * STATIC FUNCTION DECLARATIONS
  32. ******************************/
  33. /* handler for application task */
  34. static void bt_app_task_handler(void *arg);
  35. /* handler for I2S task */
  36. static void bt_i2s_task_handler(void *arg);
  37. /* message sender */
  38. static bool bt_app_send_msg(bt_app_msg_t *msg);
  39. /* handle dispatched messages */
  40. static void bt_app_work_dispatched(bt_app_msg_t *msg);
  41. /*******************************
  42. * STATIC VARIABLE DEFINITIONS
  43. ******************************/
  44. static QueueHandle_t s_bt_app_task_queue = NULL; /* handle of work queue */
  45. static TaskHandle_t s_bt_app_task_handle = NULL; /* handle of application task */
  46. static TaskHandle_t s_bt_i2s_task_handle = NULL; /* handle of I2S task */
  47. static RingbufHandle_t s_ringbuf_i2s = NULL; /* handle of ringbuffer for I2S */
  48. static SemaphoreHandle_t s_i2s_write_semaphore = NULL;
  49. static uint16_t ringbuffer_mode = RINGBUFFER_MODE_PROCESSING;
  50. /*********************************
  51. * EXTERNAL FUNCTION DECLARATIONS
  52. ********************************/
  53. #ifndef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
  54. extern i2s_chan_handle_t tx_chan;
  55. #else
  56. extern dac_continuous_handle_t tx_chan;
  57. #endif
  58. /*******************************
  59. * STATIC FUNCTION DEFINITIONS
  60. ******************************/
  61. static bool bt_app_send_msg(bt_app_msg_t *msg)
  62. {
  63. if (msg == NULL) {
  64. return false;
  65. }
  66. /* send the message to work queue */
  67. if (xQueueSend(s_bt_app_task_queue, msg, 10 / portTICK_PERIOD_MS) != pdTRUE) {
  68. ESP_LOGE(BT_APP_CORE_TAG, "%s xQueue send failed", __func__);
  69. return false;
  70. }
  71. return true;
  72. }
  73. static void bt_app_work_dispatched(bt_app_msg_t *msg)
  74. {
  75. if (msg->cb) {
  76. msg->cb(msg->event, msg->param);
  77. }
  78. }
  79. static void bt_app_task_handler(void *arg)
  80. {
  81. bt_app_msg_t msg;
  82. for (;;) {
  83. /* receive message from work queue and handle it */
  84. if (pdTRUE == xQueueReceive(s_bt_app_task_queue, &msg, (TickType_t)portMAX_DELAY)) {
  85. ESP_LOGD(BT_APP_CORE_TAG, "%s, signal: 0x%x, event: 0x%x", __func__, msg.sig, msg.event);
  86. switch (msg.sig) {
  87. case BT_APP_SIG_WORK_DISPATCH:
  88. bt_app_work_dispatched(&msg);
  89. break;
  90. default:
  91. ESP_LOGW(BT_APP_CORE_TAG, "%s, unhandled signal: %d", __func__, msg.sig);
  92. break;
  93. } /* switch (msg.sig) */
  94. if (msg.param) {
  95. free(msg.param);
  96. }
  97. }
  98. }
  99. }
  100. static void bt_i2s_task_handler(void *arg)
  101. {
  102. uint8_t *data = NULL;
  103. size_t item_size = 0;
  104. /**
  105. * The total length of DMA buffer of I2S is:
  106. * `dma_frame_num * dma_desc_num * i2s_channel_num * i2s_data_bit_width / 8`.
  107. * Transmit `dma_frame_num * dma_desc_num` bytes to DMA is trade-off.
  108. */
  109. const size_t item_size_upto = 240 * 6;
  110. size_t bytes_written = 0;
  111. for (;;) {
  112. if (pdTRUE == xSemaphoreTake(s_i2s_write_semaphore, portMAX_DELAY)) {
  113. for (;;) {
  114. item_size = 0;
  115. /* receive data from ringbuffer and write it to I2S DMA transmit buffer */
  116. data = (uint8_t *)xRingbufferReceiveUpTo(s_ringbuf_i2s, &item_size, (TickType_t)pdMS_TO_TICKS(20), item_size_upto);
  117. if (item_size == 0) {
  118. ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer underflowed! mode changed: RINGBUFFER_MODE_PREFETCHING");
  119. ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING;
  120. break;
  121. }
  122. // ---------- 关键修改:应用音量增益 ----------
  123. // 假设音频格式为16位立体声(左右声道交替)
  124. int16_t *samples = (int16_t *)data;
  125. size_t num_samples = item_size / sizeof(int16_t); // 总样本数(左+右)
  126. for (int i = 0; i < num_samples; i++) {
  127. // 使用整数运算避免浮点开销
  128. int32_t scaled = (samples[i] * s_volume) >> 8; // 等价于 samples[i] * (gain/256)
  129. // 饱和处理防止溢出
  130. scaled = (scaled > 32767) ? 32767 : (scaled < -32768) ? -32768 : scaled;
  131. samples[i] = (int16_t)scaled;
  132. }
  133. // ---------- 修改结束 ----------
  134. #ifdef CONFIG_EXAMPLE_A2DP_SINK_OUTPUT_INTERNAL_DAC
  135. dac_continuous_write(tx_chan, data, item_size, &bytes_written, -1);
  136. #else
  137. i2s_channel_write(tx_chan, data, item_size, &bytes_written, portMAX_DELAY);
  138. #endif
  139. vRingbufferReturnItem(s_ringbuf_i2s, (void *)data);
  140. }
  141. }
  142. }
  143. }
  144. /********************************
  145. * EXTERNAL FUNCTION DEFINITIONS
  146. *******************************/
  147. bool bt_app_work_dispatch(bt_app_cb_t p_cback, uint16_t event, void *p_params, int param_len, bt_app_copy_cb_t p_copy_cback)
  148. {
  149. ESP_LOGD(BT_APP_CORE_TAG, "%s event: 0x%x, param len: %d", __func__, event, param_len);
  150. bt_app_msg_t msg;
  151. memset(&msg, 0, sizeof(bt_app_msg_t));
  152. msg.sig = BT_APP_SIG_WORK_DISPATCH;
  153. msg.event = event;
  154. msg.cb = p_cback;
  155. if (param_len == 0) {
  156. return bt_app_send_msg(&msg);
  157. } else if (p_params && param_len > 0) {
  158. if ((msg.param = malloc(param_len)) != NULL) {
  159. memcpy(msg.param, p_params, param_len);
  160. /* check if caller has provided a copy callback to do the deep copy */
  161. if (p_copy_cback) {
  162. p_copy_cback(msg.param, p_params, param_len);
  163. }
  164. return bt_app_send_msg(&msg);
  165. }
  166. }
  167. return false;
  168. }
  169. void bt_app_task_start_up(void)
  170. {
  171. s_bt_app_task_queue = xQueueCreate(10, sizeof(bt_app_msg_t));
  172. xTaskCreate(bt_app_task_handler, "BtAppTask", 3072, NULL, 10, &s_bt_app_task_handle);
  173. }
  174. void bt_app_task_shut_down(void)
  175. {
  176. if (s_bt_app_task_handle) {
  177. vTaskDelete(s_bt_app_task_handle);
  178. s_bt_app_task_handle = NULL;
  179. }
  180. if (s_bt_app_task_queue) {
  181. vQueueDelete(s_bt_app_task_queue);
  182. s_bt_app_task_queue = NULL;
  183. }
  184. }
  185. void bt_i2s_task_start_up(void)
  186. {
  187. ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data empty! mode changed: RINGBUFFER_MODE_PREFETCHING");
  188. ringbuffer_mode = RINGBUFFER_MODE_PREFETCHING;
  189. if ((s_i2s_write_semaphore = xSemaphoreCreateBinary()) == NULL) {
  190. ESP_LOGE(BT_APP_CORE_TAG, "%s, Semaphore create failed", __func__);
  191. return;
  192. }
  193. if ((s_ringbuf_i2s = xRingbufferCreate(RINGBUF_HIGHEST_WATER_LEVEL, RINGBUF_TYPE_BYTEBUF)) == NULL) {
  194. ESP_LOGE(BT_APP_CORE_TAG, "%s, ringbuffer create failed", __func__);
  195. return;
  196. }
  197. xTaskCreate(bt_i2s_task_handler, "BtI2STask", 2048, NULL, configMAX_PRIORITIES - 3, &s_bt_i2s_task_handle);
  198. }
  199. void bt_i2s_task_shut_down(void)
  200. {
  201. if (s_bt_i2s_task_handle) {
  202. vTaskDelete(s_bt_i2s_task_handle);
  203. s_bt_i2s_task_handle = NULL;
  204. }
  205. if (s_ringbuf_i2s) {
  206. vRingbufferDelete(s_ringbuf_i2s);
  207. s_ringbuf_i2s = NULL;
  208. }
  209. if (s_i2s_write_semaphore) {
  210. vSemaphoreDelete(s_i2s_write_semaphore);
  211. s_i2s_write_semaphore = NULL;
  212. }
  213. }
  214. size_t write_ringbuf(const uint8_t *data, size_t size)
  215. {
  216. size_t item_size = 0;
  217. BaseType_t done = pdFALSE;
  218. if (ringbuffer_mode == RINGBUFFER_MODE_DROPPING) {
  219. ESP_LOGW(BT_APP_CORE_TAG, "ringbuffer is full, drop this packet!");
  220. vRingbufferGetInfo(s_ringbuf_i2s, NULL, NULL, NULL, NULL, &item_size);
  221. if (item_size <= RINGBUF_PREFETCH_WATER_LEVEL) {
  222. ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data decreased! mode changed: RINGBUFFER_MODE_PROCESSING");
  223. ringbuffer_mode = RINGBUFFER_MODE_PROCESSING;
  224. }
  225. return 0;
  226. }
  227. done = xRingbufferSend(s_ringbuf_i2s, (void *)data, size, (TickType_t)0);
  228. if (!done) {
  229. ESP_LOGW(BT_APP_CORE_TAG, "ringbuffer overflowed, ready to decrease data! mode changed: RINGBUFFER_MODE_DROPPING");
  230. ringbuffer_mode = RINGBUFFER_MODE_DROPPING;
  231. }
  232. if (ringbuffer_mode == RINGBUFFER_MODE_PREFETCHING) {
  233. vRingbufferGetInfo(s_ringbuf_i2s, NULL, NULL, NULL, NULL, &item_size);
  234. if (item_size >= RINGBUF_PREFETCH_WATER_LEVEL) {
  235. ESP_LOGI(BT_APP_CORE_TAG, "ringbuffer data increased! mode changed: RINGBUFFER_MODE_PROCESSING");
  236. ringbuffer_mode = RINGBUFFER_MODE_PROCESSING;
  237. if (pdFALSE == xSemaphoreGive(s_i2s_write_semaphore)) {
  238. ESP_LOGE(BT_APP_CORE_TAG, "semphore give failed");
  239. }
  240. }
  241. }
  242. return done ? size : 0;
  243. }