xref: /btstack/example/sco_demo_util.c (revision f0d95bdc335cbf6a1c209a0b20281540b92c2e60)
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_codec.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 #define SAMPLES_PER_FRAME_MAX 120
97 #else
98 #define PREBUFFER_BYTES_MAX PREBUFFER_BYTES_8KHZ
99 #define SAMPLES_PER_FRAME_MAX 60
100 #endif
101 
102 static uint16_t              audio_prebuffer_bytes;
103 
104 // output
105 static int                   audio_output_paused  = 0;
106 static uint8_t               audio_output_ring_buffer_storage[2 * PREBUFFER_BYTES_MAX];
107 static btstack_ring_buffer_t audio_output_ring_buffer;
108 
109 // input
110 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE
111 #define USE_AUDIO_INPUT
112 #else
113 #define USE_ADUIO_GENERATOR
114 static void (*sco_demo_audio_generator)(uint16_t num_samples, int16_t * data);
115 #endif
116 static int                   audio_input_paused  = 0;
117 static uint8_t               audio_input_ring_buffer_storage[2 * PREBUFFER_BYTES_MAX];
118 static btstack_ring_buffer_t audio_input_ring_buffer;
119 
120 // mod player
121 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
122 #include "hxcmod.h"
123 #include "mods/mod.h"
124 static modcontext mod_context;
125 #endif
126 
127 static int count_sent = 0;
128 static int count_received = 0;
129 
130 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
131 #define MSBC_MAX_NUM_SAMPLES (16*8)
132 static btstack_sbc_decoder_state_t decoder_state;
133 #endif
134 
135 static btstack_cvsd_plc_state_t cvsd_plc_state;
136 
137 int num_samples_to_write;
138 int num_audio_frames;
139 
140 // generic codec support
141 typedef struct {
142     void (*init)(void);
143     void(*receive)(const uint8_t * packet, uint16_t size);
144     void (*fill_payload)(uint8_t * payload_buffer, uint16_t sco_payload_length);
145     void (*close)(void);
146     //
147     uint16_t sample_rate;
148 } codec_support_t;
149 
150 // current configuration
151 static const codec_support_t * codec_current = NULL;
152 
153 // hfp_codec
154 static hfp_codec_t hfp_codec;
155 
156 // Sine Wave
157 
158 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
159 static uint16_t sine_wave_phase;
160 static uint16_t sine_wave_steps_per_sample;
161 #define SINE_WAVE_SAMPLE_RATE SAMPLE_RATE_16KHZ
162 
163 // input signal: pre-computed sine wave, 266 Hz at 16000 kHz
164 static const int16_t sine_int16_at_16000hz[] = {
165      0,   3135,   6237,   9270,  12202,  14999,  17633,  20073,  22294,  24270,
166  25980,  27406,  28531,  29344,  29835,  30000,  29835,  29344,  28531,  27406,
167  25980,  24270,  22294,  20073,  17633,  14999,  12202,   9270,   6237,   3135,
168      0,  -3135,  -6237,  -9270, -12202, -14999, -17633, -20073, -22294, -24270,
169 -25980, -27406, -28531, -29344, -29835, -30000, -29835, -29344, -28531, -27406,
170 -25980, -24270, -22294, -20073, -17633, -14999, -12202,  -9270,  -6237,  -3135,
171 };
172 
173 static void sco_demo_sine_wave_host_endian(uint16_t num_samples, int16_t * data){
174     unsigned int i;
175     for (i=0; i < num_samples; i++){
176         data[i] = sine_int16_at_16000hz[sine_wave_phase];
177         sine_wave_phase += sine_wave_steps_per_sample;
178         if (sine_wave_phase >= (sizeof(sine_int16_at_16000hz) / sizeof(int16_t))){
179             sine_wave_phase = 0;
180         }
181     }
182 }
183 #endif
184 
185 // Mod Player
186 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
187 #define NUM_SAMPLES_GENERATOR_BUFFER 30
188 static void sco_demo_modplayer(uint16_t num_samples, int16_t * data){
189     // mix down stereo
190     signed short samples[NUM_SAMPLES_GENERATOR_BUFFER * 2];
191     while (num_samples > 0){
192         uint16_t next_samples = btstack_min(num_samples, NUM_SAMPLES_GENERATOR_BUFFER);
193     	hxcmod_fillbuffer(&mod_context, (unsigned short *) samples, next_samples, NULL);
194         num_samples -= next_samples;
195         uint16_t i;
196         for (i=0;i<next_samples;i++){
197             int32_t left  = samples[2*i + 0];
198             int32_t right = samples[2*i + 1];
199             data[i] = (int16_t)((left + right) / 2);
200         }
201     }
202 }
203 #endif
204 
205 // Audio Playback / Recording
206 
207 static void audio_playback_callback(int16_t * buffer, uint16_t num_samples){
208 
209     // fill with silence while paused
210     if (audio_output_paused){
211         if (btstack_ring_buffer_bytes_available(&audio_output_ring_buffer) < audio_prebuffer_bytes){
212             memset(buffer, 0, num_samples * BYTES_PER_FRAME);
213            return;
214         } else {
215             // resume playback
216             audio_output_paused = 0;
217         }
218     }
219 
220     // get data from ringbuffer
221     uint32_t bytes_read = 0;
222     btstack_ring_buffer_read(&audio_output_ring_buffer, (uint8_t *) buffer, num_samples * BYTES_PER_FRAME, &bytes_read);
223     num_samples -= bytes_read / BYTES_PER_FRAME;
224     buffer      += bytes_read / BYTES_PER_FRAME;
225 
226     // fill with 0 if not enough
227     if (num_samples){
228         memset(buffer, 0, num_samples * BYTES_PER_FRAME);
229         audio_output_paused = 1;
230     }
231 }
232 
233 #ifdef USE_AUDIO_INPUT
234 static void audio_recording_callback(const int16_t * buffer, uint16_t num_samples){
235     btstack_ring_buffer_write(&audio_input_ring_buffer, (uint8_t *)buffer, num_samples * 2);
236 }
237 #endif
238 
239 // return 1 if ok
240 static int audio_initialize(int sample_rate){
241 
242     // -- output -- //
243 
244     // init buffers
245     memset(audio_output_ring_buffer_storage, 0, sizeof(audio_output_ring_buffer_storage));
246     btstack_ring_buffer_init(&audio_output_ring_buffer, audio_output_ring_buffer_storage, sizeof(audio_output_ring_buffer_storage));
247 
248     // config and setup audio playback
249     const btstack_audio_sink_t * audio_sink = btstack_audio_sink_get_instance();
250     if (!audio_sink) return 0;
251 
252     audio_sink->init(1, sample_rate, &audio_playback_callback);
253     audio_sink->start_stream();
254 
255     audio_output_paused  = 1;
256 
257     // -- input -- //
258 
259     // init buffers
260     memset(audio_input_ring_buffer_storage, 0, sizeof(audio_input_ring_buffer_storage));
261     btstack_ring_buffer_init(&audio_input_ring_buffer, audio_input_ring_buffer_storage, sizeof(audio_input_ring_buffer_storage));
262     audio_input_paused  = 1;
263 
264 #ifdef USE_AUDIO_INPUT
265     // config and setup audio recording
266     const btstack_audio_source_t * audio_source = btstack_audio_source_get_instance();
267     if (!audio_source) return 0;
268 
269     audio_source->init(1, sample_rate, &audio_recording_callback);
270     audio_source->start_stream();
271 #endif
272 
273     return 1;
274 }
275 
276 static void audio_terminate(void){
277     const btstack_audio_sink_t * audio_sink = btstack_audio_sink_get_instance();
278     if (!audio_sink) return;
279     audio_sink->close();
280 
281 #ifdef USE_AUDIO_INPUT
282     const btstack_audio_source_t * audio_source= btstack_audio_source_get_instance();
283     if (!audio_source) return;
284     audio_source->close();
285 #endif
286 }
287 
288 
289 // CVSD - 8 kHz
290 
291 static void sco_demo_cvsd_init(void){
292     printf("SCO Demo: Init CVSD\n");
293     btstack_cvsd_plc_init(&cvsd_plc_state);
294 }
295 
296 static void sco_demo_cvsd_receive(const uint8_t * packet, uint16_t size){
297 
298     int16_t audio_frame_out[128];    //
299 
300     if (size > sizeof(audio_frame_out)){
301         printf("sco_demo_cvsd_receive: SCO packet larger than local output buffer - dropping data.\n");
302         return;
303     }
304 
305     const int audio_bytes_read = size - 3;
306     const int num_samples = audio_bytes_read / BYTES_PER_FRAME;
307 
308     // convert into host endian
309     int16_t audio_frame_in[128];
310     int i;
311     for (i=0;i<num_samples;i++){
312         audio_frame_in[i] = little_endian_read_16(packet, 3 + i * 2);
313     }
314 
315     // treat packet as bad frame if controller does not report 'all good'
316     bool bad_frame = (packet[1] & 0x30) != 0;
317 
318     btstack_cvsd_plc_process_data(&cvsd_plc_state, bad_frame, audio_frame_in, num_samples, audio_frame_out);
319 
320 #ifdef SCO_WAV_FILENAME
321     // Samples in CVSD SCO packet are in little endian, ready for wav files (take shortcut)
322     const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
323     wav_writer_write_le_int16(samples_to_write, audio_frame_out);
324     num_samples_to_write -= samples_to_write;
325     if (num_samples_to_write == 0){
326         wav_writer_close();
327     }
328 #endif
329 
330     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read);
331 }
332 
333 static void sco_demo_cvsd_fill_payload(uint8_t * payload_buffer, uint16_t sco_payload_length){
334     uint16_t bytes_to_copy = sco_payload_length;
335 
336     // get data from ringbuffer
337     uint16_t pos = 0;
338     if (!audio_input_paused){
339         uint16_t samples_to_copy = sco_payload_length / 2;
340         uint32_t bytes_read = 0;
341         btstack_ring_buffer_read(&audio_input_ring_buffer, payload_buffer, bytes_to_copy, &bytes_read);
342         // flip 16 on big endian systems
343         // @note We don't use (uint16_t *) casts since all sample addresses are odd which causes crahses on some systems
344         if (btstack_is_big_endian()){
345             uint16_t i;
346             for (i=0;i<samples_to_copy/2;i+=2){
347                 uint8_t tmp           = payload_buffer[i*2];
348                 payload_buffer[i*2]   = payload_buffer[i*2+1];
349                 payload_buffer[i*2+1] = tmp;
350             }
351         }
352         bytes_to_copy -= bytes_read;
353         pos           += bytes_read;
354     }
355 
356     // fill with 0 if not enough
357     if (bytes_to_copy){
358         memset(payload_buffer + pos, 0, bytes_to_copy);
359         audio_input_paused = 1;
360     }
361 }
362 
363 static void sco_demo_cvsd_close(void){
364     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);
365 }
366 
367 static const codec_support_t codec_cvsd = {
368         .init         = &sco_demo_cvsd_init,
369         .receive      = &sco_demo_cvsd_receive,
370         .fill_payload = &sco_demo_cvsd_fill_payload,
371         .close        = &sco_demo_cvsd_close,
372         .sample_rate = SAMPLE_RATE_8KHZ
373 };
374 
375 // mSBC - 16 kHz
376 
377 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
378 
379 static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
380     UNUSED(context);
381     UNUSED(sample_rate);
382     UNUSED(data);
383     UNUSED(num_samples);
384     UNUSED(num_channels);
385 
386     // samples in callback in host endianess, ready for playback
387     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
388 
389 #ifdef SCO_WAV_FILENAME
390     if (!num_samples_to_write) return;
391     num_samples = btstack_min(num_samples, num_samples_to_write);
392     num_samples_to_write -= num_samples;
393     wav_writer_write_int16(num_samples, data);
394     if (num_samples_to_write == 0){
395         wav_writer_close();
396     }
397 #endif /* SCO_WAV_FILENAME */
398 }
399 
400 static void sco_demo_msbc_init(void){
401     printf("SCO Demo: Init mSBC\n");
402     btstack_sbc_decoder_init(&decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL);
403     hfp_codec_init(&hfp_codec, HFP_CODEC_MSBC);
404 }
405 
406 static void sco_demo_msbc_receive(const uint8_t * packet, uint16_t size){
407     btstack_sbc_decoder_process_data(&decoder_state, (packet[1] >> 4) & 3, packet+3, size-3);
408 }
409 
410 void sco_demo_msbc_fill_payload(uint8_t * payload_buffer, uint16_t sco_payload_length){
411     if (!audio_input_paused){
412         int num_samples = hfp_codec_num_audio_samples_per_frame(&hfp_codec);
413         btstack_assert(num_samples <= SAMPLES_PER_FRAME_MAX);
414         uint16_t samples_available = btstack_ring_buffer_bytes_available(&audio_input_ring_buffer) / BYTES_PER_FRAME;
415         if (hfp_codec_can_encode_audio_frame_now(&hfp_codec) && samples_available >= num_samples){
416             int16_t sample_buffer[SAMPLES_PER_FRAME_MAX];
417             uint32_t bytes_read;
418             btstack_ring_buffer_read(&audio_input_ring_buffer, (uint8_t*) sample_buffer, num_samples * BYTES_PER_FRAME, &bytes_read);
419             hfp_codec_encode_audio_frame(&hfp_codec, sample_buffer);
420             num_audio_frames++;
421         }
422     }
423 
424     // get data from encoder, fill with 0 if not enough
425     if (audio_input_paused || hfp_codec_num_bytes_available(&hfp_codec) < sco_payload_length){
426         // just send '0's
427         memset(payload_buffer, 0, sco_payload_length);
428         audio_input_paused = 1;
429     } else {
430         hfp_codec_read_from_stream(&hfp_codec, payload_buffer, sco_payload_length);
431     }
432 }
433 
434 static void sco_demo_msbc_close(void){
435     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);
436 }
437 
438 static const codec_support_t codec_msbc = {
439         .init         = &sco_demo_msbc_init,
440         .receive      = &sco_demo_msbc_receive,
441         .fill_payload = &sco_demo_msbc_fill_payload,
442         .close        = &sco_demo_msbc_close,
443         .sample_rate = SAMPLE_RATE_16KHZ
444 };
445 
446 #endif /* ENABLE_HFP_WIDE_BAND_SPEECH */
447 
448 void sco_demo_init(void){
449 
450 #ifdef ENABLE_CLASSIC_LEGACY_CONNECTIONS_FOR_SCO_DEMOS
451     printf("Disable BR/EDR Secure Connctions due to incompatibilities with SCO connections\n");
452     gap_secure_connections_enable(false);
453 #endif
454 
455 	// status
456 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE
457     printf("SCO Demo: Sending and receiving audio via btstack_audio.\n");
458 #endif
459 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
460     if (btstack_audio_sink_get_instance()){
461         printf("SCO Demo: Sending sine wave, audio output via btstack_audio.\n");
462     } else {
463         printf("SCO Demo: Sending sine wave, hexdump received data.\n");
464     }
465 #endif
466 
467     // Set SCO for CVSD (mSBC or other codecs automatically use 8-bit transparent mode)
468     hci_set_sco_voice_setting(0x60);    // linear, unsigned, 16-bit, CVSD
469 
470 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
471     // init mod
472     int hxcmod_initialized = hxcmod_init(&mod_context);
473     btstack_assert(hxcmod_initialized != 0);
474 #endif
475 }
476 
477 void sco_demo_set_codec(uint8_t negotiated_codec){
478     switch (negotiated_codec){
479         case HFP_CODEC_CVSD:
480             codec_current = &codec_cvsd;
481             break;
482 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
483         case HFP_CODEC_MSBC:
484             codec_current = &codec_msbc;
485             break;
486 #endif
487         default:
488             btstack_assert(false);
489             break;
490     }
491 
492     codec_current->init();
493 
494     audio_initialize(codec_current->sample_rate);
495 
496     audio_prebuffer_bytes = SCO_PREBUFFER_MS * (codec_current->sample_rate/1000) * BYTES_PER_FRAME;
497 
498 #ifdef SCO_WAV_FILENAME
499     num_samples_to_write = codec_current->sample_rate * SCO_WAV_DURATION_IN_SECONDS;
500     wav_writer_open(SCO_WAV_FILENAME, 1, codec_current->sample_rate);
501 #endif
502 
503 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
504     sine_wave_steps_per_sample = SINE_WAVE_SAMPLE_RATE / codec_current->sample_rate;
505     sco_demo_audio_generator = &sco_demo_sine_wave_host_endian;
506 #endif
507 
508 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
509     // load mod
510     hxcmod_setcfg(&mod_context, codec_current->sample_rate, 16, 1, 1, 1);
511     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
512     sco_demo_audio_generator = &sco_demo_modplayer;
513 #endif
514 }
515 
516 void sco_demo_receive(uint8_t * packet, uint16_t size){
517     static uint32_t packets = 0;
518     static uint32_t crc_errors = 0;
519     static uint32_t data_received = 0;
520     static uint32_t byte_errors = 0;
521 
522     count_received++;
523 
524     data_received += size - 3;
525     packets++;
526     if (data_received > 100000){
527         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);
528         crc_errors = 0;
529         byte_errors = 0;
530         data_received = 0;
531         packets = 0;
532     }
533 
534     codec_current->receive(packet, size);
535 }
536 
537 void sco_demo_send(hci_con_handle_t sco_handle){
538 
539     if (sco_handle == HCI_CON_HANDLE_INVALID) return;
540 
541     int sco_packet_length = hci_get_sco_packet_length();
542     int sco_payload_length = sco_packet_length - 3;
543 
544     hci_reserve_packet_buffer();
545     uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
546 
547 #ifdef USE_ADUIO_GENERATOR
548     #define REFILL_SAMPLES 16
549     // re-fill audio buffer
550     uint16_t samples_free = btstack_ring_buffer_bytes_free(&audio_input_ring_buffer) / 2;
551     while (samples_free > 0){
552         int16_t samples_buffer[REFILL_SAMPLES];
553         uint16_t samples_to_add = btstack_min(samples_free, REFILL_SAMPLES);
554         (*sco_demo_audio_generator)(samples_to_add, samples_buffer);
555         btstack_ring_buffer_write(&audio_input_ring_buffer, (uint8_t *)samples_buffer, samples_to_add * 2);
556         samples_free -= samples_to_add;
557     }
558 #endif
559 
560     // resume if pre-buffer is filled
561     if (audio_input_paused){
562         if (btstack_ring_buffer_bytes_available(&audio_input_ring_buffer) >= audio_prebuffer_bytes){
563             // resume sending
564             audio_input_paused = 0;
565         }
566     }
567 
568     // fill payload by codec
569     codec_current->fill_payload(&sco_packet[3], sco_payload_length);
570 
571     // set handle + flags
572     little_endian_store_16(sco_packet, 0, sco_handle);
573     // set len
574     sco_packet[2] = sco_payload_length;
575     // finally send packet
576     hci_send_sco_packet_buffer(sco_packet_length);
577 
578     // request another send event
579     hci_request_sco_can_send_now_event();
580 
581     count_sent++;
582     if ((count_sent % SCO_REPORT_PERIOD) == 0) {
583         printf("SCO: sent %u, received %u\n", count_sent, count_received);
584     }
585 }
586 
587 void sco_demo_close(void){
588     printf("SCO demo close\n");
589 
590     printf("SCO demo statistics: ");
591     codec_current->close();
592     codec_current = NULL;
593 
594 #if defined(SCO_WAV_FILENAME)
595     wav_writer_close();
596 #endif
597 
598     audio_terminate();
599 }
600