xref: /btstack/test/le_audio/le_audio_broadcast_source.c (revision 9d6cfed5dba87dcd41f0dd650b9b60910a5ee57c)
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 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 = BD_ADDR_TYPE_LE_PUBLIC,
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 bool is_zero_bd_addr( bd_addr_t address ) {
423     int sum = 0;
424     for( int i=0; i<6; ++i ) {
425         sum += address[i];
426     }
427     return (sum>0)?false:true;
428 }
429 
430 static void setup_advertising() {
431     bd_addr_t local_addr;
432     gap_local_bd_addr(local_addr);
433     bool local_address_invalid = is_zero_bd_addr( local_addr );
434     if( local_address_invalid ) {
435         extended_params.own_address_type = BD_ADDR_TYPE_LE_RANDOM;
436     }
437     gap_extended_advertising_setup(&le_advertising_set, &extended_params, &adv_handle);
438     if( local_address_invalid ) {
439         bd_addr_t random_address = { 0xC1, 0x01, 0x01, 0x01, 0x01, 0x01 };
440         gap_extended_advertising_set_random_address( adv_handle, random_address );
441     }
442     gap_extended_advertising_set_adv_data(adv_handle, sizeof(extended_adv_data), extended_adv_data);
443     gap_periodic_advertising_set_params(adv_handle, &periodic_params);
444     gap_periodic_advertising_set_data(adv_handle, period_adv_data_len, period_adv_data);
445     gap_periodic_advertising_start(adv_handle, 0);
446     gap_extended_advertising_start(adv_handle, 0, 0);
447 }
448 
449 static void setup_big(void){
450     // Create BIG
451     big_params.big_handle = 0;
452     big_params.advertising_handle = adv_handle;
453     big_params.num_bis = num_bis;
454     big_params.max_sdu = octets_per_frame;
455     big_params.max_transport_latency_ms = 31;
456     big_params.rtn = 2;
457     big_params.phy = 2;
458     big_params.packing = 0;
459     big_params.encryption = encryption;
460     if (encryption) {
461         memcpy(big_params.broadcast_code, &broadcast_code[0], 16);
462     } else {
463         memset(big_params.broadcast_code, 0, 16);
464     }
465     if (sampling_frequency_hz == 44100){
466         // same config as for 48k -> frame is longer by 48/44.1
467         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 8163 : 10884;
468         big_params.framing = 1;
469     } else {
470         big_params.sdu_interval_us = frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? 7500 : 10000;
471         big_params.framing = 0;
472     }
473     app_state = APP_W4_CREATE_BIG_COMPLETE;
474     gap_big_create(&big_storage, &big_params);
475 }
476 
477 
478 static void start_broadcast() {// use values from table
479     sampling_frequency_hz = codec_configurations[menu_sampling_frequency].samplingrate_hz;
480     octets_per_frame      = codec_configurations[menu_sampling_frequency].variants[menu_variant].octets_per_frame;
481     frame_duration        = codec_configurations[menu_sampling_frequency].variants[menu_variant].frame_duration;
482 
483     // get num samples per frame
484     setup_lc3_encoder();
485 
486     // setup base
487     uint8_t codec_id[] = { 0x06, 0x00, 0x00, 0x00, 0x00 };
488     uint8_t subgroup_codec_specific_configuration[] = {
489             0x02, 0x01, 0x01,
490             0x02, 0x02, 0x01,
491             0x03, 0x04, 0x1E, 0x00,
492     };
493     subgroup_codec_specific_configuration[2] = codec_configurations[menu_sampling_frequency].samplingrate_index;
494     subgroup_codec_specific_configuration[5] =  (frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US) ? 0 : 1;;
495     uint8_t subgroup_metadata[] = {
496             0x03, 0x02, 0x04, 0x00, // Metadata[i]
497     };
498     little_endian_store_16(subgroup_codec_specific_configuration, 8, octets_per_frame);
499     uint8_t bis_codec_specific_configuration_1[] = {
500             0x05, 0x03, 0x01, 0x00, 0x00, 0x00
501     };
502     uint8_t bis_codec_specific_configuration_2[] = {
503             0x05, 0x03, 0x02, 0x00, 0x00, 0x00
504     };
505     le_audio_base_builder_t builder;
506     le_audio_base_builder_init(&builder, period_adv_data, sizeof(period_adv_data), 40);
507     le_audio_base_builder_add_subgroup(&builder, codec_id,
508                                        sizeof(subgroup_codec_specific_configuration),
509                                        subgroup_codec_specific_configuration,
510                                        sizeof(subgroup_metadata), subgroup_metadata);
511     le_audio_base_builder_add_bis(&builder, 1, sizeof(bis_codec_specific_configuration_1),
512                                   bis_codec_specific_configuration_1);
513     if (num_bis == 2){
514         le_audio_base_builder_add_bis(&builder, 2, sizeof(bis_codec_specific_configuration_2),
515                                       bis_codec_specific_configuration_2);
516     }
517     period_adv_data_len = le_audio_base_builder_get_ad_data_size(&builder);
518 
519     // setup mod player
520     setup_mod_player();
521 
522     // setup sine generator
523     if (sampling_frequency_hz == 44100){
524         sine_step = 2;
525     } else {
526         sine_step = 96000 / sampling_frequency_hz;
527     }
528 
529     // setup extended and periodic advertising
530     setup_advertising();
531 
532     // setup big
533     setup_big();
534 }
535 
536 static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
537     UNUSED(channel);
538     if (packet_type != HCI_EVENT_PACKET) return;
539     uint8_t bis_index;
540 
541     switch (packet[0]) {
542         case BTSTACK_EVENT_STATE:
543             switch(btstack_event_state_get_state(packet)) {
544                 case HCI_STATE_WORKING:
545 #ifdef ENABLE_DEMO_MODE
546                     // start broadcast automatically, mod player, 48_5_1
547                     num_bis = 1;
548                     menu_sampling_frequency = 5;
549                     menu_variant = 4;
550                     start_broadcast();
551 #else
552                     show_usage();
553                     printf("Please select sample frequency and variation, then start broadcast\n");
554 #endif
555                     break;
556                 case HCI_STATE_OFF:
557                     printf("Goodbye\n");
558                     exit(0);
559                     break;
560                 default:
561                     break;
562             }
563             break;
564         case HCI_EVENT_META_GAP:
565             switch (hci_event_gap_meta_get_subevent_code(packet)){
566                 case GAP_SUBEVENT_BIG_CREATED:
567                     printf("BIG Created with BIS Connection handles: \n");
568                     for (bis_index=0;bis_index<num_bis;bis_index++){
569                         bis_con_handles[bis_index] = gap_subevent_big_created_get_bis_con_handles(packet, bis_index);
570                         printf("0x%04x ", bis_con_handles[bis_index]);
571                     }
572 
573                     app_state = APP_STREAMING;
574                     printf("Start streaming\n");
575                     generate_audio_and_encode();
576                     hci_request_bis_can_send_now_events(big_params.big_handle);
577                     break;
578                 default:
579                     break;
580             }
581             break;
582         case HCI_EVENT_BIS_CAN_SEND_NOW:
583             bis_index = hci_event_bis_can_send_now_get_bis_index(packet);
584             send_iso_packet(bis_index);
585             bis_index++;
586             if (bis_index == num_bis){
587                 generate_audio_and_encode();
588                 hci_request_bis_can_send_now_events(big_params.big_handle);
589             }
590             break;
591         default:
592             break;
593     }
594 }
595 
596 static void show_usage(void){
597     printf("\n--- LE Audio Broadcast Source Test Console ---\n");
598     print_config();
599     printf("---\n");
600     printf("c - toggle channels\n");
601     printf("e - toggle encryption\n");
602     printf("f - next sampling frequency\n");
603     printf("v - next codec variant\n");
604     printf("t - toggle sine / modplayer\n");
605     printf("s - start broadcast\n");
606     printf("---\n");
607 }
608 static void stdin_process(char c){
609     switch (c){
610         case 'c':
611             if (app_state != APP_IDLE){
612                 printf("Codec configuration can only be changed in idle state\n");
613                 break;
614             }
615             num_bis = 3 - num_bis;
616             print_config();
617             break;
618         case 'e':
619             if (app_state != APP_IDLE){
620                 printf("Encryption can only be changed in idle state\n");
621                 break;
622             }
623             encryption = 1 - encryption;
624             print_config();
625             break;
626         case 'f':
627             if (app_state != APP_IDLE){
628                 printf("Codec configuration can only be changed in idle state\n");
629                 break;
630             }
631             menu_sampling_frequency++;
632             if (menu_sampling_frequency >= 6){
633                 menu_sampling_frequency = 0;
634             }
635             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
636                 menu_variant = 0;
637             }
638             print_config();
639             break;
640         case 'v':
641             if (app_state != APP_IDLE){
642                 printf("Codec configuration can only be changed in idle state\n");
643                 break;
644             }
645             menu_variant++;
646             if (menu_variant >= codec_configurations[menu_sampling_frequency].num_variants){
647                 menu_variant = 0;
648             }
649             print_config();
650             break;
651         case 's':
652             if (app_state != APP_IDLE){
653                 printf("Cannot start broadcast - not in idle state\n");
654                 break;
655             }
656             start_broadcast();
657             break;
658         case 't':
659             audio_source = 1 - audio_source;
660             print_config();
661             break;
662         case '\n':
663         case '\r':
664             break;
665         default:
666             show_usage();
667             break;
668     }
669 }
670 
671 int btstack_main(int argc, const char * argv[]);
672 int btstack_main(int argc, const char * argv[]){
673     (void) argv;
674     (void) argc;
675 
676     // register for HCI events
677     hci_event_callback_registration.callback = &packet_handler;
678     hci_add_event_handler(&hci_event_callback_registration);
679 
680     // turn on!
681     hci_power_control(HCI_POWER_ON);
682 
683     btstack_stdin_setup(stdin_process);
684     return 0;
685 }
686