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