xref: /btstack/example/sco_demo_util.c (revision aeb2ea11482f4ba2e3e4f47536d2398c68e61870)
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 ENABLE_HFP_SUPER_WIDE_BAND_SPEECH
57 #include "btstack_lc3.h"
58 #include "btstack_lc3_google.h"
59 #endif
60 
61 
62 #ifdef _MSC_VER
63 // ignore deprecated warning for fopen
64 #pragma warning(disable : 4996)
65 #endif
66 
67 #ifdef HAVE_POSIX_FILE_IO
68 #include "wav_util.h"
69 #endif
70 
71 // test modes
72 #define SCO_DEMO_MODE_SINE		 0
73 #define SCO_DEMO_MODE_MICROPHONE 1
74 #define SCO_DEMO_MODE_MODPLAYER  2
75 
76 // SCO demo configuration
77 #define SCO_DEMO_MODE               SCO_DEMO_MODE_MICROPHONE
78 
79 // number of sco packets until 'report' on console
80 #define SCO_REPORT_PERIOD           100
81 
82 
83 #ifdef HAVE_POSIX_FILE_IO
84 // length and name of wav file on disk
85 #define SCO_WAV_DURATION_IN_SECONDS 15
86 #define SCO_WAV_FILENAME            "sco_input.wav"
87 #endif
88 
89 // constants
90 #define NUM_CHANNELS            1
91 #define SAMPLE_RATE_8KHZ        8000
92 #define SAMPLE_RATE_16KHZ       16000
93 #define SAMPLE_RATE_32KHZ       32000
94 #define BYTES_PER_FRAME         2
95 
96 // audio pre-buffer - also defines latency
97 #define SCO_PREBUFFER_MS      50
98 #define PREBUFFER_BYTES_8KHZ  (SCO_PREBUFFER_MS *  SAMPLE_RATE_8KHZ/1000 * BYTES_PER_FRAME)
99 #define PREBUFFER_BYTES_16KHZ (SCO_PREBUFFER_MS * SAMPLE_RATE_16KHZ/1000 * BYTES_PER_FRAME)
100 #define PREBUFFER_BYTES_32KHZ (SCO_PREBUFFER_MS * SAMPLE_RATE_32KHZ/1000 * BYTES_PER_FRAME)
101 
102 #if defined(ENABLE_HFP_SUPER_WIDE_BAND_SPEECH)
103 #define PREBUFFER_BYTES_MAX PREBUFFER_BYTES_32KHZ
104 #define SAMPLES_PER_FRAME_MAX 240
105 #elif defined(ENABLE_HFP_WIDE_BAND_SPEECH)
106 #define PREBUFFER_BYTES_MAX PREBUFFER_BYTES_16KHZ
107 #define SAMPLES_PER_FRAME_MAX 120
108 #else
109 #define PREBUFFER_BYTES_MAX PREBUFFER_BYTES_8KHZ
110 #define SAMPLES_PER_FRAME_MAX 60
111 #endif
112 
113 static uint16_t              audio_prebuffer_bytes;
114 
115 // output
116 static int                   audio_output_paused  = 0;
117 static uint8_t               audio_output_ring_buffer_storage[2 * PREBUFFER_BYTES_MAX];
118 static btstack_ring_buffer_t audio_output_ring_buffer;
119 
120 // input
121 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE
122 #define USE_AUDIO_INPUT
123 #else
124 #define USE_ADUIO_GENERATOR
125 static void (*sco_demo_audio_generator)(uint16_t num_samples, int16_t * data);
126 #endif
127 
128 static int                   audio_input_paused  = 0;
129 static uint8_t               audio_input_ring_buffer_storage[2 * PREBUFFER_BYTES_MAX];
130 static btstack_ring_buffer_t audio_input_ring_buffer;
131 
132 // mod player
133 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
134 #include "hxcmod.h"
135 #include "mods/mod.h"
136 static modcontext mod_context;
137 #endif
138 
139 static int count_sent = 0;
140 static int count_received = 0;
141 
142 static btstack_cvsd_plc_state_t cvsd_plc_state;
143 
144 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
145 static btstack_sbc_decoder_state_t msbc_decoder_state;
146 #endif
147 
148 #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH
149 static const btstack_lc3_decoder_t * lc3_decoder;
150 static btstack_lc3_decoder_google_t lc3_decoder_context;
151 static btstack_lc3_encoder_google_t lc3_encoder_context;
152 static hfp_h2_sync_t    hfp_h2_sync;
153 #endif
154 
155 int num_samples_to_write;
156 int num_audio_frames;
157 
158 // generic codec support
159 typedef struct {
160     void (*init)(void);
161     void(*receive)(const uint8_t * packet, uint16_t size);
162     void (*fill_payload)(uint8_t * payload_buffer, uint16_t sco_payload_length);
163     void (*close)(void);
164     //
165     uint16_t sample_rate;
166 } codec_support_t;
167 
168 // current configuration
169 static const codec_support_t * codec_current = NULL;
170 
171 // hfp_codec
172 static hfp_codec_t hfp_codec;
173 
174 // Sine Wave
175 
176 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
177 static uint16_t sine_wave_phase;
178 static uint16_t sine_wave_steps_per_sample;
179 #define SINE_WAVE_SAMPLE_RATE SAMPLE_RATE_32KHZ
180 
181 // input signal: pre-computed int16 sine wave, 32000 Hz at 266 Hz
182 static const int16_t sine_int16[] = {
183      0,   1715,   3425,   5126,   6813,   8481,  10126,  11743,  13328,  14876,
184  16383,  17846,  19260,  20621,  21925,  23170,  24351,  25465,  26509,  27481,
185  28377,  29196,  29934,  30591,  31163,  31650,  32051,  32364,  32587,  32722,
186  32767,  32722,  32587,  32364,  32051,  31650,  31163,  30591,  29934,  29196,
187  28377,  27481,  26509,  25465,  24351,  23170,  21925,  20621,  19260,  17846,
188  16383,  14876,  13328,  11743,  10126,   8481,   6813,   5126,   3425,   1715,
189      0,  -1715,  -3425,  -5126,  -6813,  -8481, -10126, -11743, -13328, -14876,
190 -16384, -17846, -19260, -20621, -21925, -23170, -24351, -25465, -26509, -27481,
191 -28377, -29196, -29934, -30591, -31163, -31650, -32051, -32364, -32587, -32722,
192 -32767, -32722, -32587, -32364, -32051, -31650, -31163, -30591, -29934, -29196,
193 -28377, -27481, -26509, -25465, -24351, -23170, -21925, -20621, -19260, -17846,
194 -16384, -14876, -13328, -11743, -10126,  -8481,  -6813,  -5126,  -3425,  -1715,
195 };
196 
197 static void sco_demo_sine_wave_host_endian(uint16_t num_samples, int16_t * data){
198     unsigned int i;
199     for (i=0; i < num_samples; i++){
200         data[i] = sine_int16[sine_wave_phase];
201         sine_wave_phase += sine_wave_steps_per_sample;
202         if (sine_wave_phase >= (sizeof(sine_int16) / sizeof(int16_t))){
203             sine_wave_phase = 0;
204         }
205     }
206 }
207 #endif
208 
209 // Mod Player
210 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
211 #define NUM_SAMPLES_GENERATOR_BUFFER 30
212 static void sco_demo_modplayer(uint16_t num_samples, int16_t * data){
213     // mix down stereo
214     signed short samples[NUM_SAMPLES_GENERATOR_BUFFER * 2];
215     while (num_samples > 0){
216         uint16_t next_samples = btstack_min(num_samples, NUM_SAMPLES_GENERATOR_BUFFER);
217     	hxcmod_fillbuffer(&mod_context, (unsigned short *) samples, next_samples, NULL);
218         num_samples -= next_samples;
219         uint16_t i;
220         for (i=0;i<next_samples;i++){
221             int32_t left  = samples[2*i + 0];
222             int32_t right = samples[2*i + 1];
223             data[i] = (int16_t)((left + right) / 2);
224         }
225     }
226 }
227 #endif
228 
229 // Audio Playback / Recording
230 
231 static void audio_playback_callback(int16_t * buffer, uint16_t num_samples){
232 
233     // fill with silence while paused
234     if (audio_output_paused){
235         if (btstack_ring_buffer_bytes_available(&audio_output_ring_buffer) < audio_prebuffer_bytes){
236             memset(buffer, 0, num_samples * BYTES_PER_FRAME);
237            return;
238         } else {
239             // resume playback
240             audio_output_paused = 0;
241         }
242     }
243 
244     // get data from ringbuffer
245     uint32_t bytes_read = 0;
246     btstack_ring_buffer_read(&audio_output_ring_buffer, (uint8_t *) buffer, num_samples * BYTES_PER_FRAME, &bytes_read);
247     num_samples -= bytes_read / BYTES_PER_FRAME;
248     buffer      += bytes_read / BYTES_PER_FRAME;
249 
250     // fill with 0 if not enough
251     if (num_samples){
252         memset(buffer, 0, num_samples * BYTES_PER_FRAME);
253         audio_output_paused = 1;
254     }
255 }
256 
257 #ifdef USE_AUDIO_INPUT
258 static void audio_recording_callback(const int16_t * buffer, uint16_t num_samples){
259     btstack_ring_buffer_write(&audio_input_ring_buffer, (uint8_t *)buffer, num_samples * 2);
260 }
261 #endif
262 
263 // return 1 if ok
264 static int audio_initialize(int sample_rate){
265 
266     // -- output -- //
267 
268     // init buffers
269     memset(audio_output_ring_buffer_storage, 0, sizeof(audio_output_ring_buffer_storage));
270     btstack_ring_buffer_init(&audio_output_ring_buffer, audio_output_ring_buffer_storage, sizeof(audio_output_ring_buffer_storage));
271 
272     // config and setup audio playback
273     const btstack_audio_sink_t * audio_sink = btstack_audio_sink_get_instance();
274     if (audio_sink != NULL){
275         audio_sink->init(1, sample_rate, &audio_playback_callback);
276         audio_sink->start_stream();
277 
278         audio_output_paused  = 1;
279     }
280 
281     // -- input -- //
282 
283     // init buffers
284     memset(audio_input_ring_buffer_storage, 0, sizeof(audio_input_ring_buffer_storage));
285     btstack_ring_buffer_init(&audio_input_ring_buffer, audio_input_ring_buffer_storage, sizeof(audio_input_ring_buffer_storage));
286     audio_input_paused  = 1;
287 
288 #ifdef USE_AUDIO_INPUT
289     // config and setup audio recording
290     const btstack_audio_source_t * audio_source = btstack_audio_source_get_instance();
291     if (audio_source != NULL){
292         audio_source->init(1, sample_rate, &audio_recording_callback);
293         audio_source->start_stream();
294     }
295 #endif
296 
297     return 1;
298 }
299 
300 static void audio_terminate(void){
301     const btstack_audio_sink_t * audio_sink = btstack_audio_sink_get_instance();
302     if (!audio_sink) return;
303     audio_sink->close();
304 
305 #ifdef USE_AUDIO_INPUT
306     const btstack_audio_source_t * audio_source= btstack_audio_source_get_instance();
307     if (!audio_source) return;
308     audio_source->close();
309 #endif
310 }
311 
312 
313 // CVSD - 8 kHz
314 
315 static void sco_demo_cvsd_init(void){
316     printf("SCO Demo: Init CVSD\n");
317     btstack_cvsd_plc_init(&cvsd_plc_state);
318 }
319 
320 static void sco_demo_cvsd_receive(const uint8_t * packet, uint16_t size){
321 
322     int16_t audio_frame_out[128];    //
323 
324     if (size > sizeof(audio_frame_out)){
325         printf("sco_demo_cvsd_receive: SCO packet larger than local output buffer - dropping data.\n");
326         return;
327     }
328 
329     const int audio_bytes_read = size - 3;
330     const int num_samples = audio_bytes_read / BYTES_PER_FRAME;
331 
332     // convert into host endian
333     int16_t audio_frame_in[128];
334     int i;
335     for (i=0;i<num_samples;i++){
336         audio_frame_in[i] = little_endian_read_16(packet, 3 + i * 2);
337     }
338 
339     // treat packet as bad frame if controller does not report 'all good'
340     bool bad_frame = (packet[1] & 0x30) != 0;
341 
342     btstack_cvsd_plc_process_data(&cvsd_plc_state, bad_frame, audio_frame_in, num_samples, audio_frame_out);
343 
344 #ifdef SCO_WAV_FILENAME
345     // Samples in CVSD SCO packet are in little endian, ready for wav files (take shortcut)
346     const int samples_to_write = btstack_min(num_samples, num_samples_to_write);
347     wav_writer_write_le_int16(samples_to_write, audio_frame_out);
348     num_samples_to_write -= samples_to_write;
349     if (num_samples_to_write == 0){
350         wav_writer_close();
351     }
352 #endif
353 
354     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)audio_frame_out, audio_bytes_read);
355 }
356 
357 static void sco_demo_cvsd_fill_payload(uint8_t * payload_buffer, uint16_t sco_payload_length){
358     uint16_t bytes_to_copy = sco_payload_length;
359 
360     // get data from ringbuffer
361     uint16_t pos = 0;
362     if (!audio_input_paused){
363         uint16_t samples_to_copy = sco_payload_length / 2;
364         uint32_t bytes_read = 0;
365         btstack_ring_buffer_read(&audio_input_ring_buffer, payload_buffer, bytes_to_copy, &bytes_read);
366         // flip 16 on big endian systems
367         // @note We don't use (uint16_t *) casts since all sample addresses are odd which causes crahses on some systems
368         if (btstack_is_big_endian()){
369             uint16_t i;
370             for (i=0;i<samples_to_copy/2;i+=2){
371                 uint8_t tmp           = payload_buffer[i*2];
372                 payload_buffer[i*2]   = payload_buffer[i*2+1];
373                 payload_buffer[i*2+1] = tmp;
374             }
375         }
376         bytes_to_copy -= bytes_read;
377         pos           += bytes_read;
378     }
379 
380     // fill with 0 if not enough
381     if (bytes_to_copy){
382         memset(payload_buffer + pos, 0, bytes_to_copy);
383         audio_input_paused = 1;
384     }
385 }
386 
387 static void sco_demo_cvsd_close(void){
388     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);
389 }
390 
391 static const codec_support_t codec_cvsd = {
392         .init         = &sco_demo_cvsd_init,
393         .receive      = &sco_demo_cvsd_receive,
394         .fill_payload = &sco_demo_cvsd_fill_payload,
395         .close        = &sco_demo_cvsd_close,
396         .sample_rate = SAMPLE_RATE_8KHZ
397 };
398 
399 // encode using hfp_codec
400 #if defined(ENABLE_HFP_WIDE_BAND_SPEECH) || defined(ENABLE_HFP_SUPER_WIDE_BAND_SPEECH)
401 static void sco_demo_codec_fill_payload(uint8_t * payload_buffer, uint16_t sco_payload_length){
402     if (!audio_input_paused){
403         int num_samples = hfp_codec_num_audio_samples_per_frame(&hfp_codec);
404         btstack_assert(num_samples <= SAMPLES_PER_FRAME_MAX);
405         uint16_t samples_available = btstack_ring_buffer_bytes_available(&audio_input_ring_buffer) / BYTES_PER_FRAME;
406         if (hfp_codec_can_encode_audio_frame_now(&hfp_codec) && samples_available >= num_samples){
407             int16_t sample_buffer[SAMPLES_PER_FRAME_MAX];
408             uint32_t bytes_read;
409             btstack_ring_buffer_read(&audio_input_ring_buffer, (uint8_t*) sample_buffer, num_samples * BYTES_PER_FRAME, &bytes_read);
410             hfp_codec_encode_audio_frame(&hfp_codec, sample_buffer);
411             num_audio_frames++;
412         }
413     }
414     // get data from encoder, fill with 0 if not enough
415     if (audio_input_paused || hfp_codec_num_bytes_available(&hfp_codec) < sco_payload_length){
416         // just send '0's
417         memset(payload_buffer, 0, sco_payload_length);
418         audio_input_paused = 1;
419     } else {
420         hfp_codec_read_from_stream(&hfp_codec, payload_buffer, sco_payload_length);
421     }
422 }
423 #endif
424 
425 // mSBC - 16 kHz
426 
427 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
428 
429 static void handle_pcm_data(int16_t * data, int num_samples, int num_channels, int sample_rate, void * context){
430     UNUSED(context);
431     UNUSED(sample_rate);
432     UNUSED(data);
433     UNUSED(num_samples);
434     UNUSED(num_channels);
435 
436     // samples in callback in host endianess, ready for playback
437     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)data, num_samples*num_channels*2);
438 
439 #ifdef SCO_WAV_FILENAME
440     if (!num_samples_to_write) return;
441     num_samples = btstack_min(num_samples, num_samples_to_write);
442     num_samples_to_write -= num_samples;
443     wav_writer_write_int16(num_samples, data);
444     if (num_samples_to_write == 0){
445         wav_writer_close();
446     }
447 #endif /* SCO_WAV_FILENAME */
448 }
449 
450 static void sco_demo_msbc_init(void){
451     printf("SCO Demo: Init mSBC\n");
452     btstack_sbc_decoder_init(&msbc_decoder_state, SBC_MODE_mSBC, &handle_pcm_data, NULL);
453     hfp_codec_init_msbc(&hfp_codec);
454 }
455 
456 static void sco_demo_msbc_receive(const uint8_t * packet, uint16_t size){
457     btstack_sbc_decoder_process_data(&msbc_decoder_state, (packet[1] >> 4) & 3, packet + 3, size - 3);
458 }
459 
460 static void sco_demo_msbc_close(void){
461     printf("Used mSBC with PLC, number of processed frames: \n - %d good frames, \n - %d zero frames, \n - %d bad frames.\n", msbc_decoder_state.good_frames_nr, msbc_decoder_state.zero_frames_nr, msbc_decoder_state.bad_frames_nr);
462 }
463 
464 static const codec_support_t codec_msbc = {
465         .init         = &sco_demo_msbc_init,
466         .receive      = &sco_demo_msbc_receive,
467         .fill_payload = &sco_demo_codec_fill_payload,
468         .close        = &sco_demo_msbc_close,
469         .sample_rate = SAMPLE_RATE_16KHZ
470 };
471 
472 #endif /* ENABLE_HFP_WIDE_BAND_SPEECH */
473 
474 #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH
475 
476 #define LC3_SWB_SAMPLES_PER_FRAME 240
477 #define LC3_SWB_OCTETS_PER_FRAME   58
478 
479 static bool sco_demo_lc3swb_frame_callback(bool bad_frame, const uint8_t * frame_data, uint16_t frame_len){
480 
481     // skip H2 header for good frames
482     if (bad_frame == false){
483         btstack_assert(frame_data != NULL);
484         frame_data += 2;
485     }
486 
487     uint8_t tmp_BEC_detect = 0;
488     uint8_t BFI = bad_frame ? 1 : 0;
489     int16_t samples[LC3_SWB_SAMPLES_PER_FRAME];
490     (void) lc3_decoder->decode_signed_16(&lc3_decoder_context, frame_data, BFI,
491                                          samples, 1, &tmp_BEC_detect);
492 
493     // samples in callback in host endianess, ready for playback
494     btstack_ring_buffer_write(&audio_output_ring_buffer, (uint8_t *)samples, LC3_SWB_SAMPLES_PER_FRAME*2);
495 
496 #ifdef SCO_WAV_FILENAME
497     if (num_samples_to_write > 0){
498         uint16_t num_samples = btstack_min(LC3_SWB_SAMPLES_PER_FRAME, num_samples_to_write);
499         num_samples_to_write -= num_samples;
500         wav_writer_write_int16(num_samples, samples);
501         if (num_samples_to_write == 0){
502             wav_writer_close();
503         }
504     }
505 #endif /* SCO_WAV_FILENAME */
506 
507     // frame is good, if it isn't a bad frame and we didn't detect other errors
508     return (bad_frame == false) && (tmp_BEC_detect == 0);
509 }
510 
511 static void sco_demo_lc3swb_init(void){
512 
513     printf("SCO Demo: Init LC3-SWB\n");
514 
515     const btstack_lc3_encoder_t * lc3_encoder = btstack_lc3_encoder_google_init_instance((btstack_lc3_encoder_google_t *) hfp_codec.lc3_encoder_context);
516     hfp_codec_init_lc3_swb(&hfp_codec, lc3_encoder, &lc3_encoder_context);
517 
518     // init lc3 decoder
519     lc3_decoder = btstack_lc3_decoder_google_init_instance(&lc3_decoder_context);
520     lc3_decoder->configure(&lc3_decoder_context, SAMPLE_RATE_32KHZ, BTSTACK_LC3_FRAME_DURATION_7500US, LC3_SWB_OCTETS_PER_FRAME);
521 
522     // init HPF H2 framing
523     hfp_h2_sync_init(&hfp_h2_sync, &sco_demo_lc3swb_frame_callback);
524 }
525 
526 static void sco_demo_lc3swb_receive(const uint8_t * packet, uint16_t size){
527     uint8_t packet_status = (packet[1] >> 4) & 3;
528     bool bad_frame = packet_status != 0;
529     hfp_h2_sync_process(&hfp_h2_sync, bad_frame, &packet[3], size-3);
530 }
531 
532 static void sco_demo_lc3swb_close(void){
533     // TODO: report
534 }
535 
536 static const codec_support_t codec_lc3swb = {
537         .init         = &sco_demo_lc3swb_init,
538         .receive      = &sco_demo_lc3swb_receive,
539         .fill_payload = &sco_demo_codec_fill_payload,
540         .close        = &sco_demo_lc3swb_close,
541         .sample_rate = SAMPLE_RATE_32KHZ
542 };
543 #endif
544 
545 void sco_demo_init(void){
546 
547 #ifdef ENABLE_CLASSIC_LEGACY_CONNECTIONS_FOR_SCO_DEMOS
548     printf("Disable BR/EDR Secure Connctions due to incompatibilities with SCO connections\n");
549     gap_secure_connections_enable(false);
550 #endif
551 
552     // Set SCO for CVSD (mSBC or other codecs automatically use 8-bit transparent mode)
553     hci_set_sco_voice_setting(0x60);    // linear, unsigned, 16-bit, CVSD
554 
555     // status
556 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MICROPHONE
557     printf("SCO Demo: Sending and receiving audio via btstack_audio.\n");
558 #endif
559 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
560     printf("SCO Demo: Sending sine wave, audio output via btstack_audio.\n");
561 #endif
562 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
563     printf("SCO Demo: Sending modplayer wave, audio output via btstack_audio.\n");
564     // init mod
565     int hxcmod_initialized = hxcmod_init(&mod_context);
566     btstack_assert(hxcmod_initialized != 0);
567 #endif
568 }
569 
570 void sco_demo_set_codec(uint8_t negotiated_codec){
571     switch (negotiated_codec){
572         case HFP_CODEC_CVSD:
573             codec_current = &codec_cvsd;
574             break;
575 #ifdef ENABLE_HFP_WIDE_BAND_SPEECH
576         case HFP_CODEC_MSBC:
577             codec_current = &codec_msbc;
578             break;
579 #endif
580 #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH
581         case HFP_CODEC_LC3_SWB:
582             codec_current = &codec_lc3swb;
583             break;
584 #endif
585         default:
586             btstack_assert(false);
587             break;
588     }
589 
590     codec_current->init();
591 
592     audio_initialize(codec_current->sample_rate);
593 
594     audio_prebuffer_bytes = SCO_PREBUFFER_MS * (codec_current->sample_rate/1000) * BYTES_PER_FRAME;
595 
596 #ifdef SCO_WAV_FILENAME
597     num_samples_to_write = codec_current->sample_rate * SCO_WAV_DURATION_IN_SECONDS;
598     wav_writer_open(SCO_WAV_FILENAME, 1, codec_current->sample_rate);
599 #endif
600 
601 #if SCO_DEMO_MODE == SCO_DEMO_MODE_SINE
602     sine_wave_steps_per_sample = SINE_WAVE_SAMPLE_RATE / codec_current->sample_rate;
603     sco_demo_audio_generator = &sco_demo_sine_wave_host_endian;
604 #endif
605 
606 #if SCO_DEMO_MODE == SCO_DEMO_MODE_MODPLAYER
607     // load mod
608     hxcmod_setcfg(&mod_context, codec_current->sample_rate, 16, 1, 1, 1);
609     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
610     sco_demo_audio_generator = &sco_demo_modplayer;
611 #endif
612 }
613 
614 void sco_demo_receive(uint8_t * packet, uint16_t size){
615     static uint32_t packets = 0;
616     static uint32_t crc_errors = 0;
617     static uint32_t data_received = 0;
618     static uint32_t byte_errors = 0;
619 
620     count_received++;
621 
622     data_received += size - 3;
623     packets++;
624     if (data_received > 100000){
625         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);
626         crc_errors = 0;
627         byte_errors = 0;
628         data_received = 0;
629         packets = 0;
630     }
631 
632     codec_current->receive(packet, size);
633 }
634 
635 void sco_demo_send(hci_con_handle_t sco_handle){
636 
637     if (sco_handle == HCI_CON_HANDLE_INVALID) return;
638 
639     int sco_packet_length = hci_get_sco_packet_length();
640     int sco_payload_length = sco_packet_length - 3;
641 
642     hci_reserve_packet_buffer();
643     uint8_t * sco_packet = hci_get_outgoing_packet_buffer();
644 
645 #ifdef USE_ADUIO_GENERATOR
646     #define REFILL_SAMPLES 16
647     // re-fill audio buffer
648     uint16_t samples_free = btstack_ring_buffer_bytes_free(&audio_input_ring_buffer) / 2;
649     while (samples_free > 0){
650         int16_t samples_buffer[REFILL_SAMPLES];
651         uint16_t samples_to_add = btstack_min(samples_free, REFILL_SAMPLES);
652         (*sco_demo_audio_generator)(samples_to_add, samples_buffer);
653         btstack_ring_buffer_write(&audio_input_ring_buffer, (uint8_t *)samples_buffer, samples_to_add * 2);
654         samples_free -= samples_to_add;
655     }
656 #endif
657 
658     // resume if pre-buffer is filled
659     if (audio_input_paused){
660         if (btstack_ring_buffer_bytes_available(&audio_input_ring_buffer) >= audio_prebuffer_bytes){
661             // resume sending
662             audio_input_paused = 0;
663         }
664     }
665 
666     // fill payload by codec
667     codec_current->fill_payload(&sco_packet[3], sco_payload_length);
668 
669     // set handle + flags
670     little_endian_store_16(sco_packet, 0, sco_handle);
671     // set len
672     sco_packet[2] = sco_payload_length;
673     // finally send packet
674     hci_send_sco_packet_buffer(sco_packet_length);
675 
676     // request another send event
677     hci_request_sco_can_send_now_event();
678 
679     count_sent++;
680     if ((count_sent % SCO_REPORT_PERIOD) == 0) {
681         printf("SCO: sent %u, received %u\n", count_sent, count_received);
682     }
683 }
684 
685 void sco_demo_close(void){
686     printf("SCO demo close\n");
687 
688     printf("SCO demo statistics: ");
689     codec_current->close();
690     codec_current = NULL;
691 
692 #if defined(SCO_WAV_FILENAME)
693     wav_writer_close();
694 #endif
695 
696     audio_terminate();
697 }
698