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