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