xref: /btstack/test/le_audio/le_audio_broadcast_source.c (revision c824d78c0a34df89b57d535abafcc7dacf30bb06)
1 /*
2  * Copyright (C) 2022 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 MATTHIAS
24  * RINGWALD 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__ "le_audio_broadcast_source.c"
39 
40 /*
41  * LE Audio Broadcast Source
42  */
43 
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <string.h>
47 #include <btstack_debug.h>
48 
49 #include "bluetooth_data_types.h"
50 #include "btstack_stdin.h"
51 #include "btstack_event.h"
52 #include "btstack_run_loop.h"
53 #include "gap.h"
54 #include "hci.h"
55 #include "hci_cmd.h"
56 #include "hci_dump.h"
57 #include "btstack_lc3.h"
58 #include "btstack_lc3_google.h"
59 #include "le-audio/le_audio_base_builder.h"
60 
61 #include "hxcmod.h"
62 #include "mods/mod.h"
63 
64 // PTS mode
65 // #define PTS_MODE
66 
67 // Count mode - send packet count as test data for manual analysis
68 // #define COUNT_MODE
69 
70 // max config
71 #define MAX_NUM_BIS 2
72 #define MAX_SAMPLES_PER_FRAME 480
73 #define MAX_LC3_FRAME_BYTES   155
74 
75 static const uint8_t adv_sid = 0;
76 
77 static le_advertising_set_t le_advertising_set;
78 
79 static const le_extended_advertising_parameters_t extended_params = {
80         .advertising_event_properties = 0,
81         .primary_advertising_interval_min = 0x4b0, // 750 ms
82         .primary_advertising_interval_max = 0x4b0, // 750 ms
83         .primary_advertising_channel_map = 7,
84         .own_address_type = 0,
85         .peer_address_type = 0,
86         .peer_address =  { 0 },
87         .advertising_filter_policy = 0,
88         .advertising_tx_power = 10, // 10 dBm
89         .primary_advertising_phy = 1, // LE 1M PHY
90         .secondary_advertising_max_skip = 0,
91         .secondary_advertising_phy = 1, // LE 1M PHY
92         .advertising_sid = adv_sid,
93         .scan_request_notification_enable = 0,
94 };
95 
96 // Random Broadcast ID, valid for lifetime of BIG
97 #define BROADCAST_ID (0x112233u)
98 
99 static const uint8_t extended_adv_data[] = {
100         // 16 bit service data, ORG_BLUETOOTH_SERVICE_BASIC_AUDIO_ANNOUNCEMENT_SERVICE, Broadcast ID
101         6, BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID, 0x52, 0x18,
102         BROADCAST_ID >> 16,
103         (BROADCAST_ID >> 8) & 0xff,
104         BROADCAST_ID & 0xff,
105         // name
106 #ifdef PTS_MODE
107         7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'P', 'T', 'S', '-', 'x', 'x'
108 #elif defined(COUNT_MODE)
109         6, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'C', 'O', 'U', 'N', 'T'
110 #else
111         7, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, 'S', 'o', 'u', 'r', 'c', 'e'
112 #endif
113 };
114 
115 static const le_periodic_advertising_parameters_t periodic_params = {
116         .periodic_advertising_interval_min = 0x258, // 375 ms
117         .periodic_advertising_interval_max = 0x258, // 375 ms
118         .periodic_advertising_properties = 0
119 };
120 
121 // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz
122 static const int16_t sine_int16[] = {
123         0,    643,   1286,   1929,   2571,   3212,   3851,   4489,   5126,   5760,
124         6393,   7022,   7649,   8273,   8894,   9512,  10126,  10735,  11341,  11943,
125         12539,  13131,  13718,  14300,  14876,  15446,  16011,  16569,  17121,  17666,
126         18204,  18736,  19260,  19777,  20286,  20787,  21280,  21766,  22242,  22710,
127         23170,  23620,  24062,  24494,  24916,  25329,  25732,  26126,  26509,  26882,
128         27245,  27597,  27938,  28269,  28589,  28898,  29196,  29482,  29757,  30021,
129         30273,  30513,  30742,  30958,  31163,  31356,  31537,  31705,  31862,  32006,
130         32137,  32257,  32364,  32458,  32540,  32609,  32666,  32710,  32742,  32761,
131         32767,  32761,  32742,  32710,  32666,  32609,  32540,  32458,  32364,  32257,
132         32137,  32006,  31862,  31705,  31537,  31356,  31163,  30958,  30742,  30513,
133         30273,  30021,  29757,  29482,  29196,  28898,  28589,  28269,  27938,  27597,
134         27245,  26882,  26509,  26126,  25732,  25329,  24916,  24494,  24062,  23620,
135         23170,  22710,  22242,  21766,  21280,  20787,  20286,  19777,  19260,  18736,
136         18204,  17666,  17121,  16569,  16011,  15446,  14876,  14300,  13718,  13131,
137         12539,  11943,  11341,  10735,  10126,   9512,   8894,   8273,   7649,   7022,
138         6393,   5760,   5126,   4489,   3851,   3212,   2571,   1929,   1286,    643,
139         0,   -643,  -1286,  -1929,  -2571,  -3212,  -3851,  -4489,  -5126,  -5760,
140         -6393,  -7022,  -7649,  -8273,  -8894,  -9512, -10126, -10735, -11341, -11943,
141         -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666,
142         -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710,
143         -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882,
144         -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021,
145         -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006,
146         -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761,
147         -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257,
148         -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513,
149         -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597,
150         -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620,
151         -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736,
152         -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131,
153         -12539, -11943, -11341, -10735, -10126,  -9512,  -8894,  -8273,  -7649,  -7022,
154         -6393,  -5760,  -5126,  -4489,  -3851,  -3212,  -2571,  -1929,  -1286,   -643,
155 };
156 
157 static bd_addr_t remote;
158 static const char * remote_addr_string = "00:1B:DC:08:E2:72";
159 
160 static btstack_packet_callback_registration_t hci_event_callback_registration;
161 static uint8_t period_adv_data[255];
162 static uint16_t period_adv_data_len;
163 
164 static uint8_t adv_handle = 0;
165 static unsigned int     next_bis_index;
166 static hci_con_handle_t bis_con_handles[MAX_NUM_BIS];
167 static uint16_t packet_sequence_numbers[MAX_NUM_BIS];
168 static uint8_t framed_pdus;
169 static bool bis_can_send[MAX_NUM_BIS];
170 static bool bis_has_data[MAX_NUM_BIS];
171 static uint8_t iso_frame_counter;
172 static uint16_t frame_duration_us;
173 
174 static le_audio_big_t big_storage;
175 static le_audio_big_params_t big_params;
176 
177 // time stamping
178 #ifdef COUNT_MODE
179 #define MAX_PACKET_INTERVAL_BINS_MS 50
180 static uint32_t send_time_bins[MAX_PACKET_INTERVAL_BINS_MS];
181 static uint32_t send_last_ms;
182 #endif
183 
184 // lc3 codec config
185 static uint16_t sampling_frequency_hz;
186 static btstack_lc3_frame_duration_t frame_duration;
187 static uint16_t number_samples_per_frame;
188 static uint16_t octets_per_frame;
189 static uint8_t  num_bis = 1;
190 
191 // lc3 encoder
192 static const btstack_lc3_encoder_t * lc3_encoder;
193 static btstack_lc3_encoder_google_t encoder_contexts[MAX_NUM_BIS];
194 static int16_t pcm[MAX_NUM_BIS * MAX_SAMPLES_PER_FRAME];
195 static uint8_t iso_payload[MAX_NUM_BIS * MAX_LC3_FRAME_BYTES];
196 static uint32_t time_generation_ms;
197 
198 // codec menu
199 static uint8_t menu_sampling_frequency;
200 static uint8_t menu_variant;
201 
202 // mod player
203 static int hxcmod_initialized;
204 static modcontext mod_context;
205 static tracker_buffer_state trkbuf;
206 
207 // sine generator
208 static uint8_t  sine_step;
209 static uint16_t sine_phases[MAX_NUM_BIS];
210 
211 // encryption
212 static uint8_t encryption = 0;
213 static uint8_t broadcast_code [] = {0x01, 0x02, 0x68, 0x05, 0x53, 0xF1, 0x41, 0x5A, 0xA2, 0x65, 0xBB, 0xAF, 0xC6, 0xEA, 0x03, 0xB8, };
214 
215 // audio producer
216 static enum {
217     AUDIO_SOURCE_SINE,
218     AUDIO_SOURCE_MODPLAYER
219 } audio_source = AUDIO_SOURCE_MODPLAYER;
220 
221 static enum {
222     APP_IDLE,
223     APP_W4_CREATE_BIG_COMPLETE,
224     APP_STREAMING,
225 } app_state = APP_IDLE;
226 
227 // enumerate default codec configs
228 static struct {
229     uint16_t samplingrate_hz;
230     uint8_t  samplingrate_index;
231     uint8_t  num_variants;
232     struct {
233         const char * name;
234         btstack_lc3_frame_duration_t frame_duration;
235         uint16_t octets_per_frame;
236     } variants[6];
237 } codec_configurations[] = {
238     {
239         8000, 0x01, 2,
240         {
241             {  "8_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 26},
242             {  "8_2", BTSTACK_LC3_FRAME_DURATION_10000US, 30}
243         }
244     },
245     {
246        16000, 0x03, 2,
247        {
248             {  "16_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 30},
249             {  "16_2", BTSTACK_LC3_FRAME_DURATION_10000US, 40}
250        }
251     },
252     {
253         24000, 0x05, 2,
254         {
255             {  "24_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 45},
256             {  "24_2", BTSTACK_LC3_FRAME_DURATION_10000US, 60}
257        }
258     },
259     {
260         32000, 0x06, 2,
261         {
262             {  "32_1",  BTSTACK_LC3_FRAME_DURATION_7500US, 60},
263             {  "32_2", BTSTACK_LC3_FRAME_DURATION_10000US, 80}
264         }
265     },
266     {
267         44100, 0x07, 2,
268         {
269             { "441_1",  BTSTACK_LC3_FRAME_DURATION_7500US,  97},
270             { "441_2", BTSTACK_LC3_FRAME_DURATION_10000US, 130}
271         }
272     },
273     {
274         48000, 0x08, 6,
275         {
276             {  "48_1", BTSTACK_LC3_FRAME_DURATION_7500US, 75},
277             {  "48_2", BTSTACK_LC3_FRAME_DURATION_10000US, 100},
278             {  "48_3", BTSTACK_LC3_FRAME_DURATION_7500US, 90},
279             {  "48_4", BTSTACK_LC3_FRAME_DURATION_10000US, 120},
280             {  "48_5", BTSTACK_LC3_FRAME_DURATION_7500US, 117},
281             {  "48_6", BTSTACK_LC3_FRAME_DURATION_10000US, 155}
282         }
283     },
284 };
285 
286 static void show_usage(void);
287 
288 static void print_config(void) {
289     printf("Config '%s_%u': %u, %s ms, %u octets - %s%s\n",
290            codec_configurations[menu_sampling_frequency].variants[menu_variant].name,
291            num_bis,
292            codec_configurations[menu_sampling_frequency].samplingrate_hz,
293            codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
294            codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame,
295            audio_source == AUDIO_SOURCE_SINE ? "Sine" : "Modplayer", encryption ? " (encrypted)" : "");
296 }
297 
298 static void setup_lc3_encoder(void){
299     uint8_t channel;
300     for (channel = 0 ; channel < num_bis ; channel++){
301         btstack_lc3_encoder_google_t * context = &encoder_contexts[channel];
302         lc3_encoder = btstack_lc3_encoder_google_init_instance(context);
303         lc3_encoder->configure(context, sampling_frequency_hz, frame_duration, octets_per_frame);
304     }
305     number_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration);
306     btstack_assert(number_samples_per_frame <= MAX_SAMPLES_PER_FRAME);
307     printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n",
308            sampling_frequency_hz, frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
309            number_samples_per_frame, octets_per_frame);
310 }
311 
312 static void setup_mod_player(void){
313     if (!hxcmod_initialized) {
314         hxcmod_initialized = hxcmod_init(&mod_context);
315         btstack_assert(hxcmod_initialized != 0);
316     }
317     hxcmod_unload(&mod_context);
318     hxcmod_setcfg(&mod_context, sampling_frequency_hz, 16, 1, 1, 1);
319     hxcmod_load(&mod_context, (void *) &mod_data, mod_len);
320 }
321 
322 static void generate_audio(void){
323     uint32_t start_ms = btstack_run_loop_get_time_ms();
324     uint16_t sample;
325     switch (audio_source) {
326         case AUDIO_SOURCE_SINE:
327             // generate sine wave for all channels
328             for (sample = 0 ; sample < number_samples_per_frame ; sample++){
329                 uint8_t channel;
330                 for (channel = 0; channel < num_bis; channel++) {
331                     int16_t value = sine_int16[sine_phases[channel]] / 4;
332                     pcm[sample * num_bis + channel] = value;
333                     sine_phases[channel] += sine_step * (1+channel);    // second channel, double frequency
334                     if (sine_phases[channel] >= (sizeof(sine_int16) / sizeof(int16_t))) {
335                         sine_phases[channel] = 0;
336                     }
337                 }
338             }
339             break;
340         case AUDIO_SOURCE_MODPLAYER:
341             // mod player configured for stereo
342             hxcmod_fillbuffer(&mod_context, (unsigned short *) pcm, number_samples_per_frame, &trkbuf);
343             if (num_bis == 1) {
344                 // stereo -> mono
345                 uint16_t i;
346                 for (i=0;i<number_samples_per_frame;i++){
347                     pcm[i] = (pcm[2*i] / 2) + (pcm[2*i+1] / 2);
348                 }
349             }
350             break;
351         default:
352             btstack_unreachable();
353             break;
354     }
355     time_generation_ms = btstack_run_loop_get_time_ms() - start_ms;
356     iso_frame_counter++;
357 }
358 
359 static void encode(uint8_t bis_index){
360     // encode as lc3
361     lc3_encoder->encode_signed_16(&encoder_contexts[bis_index], &pcm[bis_index], num_bis, &iso_payload[bis_index * MAX_LC3_FRAME_BYTES]);
362 }
363 
364 
365 static void send_iso_packet(uint8_t bis_index) {
366 
367 #ifdef COUNT_MODE
368     if (bis_index == 0) {
369         uint32_t now = btstack_run_loop_get_time_ms();
370         if (send_last_ms != 0) {
371             uint16_t send_interval_ms = now - send_last_ms;
372             if (send_interval_ms >= MAX_PACKET_INTERVAL_BINS_MS) {
373                 printf("ERROR: send interval %u\n", send_interval_ms);
374             } else {
375                 send_time_bins[send_interval_ms]++;
376             }
377         }
378         send_last_ms = now;
379     }
380 #endif
381     bool ok = hci_reserve_packet_buffer();
382     btstack_assert(ok);
383     uint8_t * buffer = hci_get_outgoing_packet_buffer();
384     // complete SDU, no TimeStamp
385     little_endian_store_16(buffer, 0, bis_con_handles[bis_index] | (2 << 12));
386     // len
387     little_endian_store_16(buffer, 2, 0 + 4 + octets_per_frame);
388     // TimeStamp if TS flag is set
389     // packet seq nr
390     little_endian_store_16(buffer, 4, packet_sequence_numbers[bis_index]);
391     // iso sdu len
392     little_endian_store_16(buffer, 6, octets_per_frame);
393 #ifdef COUNT_MODE
394     // test data: bis_index, counter
395     buffer[8] = bis_index;
396     memset(&buffer[9], iso_frame_counter, octets_per_frame - 1);
397 #else
398     // copy encoded payload
399     memcpy(&buffer[8], &iso_payload[bis_index * MAX_LC3_FRAME_BYTES], octets_per_frame);
400 #endif
401     // send
402     hci_send_iso_packet_buffer(4 + 0 + 4 + octets_per_frame);
403 
404 #ifdef HAVE_POSIX_FILE_IO
405     if (((packet_sequence_numbers[bis_index] & 0x7f) == 0) && (bis_index == 0)) {
406         printf("Encoding time: %u\n", time_generation_ms);
407     }
408 #endif
409 
410     packet_sequence_numbers[bis_index]++;
411 }
412 
413 static void generate_audio_and_encode(void){
414     uint8_t i;
415     generate_audio();
416     for (i = 0; i < num_bis; i++) {
417         encode(i);
418         bis_has_data[i] = true;
419     }
420 }
421 
422 static void setup_advertising() {
423     gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle);
424     gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data);
425     gap_periodic_advertising_set_params(adv_handle, &periodic_params);
426     gap_periodic_advertising_set_data(adv_handle, period_adv_data_len, period_adv_data);
427     gap_periodic_advertising_start(adv_handle, 0);
428     gap_extended_advertising_start(adv_handle, 0, 0);
429 }
430 
431 static void setup_big(void){
432     // Create BIG
433     big_params.big_handle = 0;
434     big_params.advertising_handle = adv_handle;
435     big_params.num_bis = num_bis;
436     big_params.max_sdu = octets_per_frame;
437     big_params.max_transport_latency_ms = 31;
438     big_params.rtn = 2;
439     big_params.phy = 2;
440     big_params.packing = 0;
441     big_params.encryption = encryption;
442     if (encryption) {
443         memcpy(big_params.broadcast_code, &broadcast_code[0], 16);
444     } else {
445         memset(big_params.broadcast_code, 0, 16);
446     }
447     if (sampling_frequency_hz == 44100){
448         // same config as for 48k -> frame is longer by 48/44.1
449         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884;
450         big_params.framing = 1;
451     } else {
452         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000;
453         big_params.framing = 0;
454     }
455     app_state = APP_W4_CREATE_BIG_COMPLETE;
456     gap_big_create(&big_storage, &big_params);
457 }
458 
459 
460 static void start_broadcast() {// use values from table
461     sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz;
462     octets_per_frame      = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame;
463     frame_duration        = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration;
464 
465     // get num samples per frame
466     setup_lc3_encoder();
467 
468     // setup base
469     uint8_t codec_id[] = { 0x06, 0x00, 0x00, 0x00, 0x00 };
470     uint8_t subgroup_codec_specific_configuration[] = {
471             0x02, 0x01, 0x01,
472             0x02, 0x02, 0x01,
473             0x03, 0x04, 0x1E, 0x00,
474     };
475     subgroup_codec_specific_configuration[2] = codec_configurations[menu_sampling_frequency].samplingrate_index;
476     subgroup_codec_specific_configuration[5] =  (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;;
477     uint8_t subgroup_metadata[] = {
478             0x03, 0x02, 0x04, 0x00, // Metadata[i]
479     };
480     little_endian_store_16(subgroup_codec_specific_configuration, 8, octets_per_frame);
481     uint8_t bis_codec_specific_configuration_1[] = {
482             0x05, 0x03, 0x01, 0x00, 0x00, 0x00
483     };
484     uint8_t bis_codec_specific_configuration_2[] = {
485             0x05, 0x03, 0x02, 0x00, 0x00, 0x00
486     };
487     le_audio_base_builder_t builder;
488     le_audio_base_builder_init(&builder, period_adv_data, sizeof(period_adv_data), 40);
489     le_audio_base_builder_add_subgroup(&builder, codec_id,
490                                        sizeof(subgroup_codec_specific_configuration),
491                                        subgroup_codec_specific_configuration,
492                                        sizeof(subgroup_metadata), subgroup_metadata);
493     le_audio_base_builder_add_bis(&builder, 1, sizeof(bis_codec_specific_configuration_1),
494                                   bis_codec_specific_configuration_1);
495     if (num_bis == 2){
496         le_audio_base_builder_add_bis(&builder, 2, sizeof(bis_codec_specific_configuration_2),
497                                       bis_codec_specific_configuration_2);
498     }
499     period_adv_data_len = le_audio_base_builder_get_ad_data_size(&builder);
500 
501     // setup mod player
502     setup_mod_player();
503 
504     // setup sine generator
505     if (sampling_frequency_hz == 44100){
506         sine_step = 2;
507     } else {
508         sine_step = 96000 / sampling_frequency_hz;
509     }
510 
511     // setup extended and periodic advertising
512     setup_advertising();
513 
514     // setup big
515     setup_big();
516 }
517 
518 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
519     UNUSED(channel);
520     if (packet_type != HCI_EVENT_PACKET) return;
521     uint8_t bis_index;
522 
523     switch (packet[0]) {
524         case BTSTACK_EVENT_STATE:
525             switch(btstack_event_state_get_state(packet)) {
526                 case HCI_STATE_WORKING:
527 #ifdef ENABLE_DEMO_MODE
528                     // start broadcast automatically, mod player, 48_5_1
529                     num_bis = 1;
530                     menu_sampling_frequency = 5;
531                     menu_variant = 4;
532                     start_broadcast();
533 #else
534                     show_usage();
535                     printf("Please select sample frequency and variation, then start broadcast\n");
536 #endif
537                     break;
538                 case HCI_STATE_OFF:
539                     printf("Goodbye\n");
540                     exit(0);
541                     break;
542                 default:
543                     break;
544             }
545             break;
546         case HCI_EVENT_META_GAP:
547             switch (hci_event_gap_meta_get_subevent_code(packet)){
548                 case GAP_SUBEVENT_BIG_CREATED:
549                     printf("BIG Created with BIS Connection handles: \n");
550                     for (bis_index=0;bis_index<num_bis;bis_index++){
551                         bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index);
552                         printf("0x%04x ", bis_con_handles[bis_index]);
553                     }
554 
555                     app_state = APP_STREAMING;
556                     printf("Start streaming\n");
557                     generate_audio_and_encode();
558                     hci_request_bis_can_send_now_events(big_params.big_handle);
559                     break;
560                 default:
561                     break;
562             }
563             break;
564         case HCI_EVENT_BIS_CAN_SEND_NOW:
565             bis_index = hci_event_bis_can_send_now_get_bis_index(packet);
566             send_iso_packet(bis_index);
567             bis_index++;
568             if (bis_index == num_bis){
569                 generate_audio_and_encode();
570                 hci_request_bis_can_send_now_events(big_params.big_handle);
571             }
572             break;
573         default:
574             break;
575     }
576 }
577 
578 static void show_usage(void){
579     printf("\n--- LE Audio Broadcast Source Test Console ---\n");
580     print_config();
581     printf("---\n");
582     printf("c - toggle channels\n");
583     printf("e - toggle encryption\n");
584     printf("f - next sampling frequency\n");
585     printf("v - next codec variant\n");
586     printf("t - toggle sine / modplayer\n");
587     printf("s - start broadcast\n");
588     printf("---\n");
589 }
590 static void stdin_process(char c){
591     switch (c){
592         case 'c':
593             if (app_state != APP_IDLE){
594                 printf("Codec configuration can only be changed in idle state\n");
595                 break;
596             }
597             num_bis = 3 - num_bis;
598             print_config();
599             break;
600         case 'e':
601             if (app_state != APP_IDLE){
602                 printf("Encryption can only be changed in idle state\n");
603                 break;
604             }
605             encryption = 1 - encryption;
606             print_config();
607             break;
608         case 'f':
609             if (app_state != APP_IDLE){
610                 printf("Codec configuration can only be changed in idle state\n");
611                 break;
612             }
613             menu_sampling_frequency++;
614             if (menu_sampling_frequency >= 6){
615                 menu_sampling_frequency = 0;
616             }
617             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
618                 menu_variant = 0;
619             }
620             print_config();
621             break;
622         case 'v':
623             if (app_state != APP_IDLE){
624                 printf("Codec configuration can only be changed in idle state\n");
625                 break;
626             }
627             menu_variant++;
628             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
629                 menu_variant = 0;
630             }
631             print_config();
632             break;
633         case 's':
634             if (app_state != APP_IDLE){
635                 printf("Cannot start broadcast - not in idle state\n");
636                 break;
637             }
638             start_broadcast();
639             break;
640         case 't':
641             audio_source = 1 - audio_source;
642             print_config();
643             break;
644         case '\n':
645         case '\r':
646             break;
647         default:
648             show_usage();
649             break;
650     }
651 }
652 
653 int btstack_main(int argc, const char * argv[]);
654 int btstack_main(int argc, const char * argv[]){
655     (void) argv;
656     (void) argc;
657 
658     // register for HCI events
659     hci_event_callback_registration.callback = &packet_handler;
660     hci_add_event_handler(&hci_event_callback_registration);
661 
662     // turn on!
663     hci_power_control(HCI_POWER_ON);
664 
665     btstack_stdin_setup(stdin_process);
666     return 0;
667 }
668