output_bt.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Squeezelite for esp32
  3. *
  4. * (c) Sebastien 2019
  5. * Philippe G. 2019, philippe_44@outlook.com
  6. *
  7. * This software is released under the MIT License.
  8. * https://opensource.org/licenses/MIT
  9. *
  10. */
  11. #include <assert.h>
  12. #include "driver/gpio.h"
  13. #include "squeezelite.h"
  14. #include "equalizer.h"
  15. #include "perf_trace.h"
  16. #include "platform_config.h"
  17. #include "services.h"
  18. #include "led.h"
  19. extern struct outputstate output;
  20. extern struct buffer *outputbuf;
  21. extern struct buffer *streambuf;
  22. extern u8_t *silencebuf;
  23. #define LOCK mutex_lock(outputbuf->mutex)
  24. #define UNLOCK mutex_unlock(outputbuf->mutex)
  25. #define LOCK_S mutex_lock(streambuf->mutex)
  26. #define UNLOCK_S mutex_unlock(streambuf->mutex)
  27. #define FRAME_BLOCK MAX_SILENCE_FRAMES
  28. #define STATS_REPORT_DELAY_MS 15000
  29. extern void hal_bluetooth_init(const char * options);
  30. extern void hal_bluetooth_stop(void);
  31. extern u8_t config_spdif_gpio;
  32. static log_level loglevel;
  33. static bool running = false;
  34. static uint8_t *btout;
  35. static frames_t oframes;
  36. static bool stats;
  37. static uint32_t bt_idle_since;
  38. static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags,
  39. s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr);
  40. #define DECLARE_ALL_MIN_MAX \
  41. DECLARE_MIN_MAX(req);\
  42. DECLARE_MIN_MAX(rec);\
  43. DECLARE_MIN_MAX(bt);\
  44. DECLARE_MIN_MAX(under);\
  45. DECLARE_MIN_MAX(stream_buf);\
  46. DECLARE_MIN_MAX_DURATION(lock_out_time)
  47. #define RESET_ALL_MIN_MAX \
  48. RESET_MIN_MAX(bt); \
  49. RESET_MIN_MAX(req); \
  50. RESET_MIN_MAX(rec); \
  51. RESET_MIN_MAX(under); \
  52. RESET_MIN_MAX(stream_buf); \
  53. RESET_MIN_MAX_DURATION(lock_out_time)
  54. DECLARE_ALL_MIN_MAX;
  55. /****************************************************************************************
  56. * Get inactivity callback
  57. */
  58. static uint32_t bt_idle_callback(void) {
  59. return output.state <= OUTPUT_STOPPED ? pdTICKS_TO_MS(xTaskGetTickCount()) - bt_idle_since : 0;
  60. }
  61. /****************************************************************************************
  62. * Init BT sink
  63. */
  64. void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
  65. loglevel = level;
  66. // idle counter
  67. bt_idle_since = pdTICKS_TO_MS(xTaskGetTickCount());
  68. services_sleep_setsleeper(bt_idle_callback);
  69. // even BT has a right to use led :-)
  70. led_blink(LED_GREEN, 200, 1000);
  71. running = true;
  72. output.write_cb = &_write_frames;
  73. hal_bluetooth_init(device);
  74. char *p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0);
  75. stats = p && (*p == '1' || *p == 'Y' || *p == 'y');
  76. free(p);
  77. equalizer_set_samplerate(output.current_sample_rate);
  78. }
  79. /****************************************************************************************
  80. * Close BT sink
  81. */
  82. void output_close_bt(void) {
  83. LOCK;
  84. running = false;
  85. UNLOCK;
  86. hal_bluetooth_stop();
  87. equalizer_close();
  88. }
  89. /****************************************************************************************
  90. * Data framing callback
  91. */
  92. static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t gainR, u8_t flags,
  93. s32_t cross_gain_in, s32_t cross_gain_out, ISAMPLE_T **cross_ptr) {
  94. assert(btout != NULL);
  95. if (!silence ) {
  96. if (output.fade == FADE_ACTIVE && output.fade_dir == FADE_CROSS && *cross_ptr) {
  97. _apply_cross(outputbuf, out_frames, cross_gain_in, cross_gain_out, cross_ptr);
  98. }
  99. _apply_gain(outputbuf, out_frames, gainL, gainR, flags);
  100. #if BYTES_PER_FRAME == 4
  101. memcpy(btout + oframes * BYTES_PER_FRAME, outputbuf->readp, out_frames * BYTES_PER_FRAME);
  102. #else
  103. {
  104. frames_t count = out_frames;
  105. s32_t *_iptr = (s32_t*) outputbuf->readp;
  106. s16_t *_optr = (s16_t*) (btout + oframes * BYTES_PER_FRAME);
  107. while (count--) {
  108. *_optr++ = *_iptr++ >> 16;
  109. *_optr++ = *_iptr++ >> 16;
  110. }
  111. }
  112. #endif
  113. } else {
  114. u8_t *buf = silencebuf;
  115. memcpy(btout + oframes * BYTES_PER_FRAME, buf, out_frames * BYTES_PER_FRAME);
  116. }
  117. output_visu_export(btout + oframes * BYTES_PER_FRAME, out_frames, output.current_sample_rate, silence, (gainL + gainR) / 2);
  118. oframes += out_frames;
  119. return (int)out_frames;
  120. }
  121. /****************************************************************************************
  122. * Data callback for BT stack
  123. */
  124. int32_t output_bt_data(uint8_t *data, int32_t len) {
  125. int32_t iframes = len / BYTES_PER_FRAME, start_timer = 0;
  126. if (iframes <= 0 || data == NULL || !running) {
  127. return 0;
  128. }
  129. btout = data;
  130. oframes = 0;
  131. // This is how the BTC layer calculates the number of bytes to
  132. // for us to send. (BTC_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16) - availPcmBytes
  133. SET_MIN_MAX(len,req);
  134. TIME_MEASUREMENT_START(start_timer);
  135. LOCK;
  136. SET_MIN_MAX_SIZED(_buf_used(outputbuf),bt,outputbuf->size);
  137. output.device_frames = 0;
  138. output.updated = gettime_ms();
  139. output.frames_played_dmp = output.frames_played;
  140. _output_frames(iframes);
  141. output.frames_in_process = oframes;
  142. UNLOCK;
  143. equalizer_process(data, oframes * BYTES_PER_FRAME);
  144. SET_MIN_MAX(TIME_MEASUREMENT_GET(start_timer),lock_out_time);
  145. SET_MIN_MAX((len-oframes*BYTES_PER_FRAME), rec);
  146. TIME_MEASUREMENT_START(start_timer);
  147. return oframes * BYTES_PER_FRAME;
  148. }
  149. /****************************************************************************************
  150. * Tick for BT
  151. */
  152. void output_bt_tick(void) {
  153. static time_t lastTime=0;
  154. if (!running) return;
  155. LOCK_S;
  156. SET_MIN_MAX_SIZED(_buf_used(streambuf), stream_buf, streambuf->size);
  157. UNLOCK_S;
  158. if (stats && lastTime <= gettime_ms() )
  159. {
  160. lastTime = gettime_ms() + STATS_REPORT_DELAY_MS;
  161. LOG_INFO("Statistics over %u secs. " , STATS_REPORT_DELAY_MS/1000);
  162. LOG_INFO(" +==========+==========+================+=====+================+");
  163. LOG_INFO(" | max | min | average | avg | count |");
  164. LOG_INFO(" | (bytes) | (bytes) | (bytes) | pct | |");
  165. LOG_INFO(" +==========+==========+================+=====+================+");
  166. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("stream avl",stream_buf));
  167. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("output avl",bt));
  168. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("requested",req));
  169. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("received",rec));
  170. LOG_INFO(LINE_MIN_MAX_FORMAT,LINE_MIN_MAX("underrun",under));
  171. LOG_INFO( " +==========+==========+================+=====+================+");
  172. LOG_INFO("\n");
  173. LOG_INFO(" ==========+==========+===========+===========+ ");
  174. LOG_INFO(" max (us) | min (us) | avg(us) | count | ");
  175. LOG_INFO(" ==========+==========+===========+===========+ ");
  176. LOG_INFO(LINE_MIN_MAX_DURATION_FORMAT,LINE_MIN_MAX_DURATION("Out Buf Lock",lock_out_time));
  177. LOG_INFO(" ==========+==========+===========+===========+");
  178. RESET_ALL_MIN_MAX;
  179. }
  180. }
  181. /****************************************************************************************
  182. * BT playback stop
  183. */
  184. void output_bt_stop(void) {
  185. led_blink(LED_GREEN, 200, 1000);
  186. bt_idle_since = pdTICKS_TO_MS(xTaskGetTickCount());
  187. }
  188. /****************************************************************************************
  189. * BT playback start
  190. */
  191. void output_bt_start(void) {
  192. led_on(LED_GREEN);
  193. bt_idle_since = pdTICKS_TO_MS(xTaskGetTickCount());
  194. }