xref: /btstack/example/sco_demo_util.c (revision 360d44f609bbebbf954ea85f461752a6b07644cd)
1 /*
2  * Copyright (C) 2016 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "sco_demo_util.c"
39 
40 /*
41  * sco_demo_util.c - send/receive test data via SCO, used by hfp_*_demo and hsp_*_demo
42  */
43 
44 #include <stdio.h>
45 
46 #include "sco_demo_util.h"
47 
48 #include "btstack_audio.h"
49 #include "btstack_debug.h"
50 #include "btstack_ring_buffer.h"
51 #include "classic/btstack_cvsd_plc.h"
52 #include "classic/btstack_sbc.h"
53 #include "classic/hfp.h"
54 #include "classic/hfp_msbc.h"
55 
56 #ifdef _MSC_VER
57 // ignore deprecated warning for fopen
58 #pragma warning(disable : 4996)
59 #endif
60 
61 #ifdef HAVE_POSIX_FILE_IO
62 #include "wav_util.h"
63 #endif
64 
65 // test modes
66 #define SCO_DEMO_MODE_SINE		 0
67 #define SCO_DEMO_MODE_MICROPHONE 1
68 #define SCO_DEMO_MODE_MODPLAYER  2
69 
70 // SCO demo configuration
71 #define SCO_DEMO_MODE               SCO_DEMO_MODE_MICROPHONE
72 
73 // number of sco packets until 'report' on console
74 #define SCO_REPORT_PERIOD           100
75 
76 
77 #ifdef HAVE_POSIX_FILE_IO
78 // length and name of wav file on disk
79 #define SCO_WAV_DURATION_IN_SECONDS 15
80 #define SCO_WAV_FILENAME            "sco_input.wav"
81 #endif
82 
83 // constants
84 #define NUM_CHANNELS            1
85 #define SAMPLE_RATE_8KHZ        8000
86 #define SAMPLE_RATE_16KHZ       16000
87 #define BYTES_PER_FRAME         2
88 
89 // pre-buffer for CVSD and mSBC - also defines latency
90 #define SCO_PREBUFFER_MS      50
91 #define PREBUFFER_BYTES_8KHZ  (SCO_PREBUFFER_MS *  SAMPLE_RATE_8KHZ/1000 * BYTES_PER_FRAME)
92 #define PREBUFFER_BYTES_16KHZ (SCO_PREBUFFER_MS * SAMPLE_RATE_16KHZ/1000 * BYTES_PER_FRAME)
93 
94 #if defined(ENABLE_HFP_WIDE_BAND_SPEECH)
95 #define PREBUFFER_BYTES_MAX PREBUFFER_BYTES_16KHZ
96 #else
97 #define PREBUFFER_BYTES_MAX PREBUFFER_BYTES_8KHZ
98 #endif
99 
100 static uint16_t              audio_prebuffer_bytes;
101 
102 // output
103 static int                   audio_output_paused  = 0;
104 static uint8_t               audio_output_ring_buffer_storage[2 * PREBUFFER_BYTES_MAX];
105 static btstack_ring_buffer_t audio_output_ring_buffer;
106 
107 // input
108 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE
109 #define USE_AUDIO_INPUT
110 #else
111 #define USE_ADUIO_GENERATOR
112 static void (*sco_demo_audio_generator)(uint16_t num_samples, int16_t * data);
113 #endif
114 static int                   audio_input_paused  = 0;
115 static uint8_t               audio_input_ring_buffer_storage[2 * PREBUFFER_BYTES_MAX];
116 static btstack_ring_buffer_t audio_input_ring_buffer;
117 
118 // mod player
119 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
120 #include "hxcmod.h"
121 #include "mods/mod.h"
122 static modcontext mod_context;
123 #endif
124 
125 static int count_sent = 0;
126 static int count_received = 0;
127 
128 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
129 #define MSBC_MAX_NUM_SAMPLES (16*8)
130 static btstack_sbc_decoder_state_t decoder_state;
131 #endif
132 
133 static btstack_cvsd_plc_state_t cvsd_plc_state;
134 
135 int num_samples_to_write;
136 int num_audio_frames;
137 
138 // generic codec support
139 typedef struct {
140     void (*init)(void);
141     void(*receive)(const uint8_t * packet, uint16_t size);
142     void (*fill_payload)(uint8_t * payload_buffer, uint16_t sco_payload_length);
143     void (*close)(void);
144     //
145     uint16_t sample_rate;
146 } codec_support_t;
147 
148 // current configuration
149 static const codec_support_t * codec_current = NULL;
150 
151 
152 // Sine Wave
153 
154 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
155 static uint16_t sine_wave_phase;
156 static uint16_t sine_wave_steps_per_sample;
157 #define SINE_WAVE_SAMPLE_RATE SAMPLE_RATE_16KHZ
158 
159 // input signal: pre-computed sine wave, 266 Hz at 16000 kHz
160 static const int16_t sine_int16_at_16000hz[] = {
161      0,   3135,   6237,   9270,  12202,  14999,  17633,  20073,  22294,  24270,
162  25980,  27406,  28531,  29344,  29835,  30000,  29835,  29344,  28531,  27406,
163  25980,  24270,  22294,  20073,  17633,  14999,  12202,   9270,   6237,   3135,
164      0,  -3135,  -6237,  -9270, -12202, -14999, -17633, -20073, -22294, -24270,
165 -25980, -27406, -28531, -29344, -29835, -30000, -29835, -29344, -28531, -27406,
166 -25980, -24270, -22294, -20073, -17633, -14999, -12202,  -9270,  -6237,  -3135,
167 };
168 
169 static void sco_demo_sine_wave_host_endian(uint16_t num_samples, int16_t * data){
170     unsigned int i;
171     for (i=0; i < num_samples; i++){
172         data[i] = sine_int16_at_16000hz[sine_wave_phase];
173         sine_wave_phase += sine_wave_steps_per_sample;
174         if (sine_wave_phase >= (sizeof(sine_int16_at_16000hz) / sizeof(int16_t))){
175             sine_wave_phase = 0;
176         }
177     }
178 }
179 #endif
180 
181 // Mod Player
182 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
183 #define NUM_SAMPLES_GENERATOR_BUFFER 30
184 static void sco_demo_modplayer(uint16_t num_samples, int16_t * data){
185     // mix down stereo
186     signed short samples[NUM_SAMPLES_GENERATOR_BUFFER * 2];
187     while (num_samples > 0){
188         uint16_t next_samples = btstack_min(num_samples, NUM_SAMPLES_GENERATOR_BUFFER);
189     	hxcmod_fillbuffer(&mod_context, (unsigned short *) samples, next_samples, NULL);
190         num_samples -= next_samples;
191         uint16_t i;
192         for (i=0;i<next_samples;i++){
193             int32_t left  = samples[2*i + 0];
194             int32_t right = samples[2*i + 1];
195             data[i] = (int16_t)((left + right) / 2);
196         }
197     }
198 }
199 #endif
200 
201 // Audio Playback / Recording
202 
203 static void audio_playback_callback(int16_t * buffer, uint16_t num_samples){
204 
205     // fill with silence while paused
206     if (audio_output_paused){
207         if (btstack_ring_buffer_bytes_available(&audio_output_ring_buffer) < audio_prebuffer_bytes){
208             memset(buffer, 0, num_samples * BYTES_PER_FRAME);
209            return;
210         } else {
211             // resume playback
212             audio_output_paused = 0;
213         }
214     }
215 
216     // get data from ringbuffer
217     uint32_t bytes_read = 0;
218     btstack_ring_buffer_read(&audio_output_ring_buffer, (uint8_t *) buffer, num_samples * BYTES_PER_FRAME, &bytes_read);
219     num_samples -= bytes_read / BYTES_PER_FRAME;
220     buffer      += bytes_read / BYTES_PER_FRAME;
221 
222     // fill with 0 if not enough
223     if (num_samples){
224         memset(buffer, 0, num_samples * BYTES_PER_FRAME);
225         audio_output_paused = 1;
226     }
227 }
228 
229 #ifdef USE_AUDIO_INPUT
230 static void audio_recording_callback(const int16_t * buffer, uint16_t num_samples){
231     btstack_ring_buffer_write(&audio_input_ring_buffer, (uint8_t *)buffer, num_samples * 2);
232 }
233 #endif
234 
235 // return 1 if ok
236 static int audio_initialize(int sample_rate){
237 
238     // -- output -- //
239 
240     // init buffers
241     memset(audio_output_ring_buffer_storage, 0, sizeof(audio_output_ring_buffer_storage));
242     btstack_ring_buffer_init(&audio_output_ring_buffer, audio_output_ring_buffer_storage, sizeof(audio_output_ring_buffer_storage));
243 
244     // config and setup audio playback
245     const btstack_audio_sink_t * audio_sink = btstack_audio_sink_get_instance();
246     if (!audio_sink) return 0;
247 
248     audio_sink->init(1, sample_rate, &audio_playback_callback);
249     audio_sink->start_stream();
250 
251     audio_output_paused  = 1;
252 
253     // -- input -- //
254 
255     // init buffers
256     memset(audio_input_ring_buffer_storage, 0, sizeof(audio_input_ring_buffer_storage));
257     btstack_ring_buffer_init(&audio_input_ring_buffer, audio_input_ring_buffer_storage, sizeof(audio_input_ring_buffer_storage));
258     audio_input_paused  = 1;
259 
260 #ifdef USE_AUDIO_INPUT
261     // config and setup audio recording
262     const btstack_audio_source_t * audio_source = btstack_audio_source_get_instance();
263     if (!audio_source) return 0;
264 
265     audio_source->init(1, sample_rate, &audio_recording_callback);
266     audio_source->start_stream();
267 #endif
268 
269     return 1;
270 }
271 
272 static void audio_terminate(void){
273     const btstack_audio_sink_t * audio_sink = btstack_audio_sink_get_instance();
274     if (!audio_sink) return;
275     audio_sink->close();
276 
277 #ifdef USE_AUDIO_INPUT
278     const btstack_audio_source_t * audio_source= btstack_audio_source_get_instance();
279     if (!audio_source) return;
280     audio_source->close();
281 #endif
282 }
283 
284 
285 // CVSD - 8 kHz
286 
287 static void sco_demo_cvsd_init(void){
288     printf("SCO Demo: Init CVSD\n");
289     btstack_cvsd_plc_init(&cvsd_plc_state);
290 }
291 
292 static void sco_demo_cvsd_receive(const uint8_t * packet, uint16_t size){
293 
294     int16_t audio_frame_out[128];    //
295 
296     if (size > sizeof(audio_frame_out)){
297         printf("sco_demo_cvsd_receive: SCO packet larger than local output buffer - dropping data.\n");
298         return;
299     }
300 
301     const int audio_bytes_read = size - 3;
302     const int num_samples = audio_bytes_read / BYTES_PER_FRAME;
303 
304     // convert into host endian
305     int16_t audio_frame_in[128];
306     int i;
307     for (i=0;i<num_samples;i++){
308         audio_frame_in[i] = little_endian_read_16(packet, 3 + i * 2);
309     }
310 
311     // treat packet as bad frame if controller does not report 'all good'
312     bool bad_frame = (packet[1] & 0x30) != 0;
313 
314     btstack_cvsd_plc_process_data(&cvsd_plc_state, bad_frame, audio_frame_in, num_samples, audio_frame_out);
315 
316 #ifdef SCO_WAV_FILENAME
317     // Samples in CVSD SCO packet are in little endian, ready for wav files (take shortcut)
318     const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
319     wav_writer_write_le_int16(samples_to_write, audio_frame_out);
320     num_samples_to_write -= samples_to_write;
321     if (num_samples_to_write == 0){
322         wav_writer_close();
323     }
324 #endif
325 
326     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read);
327 }
328 
329 static void sco_demo_cvsd_fill_payload(uint8_t * payload_buffer, uint16_t sco_payload_length){
330     uint16_t bytes_to_copy = sco_payload_length;
331 
332     // get data from ringbuffer
333     uint16_t pos = 0;
334     if (!audio_input_paused){
335         uint16_t samples_to_copy = sco_payload_length / 2;
336         uint32_t bytes_read = 0;
337         btstack_ring_buffer_read(&audio_input_ring_buffer, payload_buffer, bytes_to_copy, &bytes_read);
338         // flip 16 on big endian systems
339         // @note We don't use (uint16_t *) casts since all sample addresses are odd which causes crahses on some systems
340         if (btstack_is_big_endian()){
341             uint16_t i;
342             for (i=0;i<samples_to_copy/2;i+=2){
343                 uint8_t tmp           = payload_buffer[i*2];
344                 payload_buffer[i*2]   = payload_buffer[i*2+1];
345                 payload_buffer[i*2+1] = tmp;
346             }
347         }
348         bytes_to_copy -= bytes_read;
349         pos           += bytes_read;
350     }
351 
352     // fill with 0 if not enough
353     if (bytes_to_copy){
354         memset(payload_buffer + pos, 0, bytes_to_copy);
355         audio_input_paused = 1;
356     }
357 }
358 
359 static void sco_demo_cvsd_close(void){
360     printf("Used CVSD with PLC, number of proccesed frames: \n - %d good frames, \n - %d bad frames.\n", cvsd_plc_state.good_frames_nr, cvsd_plc_state.bad_frames_nr);
361 }
362 
363 static const codec_support_t codec_cvsd = {
364         .init         = &sco_demo_cvsd_init,
365         .receive      = &sco_demo_cvsd_receive,
366         .fill_payload = &sco_demo_cvsd_fill_payload,
367         .close        = &sco_demo_cvsd_close,
368         .sample_rate = SAMPLE_RATE_8KHZ
369 };
370 
371 // mSBC - 16 kHz
372 
373 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
374 
375 static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
376     UNUSED(context);
377     UNUSED(sample_rate);
378     UNUSED(data);
379     UNUSED(num_samples);
380     UNUSED(num_channels);
381 
382     // samples in callback in host endianess, ready for playback
383     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
384 
385 #ifdef SCO_WAV_FILENAME
386     if (!num_samples_to_write) return;
387     num_samples = btstack_min(num_samples, num_samples_to_write);
388     num_samples_to_write -= num_samples;
389     wav_writer_write_int16(num_samples, data);
390     if (num_samples_to_write == 0){
391         wav_writer_close();
392     }
393 #endif /* SCO_WAV_FILENAME */
394 }
395 
396 static void sco_demo_msbc_init(void){
397     printf("SCO Demo: Init mSBC\n");
398     btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL);
399     hfp_msbc_init();
400 }
401 
402 static void sco_demo_msbc_receive(const uint8_t * packet, uint16_t size){
403     btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3);
404 }
405 
406 void sco_demo_msbc_fill_payload(uint8_t * payload_buffer, uint16_t sco_payload_length){
407     if (!audio_input_paused){
408         int num_samples = hfp_msbc_num_audio_samples_per_frame();
409         btstack_assert(num_samples <= MSBC_MAX_NUM_SAMPLES);
410         if (hfp_msbc_can_encode_audio_frame_now() && btstack_ring_buffer_bytes_available(&audio_input_ring_buffer) >= (unsigned int)(num_samples * BYTES_PER_FRAME)){
411             int16_t sample_buffer[MSBC_MAX_NUM_SAMPLES];
412             uint32_t bytes_read;
413             btstack_ring_buffer_read(&audio_input_ring_buffer, (uint8_t*) sample_buffer, num_samples * BYTES_PER_FRAME, &bytes_read);
414             hfp_msbc_encode_audio_frame(sample_buffer);
415             num_audio_frames++;
416         }
417         btstack_assert(hfp_msbc_num_bytes_in_stream() >= sco_payload_length);
418     }
419 
420     // get data from encoder, fill with 0 if not enough
421     if (audio_input_paused || hfp_msbc_num_bytes_in_stream() < sco_payload_length){
422         // just send '0's
423         memset(payload_buffer, 0, sco_payload_length);
424         audio_input_paused = 1;
425     } else {
426         hfp_msbc_read_from_stream(payload_buffer, sco_payload_length);
427     }
428 }
429 
430 static void sco_demo_msbc_close(void){
431     printf("Used mSBC with PLC, number of processed frames: \n - %d good frames, \n - %d zero frames, \n - %d bad frames.\n", decoder_state.good_frames_nr, decoder_state.zero_frames_nr, decoder_state.bad_frames_nr);
432 }
433 
434 static const codec_support_t codec_msbc = {
435         .init         = &sco_demo_msbc_init,
436         .receive      = &sco_demo_msbc_receive,
437         .fill_payload = &sco_demo_msbc_fill_payload,
438         .close        = &sco_demo_msbc_close,
439         .sample_rate = SAMPLE_RATE_16KHZ
440 };
441 
442 #endif /* ENABLE_HFP_WIDE_BAND_SPEECH */
443 
444 void sco_demo_init(void){
445 
446 #ifdef ENABLE_CLASSIC_LEGACY_CONNECTIONS_FOR_SCO_DEMOS
447     printf("Disable BR/EDR Secure Connctions due to incompatibilities with SCO connections\n");
448     gap_secure_connections_enable(false);
449 #endif
450 
451 	// status
452 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE
453     printf("SCO Demo: Sending and receiving audio via btstack_audio.\n");
454 #endif
455 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
456     if (btstack_audio_sink_get_instance()){
457         printf("SCO Demo: Sending sine wave, audio output via btstack_audio.\n");
458     } else {
459         printf("SCO Demo: Sending sine wave, hexdump received data.\n");
460     }
461 #endif
462 
463     // Set SCO for CVSD (mSBC or other codecs automatically use 8-bit transparent mode)
464     hci_set_sco_voice_setting(0x60);    // linear, unsigned, 16-bit, CVSD
465 
466 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
467     // init mod
468     int hxcmod_initialized = hxcmod_init(&mod_context);
469     btstack_assert(hxcmod_initialized != 0);
470 #endif
471 }
472 
473 void sco_demo_set_codec(uint8_t negotiated_codec){
474     switch (negotiated_codec){
475         case HFP_CODEC_CVSD:
476             codec_current = &codec_cvsd;
477             break;
478 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
479         case HFP_CODEC_MSBC:
480             codec_current = &codec_msbc;
481             break;
482 #endif
483         default:
484             btstack_assert(false);
485             break;
486     }
487 
488     codec_current->init();
489 
490     audio_initialize(codec_current->sample_rate);
491 
492     audio_prebuffer_bytes = SCO_PREBUFFER_MS * (codec_current->sample_rate/1000) * BYTES_PER_FRAME;
493 
494 #ifdef SCO_WAV_FILENAME
495     num_samples_to_write = codec_current->sample_rate * SCO_WAV_DURATION_IN_SECONDS;
496     wav_writer_open(SCO_WAV_FILENAME, 1, codec_current->sample_rate);
497 #endif
498 
499 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
500     sine_wave_steps_per_sample = SINE_WAVE_SAMPLE_RATE / codec_current->sample_rate;
501     sco_demo_audio_generator = &sco_demo_sine_wave_host_endian;
502 #endif
503 
504 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
505     // load mod
506     hxcmod_setcfg(&mod_context, codec_current->sample_rate, 16, 1, 1, 1);
507     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
508     sco_demo_audio_generator = &sco_demo_modplayer;
509 #endif
510 }
511 
512 void sco_demo_receive(uint8_t * packet, uint16_t size){
513     static uint32_t packets = 0;
514     static uint32_t crc_errors = 0;
515     static uint32_t data_received = 0;
516     static uint32_t byte_errors = 0;
517 
518     count_received++;
519 
520     data_received += size - 3;
521     packets++;
522     if (data_received > 100000){
523         printf("Summary: data %07u, packets %04u, packet with crc errors %0u, byte errors %04u\n",  (unsigned int) data_received,  (unsigned int) packets, (unsigned int) crc_errors, (unsigned int) byte_errors);
524         crc_errors = 0;
525         byte_errors = 0;
526         data_received = 0;
527         packets = 0;
528     }
529 
530     codec_current->receive(packet, size);
531 }
532 
533 void sco_demo_send(hci_con_handle_t sco_handle){
534 
535     if (sco_handle == HCI_CON_HANDLE_INVALID) return;
536 
537     int sco_packet_length = hci_get_sco_packet_length();
538     int sco_payload_length = sco_packet_length - 3;
539 
540     hci_reserve_packet_buffer();
541     uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
542 
543 #ifdef USE_ADUIO_GENERATOR
544     #define REFILL_SAMPLES 16
545     // re-fill audio buffer
546     uint16_t samples_free = btstack_ring_buffer_bytes_free(&audio_input_ring_buffer) / 2;
547     while (samples_free > 0){
548         int16_t samples_buffer[REFILL_SAMPLES];
549         uint16_t samples_to_add = btstack_min(samples_free, REFILL_SAMPLES);
550         (*sco_demo_audio_generator)(samples_to_add, samples_buffer);
551         btstack_ring_buffer_write(&audio_input_ring_buffer, (uint8_t *)samples_buffer, samples_to_add * 2);
552         samples_free -= samples_to_add;
553     }
554 #endif
555 
556     // resume if pre-buffer is filled
557     if (audio_input_paused){
558         if (btstack_ring_buffer_bytes_available(&audio_input_ring_buffer) >= audio_prebuffer_bytes){
559             // resume sending
560             audio_input_paused = 0;
561         }
562     }
563 
564     // fill payload by codec
565     codec_current->fill_payload(&sco_packet[3], sco_payload_length);
566 
567     // set handle + flags
568     little_endian_store_16(sco_packet, 0, sco_handle);
569     // set len
570     sco_packet[2] = sco_payload_length;
571     // finally send packet
572     hci_send_sco_packet_buffer(sco_packet_length);
573 
574     // request another send event
575     hci_request_sco_can_send_now_event();
576 
577     count_sent++;
578     if ((count_sent % SCO_REPORT_PERIOD) == 0) {
579         printf("SCO: sent %u, received %u\n", count_sent, count_received);
580     }
581 }
582 
583 void sco_demo_close(void){
584     printf("SCO demo close\n");
585 
586     printf("SCO demo statistics: ");
587     codec_current->close();
588     codec_current = NULL;
589 
590 #if defined(SCO_WAV_FILENAME)
591     wav_writer_close();
592 #endif
593 
594     audio_terminate();
595 }
596