xref: /btstack/example/le_audio_demo_util_source.c (revision b5232cd8d2a8f4207ab6f08dbc722b09849da5b1)
124b69d49SMatthias Ringwald /*
224b69d49SMatthias Ringwald  * Copyright (C) {copyright_year} BlueKitchen GmbH
324b69d49SMatthias Ringwald  *
424b69d49SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
524b69d49SMatthias Ringwald  * modification, are permitted provided that the following conditions
624b69d49SMatthias Ringwald  * are met:
724b69d49SMatthias Ringwald  *
824b69d49SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
924b69d49SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
1024b69d49SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
1124b69d49SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
1224b69d49SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
1324b69d49SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
1424b69d49SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
1524b69d49SMatthias Ringwald  *    from this software without specific prior written permission.
1624b69d49SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
1724b69d49SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
1824b69d49SMatthias Ringwald  *    monetary gain.
1924b69d49SMatthias Ringwald  *
2024b69d49SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
2124b69d49SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2224b69d49SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2324b69d49SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
2424b69d49SMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2524b69d49SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
2624b69d49SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
2724b69d49SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2824b69d49SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2924b69d49SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3024b69d49SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3124b69d49SMatthias Ringwald  * SUCH DAMAGE.
3224b69d49SMatthias Ringwald  *
3324b69d49SMatthias Ringwald  * Please inquire about commercial licensing options at
3424b69d49SMatthias Ringwald  * [email protected]
3524b69d49SMatthias Ringwald  *
3624b69d49SMatthias Ringwald  */
3724b69d49SMatthias Ringwald 
3824b69d49SMatthias Ringwald #define BTSTACK_FILE__ "le_audio_demo_util_source.c"
3924b69d49SMatthias Ringwald 
4024b69d49SMatthias Ringwald #include "le_audio_demo_util_source.h"
4124b69d49SMatthias Ringwald 
4224b69d49SMatthias Ringwald #include "btstack_bool.h"
4324b69d49SMatthias Ringwald #include "btstack_config.h"
4424b69d49SMatthias Ringwald #include <btstack_debug.h>
459d8b6c89SDirk Helbig #include <stdio.h>
4624b69d49SMatthias Ringwald 
4724b69d49SMatthias Ringwald #include "hci.h"
4824b69d49SMatthias Ringwald #include "btstack_audio.h"
4924b69d49SMatthias Ringwald #include "btstack_lc3_google.h"
5024b69d49SMatthias Ringwald #include "btstack_lc3plus_fraunhofer.h"
5124b69d49SMatthias Ringwald 
5224b69d49SMatthias Ringwald #include "hxcmod.h"
5324b69d49SMatthias Ringwald #include "mods/mod.h"
5424b69d49SMatthias Ringwald 
5524b69d49SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO
5624b69d49SMatthias Ringwald #include "wav_util.h"
5724b69d49SMatthias Ringwald #include "btstack_ring_buffer.h"
5824b69d49SMatthias Ringwald 
5924b69d49SMatthias Ringwald #endif
6024b69d49SMatthias Ringwald 
6124b69d49SMatthias Ringwald //#define DEBUG_PLC
6224b69d49SMatthias Ringwald #ifdef DEBUG_PLC
6324b69d49SMatthias Ringwald #define printf_plc(...) printf(__VA_ARGS__)
6424b69d49SMatthias Ringwald #else
6524b69d49SMatthias Ringwald #define printf_plc(...)  (void)(0);
6624b69d49SMatthias Ringwald #endif
6724b69d49SMatthias Ringwald 
6824b69d49SMatthias Ringwald #define MAX_CHANNELS 2
6924b69d49SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480
7024b69d49SMatthias Ringwald #define MAX_LC3_FRAME_BYTES   155
7124b69d49SMatthias Ringwald 
7224b69d49SMatthias Ringwald // playback
7324b69d49SMatthias Ringwald #define MAX_NUM_LC3_FRAMES   15
7424b69d49SMatthias Ringwald #define MAX_BYTES_PER_SAMPLE 4
7524b69d49SMatthias Ringwald #define PLAYBACK_BUFFER_SIZE (MAX_NUM_LC3_FRAMES * MAX_SAMPLES_PER_FRAME * MAX_BYTES_PER_SAMPLE)
7624b69d49SMatthias Ringwald #define PLAYBACK_START_MS (MAX_NUM_LC3_FRAMES * 20 / 3)
7724b69d49SMatthias Ringwald 
7824b69d49SMatthias Ringwald #define ANSI_COLOR_RED     "\x1b[31m"
7924b69d49SMatthias Ringwald #define ANSI_COLOR_GREEN   "\x1b[32m"
8024b69d49SMatthias Ringwald #define ANSI_COLOR_YELLOW  "\x1b[33m"
8124b69d49SMatthias Ringwald #define ANSI_COLOR_BLUE    "\x1b[34m"
8224b69d49SMatthias Ringwald #define ANSI_COLOR_MAGENTA "\x1b[35m"
8324b69d49SMatthias Ringwald #define ANSI_COLOR_CYAN    "\x1b[36m"
8424b69d49SMatthias Ringwald #define ANSI_COLOR_RESET   "\x1b[0m"
8524b69d49SMatthias Ringwald 
8624b69d49SMatthias Ringwald // analysis
8724b69d49SMatthias Ringwald #define PACKET_PREFIX_LEN 10
8824b69d49SMatthias Ringwald 
8924b69d49SMatthias Ringwald // SOURCE
9024b69d49SMatthias Ringwald 
9124b69d49SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz
9224b69d49SMatthias Ringwald static const int16_t sine_int16[] = {
9324b69d49SMatthias Ringwald         0,    643,   1286,   1929,   2571,   3212,   3851,   4489,   5126,   5760,
9424b69d49SMatthias Ringwald         6393,   7022,   7649,   8273,   8894,   9512,  10126,  10735,  11341,  11943,
9524b69d49SMatthias Ringwald         12539,  13131,  13718,  14300,  14876,  15446,  16011,  16569,  17121,  17666,
9624b69d49SMatthias Ringwald         18204,  18736,  19260,  19777,  20286,  20787,  21280,  21766,  22242,  22710,
9724b69d49SMatthias Ringwald         23170,  23620,  24062,  24494,  24916,  25329,  25732,  26126,  26509,  26882,
9824b69d49SMatthias Ringwald         27245,  27597,  27938,  28269,  28589,  28898,  29196,  29482,  29757,  30021,
9924b69d49SMatthias Ringwald         30273,  30513,  30742,  30958,  31163,  31356,  31537,  31705,  31862,  32006,
10024b69d49SMatthias Ringwald         32137,  32257,  32364,  32458,  32540,  32609,  32666,  32710,  32742,  32761,
10124b69d49SMatthias Ringwald         32767,  32761,  32742,  32710,  32666,  32609,  32540,  32458,  32364,  32257,
10224b69d49SMatthias Ringwald         32137,  32006,  31862,  31705,  31537,  31356,  31163,  30958,  30742,  30513,
10324b69d49SMatthias Ringwald         30273,  30021,  29757,  29482,  29196,  28898,  28589,  28269,  27938,  27597,
10424b69d49SMatthias Ringwald         27245,  26882,  26509,  26126,  25732,  25329,  24916,  24494,  24062,  23620,
10524b69d49SMatthias Ringwald         23170,  22710,  22242,  21766,  21280,  20787,  20286,  19777,  19260,  18736,
10624b69d49SMatthias Ringwald         18204,  17666,  17121,  16569,  16011,  15446,  14876,  14300,  13718,  13131,
10724b69d49SMatthias Ringwald         12539,  11943,  11341,  10735,  10126,   9512,   8894,   8273,   7649,   7022,
10824b69d49SMatthias Ringwald         6393,   5760,   5126,   4489,   3851,   3212,   2571,   1929,   1286,    643,
10924b69d49SMatthias Ringwald         0,   -643,  -1286,  -1929,  -2571,  -3212,  -3851,  -4489,  -5126,  -5760,
11024b69d49SMatthias Ringwald         -6393,  -7022,  -7649,  -8273,  -8894,  -9512, -10126, -10735, -11341, -11943,
11124b69d49SMatthias Ringwald         -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666,
11224b69d49SMatthias Ringwald         -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710,
11324b69d49SMatthias Ringwald         -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882,
11424b69d49SMatthias Ringwald         -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021,
11524b69d49SMatthias Ringwald         -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006,
11624b69d49SMatthias Ringwald         -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761,
11724b69d49SMatthias Ringwald         -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257,
11824b69d49SMatthias Ringwald         -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513,
11924b69d49SMatthias Ringwald         -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597,
12024b69d49SMatthias Ringwald         -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620,
12124b69d49SMatthias Ringwald         -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736,
12224b69d49SMatthias Ringwald         -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131,
12324b69d49SMatthias Ringwald         -12539, -11943, -11341, -10735, -10126,  -9512,  -8894,  -8273,  -7649,  -7022,
12424b69d49SMatthias Ringwald         -6393,  -5760,  -5126,  -4489,  -3851,  -3212,  -2571,  -1929,  -1286,   -643,
12524b69d49SMatthias Ringwald };
12624b69d49SMatthias Ringwald 
12724b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_octets_per_frame;
12824b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_packet_sequence_numbers[MAX_CHANNELS];
12924b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_iso_frame_counter;
13024b69d49SMatthias Ringwald static uint32_t le_audio_demo_source_sampling_frequency_hz;
13124b69d49SMatthias Ringwald static btstack_lc3_frame_duration_t le_audio_demo_source_frame_duration;
13224b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_num_channels;
13324b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_num_streams;
13424b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_num_channels_per_stream;
13524b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_num_samples_per_frame;
13624b69d49SMatthias Ringwald 
13724b69d49SMatthias Ringwald 
13824b69d49SMatthias Ringwald static uint8_t le_audio_demo_source_iso_payload[MAX_CHANNELS * MAX_LC3_FRAME_BYTES];
13924b69d49SMatthias Ringwald 
14024b69d49SMatthias Ringwald // lc3 encoder
14124b69d49SMatthias Ringwald static const btstack_lc3_encoder_t * le_audio_demo_source_lc3_encoder;
14224b69d49SMatthias Ringwald static btstack_lc3_encoder_google_t  le_audio_demo_source_encoder_contexts[MAX_CHANNELS];
14324b69d49SMatthias Ringwald static int16_t                       le_audio_demo_source_pcm[MAX_CHANNELS * MAX_SAMPLES_PER_FRAME];
14424b69d49SMatthias Ringwald 
14524b69d49SMatthias Ringwald // sine generator
14624b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_sine_step;
14724b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_sine_phases[MAX_CHANNELS];
14824b69d49SMatthias Ringwald 
14924b69d49SMatthias Ringwald // mod player
15024b69d49SMatthias Ringwald static bool                 le_audio_demo_source_hxcmod_initialized;
15124b69d49SMatthias Ringwald static modcontext           le_audio_demo_source_hxcmod_context;
15224b69d49SMatthias Ringwald static tracker_buffer_state le_audio_demo_source_hxcmod_trkbuf;
15324b69d49SMatthias Ringwald 
15424b69d49SMatthias Ringwald void le_audio_demo_util_source_init(void){
15524b69d49SMatthias Ringwald }
15624b69d49SMatthias Ringwald 
15724b69d49SMatthias Ringwald static void le_audio_demo_source_setup_lc3_encoder(void){
15824b69d49SMatthias Ringwald     uint8_t channel;
15924b69d49SMatthias Ringwald     for (channel = 0 ; channel < le_audio_demo_source_num_channels ; channel++){
16024b69d49SMatthias Ringwald         btstack_lc3_encoder_google_t * context = &le_audio_demo_source_encoder_contexts[channel];
16124b69d49SMatthias Ringwald         le_audio_demo_source_lc3_encoder = btstack_lc3_encoder_google_init_instance(context);
16224b69d49SMatthias Ringwald         le_audio_demo_source_lc3_encoder->configure(context, le_audio_demo_source_sampling_frequency_hz, le_audio_demo_source_frame_duration, le_audio_demo_source_octets_per_frame);
16324b69d49SMatthias Ringwald     }
16424b69d49SMatthias Ringwald 
16524b69d49SMatthias Ringwald     printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n",
16624b69d49SMatthias Ringwald            le_audio_demo_source_sampling_frequency_hz, le_audio_demo_source_frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
16724b69d49SMatthias Ringwald            le_audio_demo_source_num_samples_per_frame, le_audio_demo_source_octets_per_frame);
16824b69d49SMatthias Ringwald }
16924b69d49SMatthias Ringwald 
17024b69d49SMatthias Ringwald static void le_audio_demo_source_setup_mod_player(void){
17124b69d49SMatthias Ringwald     if (!le_audio_demo_source_hxcmod_initialized) {
17224b69d49SMatthias Ringwald         le_audio_demo_source_hxcmod_initialized = hxcmod_init(&le_audio_demo_source_hxcmod_context);
17324b69d49SMatthias Ringwald         btstack_assert(le_audio_demo_source_hxcmod_initialized != 0);
17424b69d49SMatthias Ringwald     }
17524b69d49SMatthias Ringwald     hxcmod_unload(&le_audio_demo_source_hxcmod_context);
17624b69d49SMatthias Ringwald     hxcmod_setcfg(&le_audio_demo_source_hxcmod_context, le_audio_demo_source_sampling_frequency_hz, 16, 1, 1, 1);
17724b69d49SMatthias Ringwald     hxcmod_load(&le_audio_demo_source_hxcmod_context, (void *) &mod_data, mod_len);
17824b69d49SMatthias Ringwald }
17924b69d49SMatthias Ringwald 
18024b69d49SMatthias Ringwald void le_audio_demo_util_source_configure(uint8_t num_streams, uint8_t num_channels_per_stream, uint32_t sampling_frequency_hz,
18124b69d49SMatthias Ringwald                                          btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame) {
18224b69d49SMatthias Ringwald     le_audio_demo_source_sampling_frequency_hz = sampling_frequency_hz;
18324b69d49SMatthias Ringwald     le_audio_demo_source_frame_duration = frame_duration;
18424b69d49SMatthias Ringwald     le_audio_demo_source_octets_per_frame = octets_per_frame;
18524b69d49SMatthias Ringwald     le_audio_demo_source_num_streams = num_streams;
18624b69d49SMatthias Ringwald     le_audio_demo_source_num_channels_per_stream = num_channels_per_stream;
18724b69d49SMatthias Ringwald 
18824b69d49SMatthias Ringwald     le_audio_demo_source_num_channels = num_streams * num_channels_per_stream;
18924b69d49SMatthias Ringwald     btstack_assert((le_audio_demo_source_num_channels == 1) || (le_audio_demo_source_num_channels == 2));
19024b69d49SMatthias Ringwald 
19124b69d49SMatthias Ringwald     le_audio_demo_source_num_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration);
19224b69d49SMatthias Ringwald     btstack_assert(le_audio_demo_source_num_samples_per_frame <= MAX_SAMPLES_PER_FRAME);
19324b69d49SMatthias Ringwald 
19424b69d49SMatthias Ringwald     // setup encoder
19524b69d49SMatthias Ringwald     le_audio_demo_source_setup_lc3_encoder();
19624b69d49SMatthias Ringwald 
19724b69d49SMatthias Ringwald     // setup sine generator
19824b69d49SMatthias Ringwald     if (sampling_frequency_hz == 44100){
19924b69d49SMatthias Ringwald         le_audio_demo_source_sine_step = 2;
20024b69d49SMatthias Ringwald     } else {
20124b69d49SMatthias Ringwald         le_audio_demo_source_sine_step = 96000 / sampling_frequency_hz;
20224b69d49SMatthias Ringwald     }
20324b69d49SMatthias Ringwald 
20424b69d49SMatthias Ringwald     // setup mod player
20524b69d49SMatthias Ringwald     le_audio_demo_source_setup_mod_player();
20624b69d49SMatthias Ringwald };
20724b69d49SMatthias Ringwald 
20824b69d49SMatthias Ringwald void le_audio_demo_util_source_generate_iso_frame(le_audio_demo_source_generator generator) {
20924b69d49SMatthias Ringwald     btstack_assert(le_audio_demo_source_octets_per_frame != 0);
21024b69d49SMatthias Ringwald     uint16_t sample;
21124b69d49SMatthias Ringwald     bool encode_pcm = true;
21224b69d49SMatthias Ringwald     switch (generator){
21324b69d49SMatthias Ringwald         case AUDIO_SOURCE_COUNTER:
21424b69d49SMatthias Ringwald             encode_pcm = false;
21524b69d49SMatthias Ringwald             memset(le_audio_demo_source_iso_payload, le_audio_demo_source_iso_frame_counter++, sizeof(le_audio_demo_source_iso_payload));
21624b69d49SMatthias Ringwald             break;
21724b69d49SMatthias Ringwald         case AUDIO_SOURCE_SINE:
21824b69d49SMatthias Ringwald             // generate sine wave for all channels
21924b69d49SMatthias Ringwald             for (sample = 0 ; sample < le_audio_demo_source_num_samples_per_frame ; sample++){
22024b69d49SMatthias Ringwald                 uint8_t i;
22124b69d49SMatthias Ringwald                 for (i = 0; i < le_audio_demo_source_num_channels; i++) {
22224b69d49SMatthias Ringwald                     int16_t value = sine_int16[le_audio_demo_source_sine_phases[i]] / 4;
22324b69d49SMatthias Ringwald                     le_audio_demo_source_pcm[sample * le_audio_demo_source_num_channels + i] = value;
22424b69d49SMatthias Ringwald                     le_audio_demo_source_sine_phases[i] += le_audio_demo_source_sine_step * (1 + i);    // second channel, double frequency
22524b69d49SMatthias Ringwald                     if (le_audio_demo_source_sine_phases[i] >= (sizeof(sine_int16) / sizeof(int16_t))) {
22624b69d49SMatthias Ringwald                         le_audio_demo_source_sine_phases[i] = 0;
22724b69d49SMatthias Ringwald                     }
22824b69d49SMatthias Ringwald                 }
22924b69d49SMatthias Ringwald             }
23024b69d49SMatthias Ringwald             break;
23124b69d49SMatthias Ringwald         case AUDIO_SOURCE_MODPLAYER:
23224b69d49SMatthias Ringwald             // mod player configured for stereo
23324b69d49SMatthias Ringwald             hxcmod_fillbuffer(&le_audio_demo_source_hxcmod_context, (unsigned short *) le_audio_demo_source_pcm, le_audio_demo_source_num_samples_per_frame, &le_audio_demo_source_hxcmod_trkbuf);
23424b69d49SMatthias Ringwald             if (le_audio_demo_source_num_channels == 1) {
23524b69d49SMatthias Ringwald                 // stereo -> mono
236*b5232cd8SMatthias Ringwald                 uint16_t i;
23724b69d49SMatthias Ringwald                 for (i=0;i<le_audio_demo_source_num_samples_per_frame;i++){
23824b69d49SMatthias Ringwald                     le_audio_demo_source_pcm[i] = (le_audio_demo_source_pcm[2*i] / 2) + (le_audio_demo_source_pcm[2*i+1] / 2);
23924b69d49SMatthias Ringwald                 }
24024b69d49SMatthias Ringwald             }
24124b69d49SMatthias Ringwald             break;
24224b69d49SMatthias Ringwald         default:
24324b69d49SMatthias Ringwald             btstack_unreachable();
24424b69d49SMatthias Ringwald             break;
24524b69d49SMatthias Ringwald     }
24624b69d49SMatthias Ringwald 
24724b69d49SMatthias Ringwald     if (encode_pcm){
24824b69d49SMatthias Ringwald         uint8_t i;
24924b69d49SMatthias Ringwald         for (i=0;i<le_audio_demo_source_num_channels;i++){
25024b69d49SMatthias Ringwald             le_audio_demo_source_lc3_encoder->encode_signed_16(&le_audio_demo_source_encoder_contexts[i], &le_audio_demo_source_pcm[i], le_audio_demo_source_num_channels, &le_audio_demo_source_iso_payload[i * MAX_LC3_FRAME_BYTES]);
25124b69d49SMatthias Ringwald         }
25224b69d49SMatthias Ringwald     }
25324b69d49SMatthias Ringwald };
25424b69d49SMatthias Ringwald 
25524b69d49SMatthias Ringwald void le_audio_demo_util_source_send(uint8_t stream_index, hci_con_handle_t con_handle){
25624b69d49SMatthias Ringwald     btstack_assert(le_audio_demo_source_octets_per_frame != 0);
25724b69d49SMatthias Ringwald 
25824b69d49SMatthias Ringwald     bool ok = hci_reserve_packet_buffer();
25924b69d49SMatthias Ringwald     btstack_assert(ok);
26024b69d49SMatthias Ringwald 
26124b69d49SMatthias Ringwald     uint8_t * buffer = hci_get_outgoing_packet_buffer();
26224b69d49SMatthias Ringwald     // complete SDU, no TimeStamp
26324b69d49SMatthias Ringwald     little_endian_store_16(buffer, 0, ((uint16_t) con_handle) | (2 << 12));
26424b69d49SMatthias Ringwald     // len
26524b69d49SMatthias Ringwald     little_endian_store_16(buffer, 2, 0 + 4 + le_audio_demo_source_num_channels_per_stream * le_audio_demo_source_octets_per_frame);
26624b69d49SMatthias Ringwald     // TimeStamp if TS flag is set
26724b69d49SMatthias Ringwald     // packet seq nr
26824b69d49SMatthias Ringwald     little_endian_store_16(buffer, 4, le_audio_demo_source_packet_sequence_numbers[stream_index]);
26924b69d49SMatthias Ringwald     // iso sdu len
27024b69d49SMatthias Ringwald     little_endian_store_16(buffer, 6, le_audio_demo_source_num_channels_per_stream * le_audio_demo_source_octets_per_frame);
27124b69d49SMatthias Ringwald     uint16_t offset = 8;
27224b69d49SMatthias Ringwald     // copy encoded payload
27324b69d49SMatthias Ringwald     uint8_t i;
27424b69d49SMatthias Ringwald     for (i=0; i<le_audio_demo_source_num_channels_per_stream;i++) {
27524b69d49SMatthias Ringwald         memcpy(&buffer[offset], &le_audio_demo_source_iso_payload[i * MAX_LC3_FRAME_BYTES], le_audio_demo_source_octets_per_frame);
27624b69d49SMatthias Ringwald         offset += le_audio_demo_source_octets_per_frame;
27724b69d49SMatthias Ringwald     }
27824b69d49SMatthias Ringwald     // send
27924b69d49SMatthias Ringwald     hci_send_iso_packet_buffer(offset);
28024b69d49SMatthias Ringwald 
28124b69d49SMatthias Ringwald     le_audio_demo_source_packet_sequence_numbers[stream_index]++;
28224b69d49SMatthias Ringwald }
28324b69d49SMatthias Ringwald 
28424b69d49SMatthias Ringwald void le_audio_demo_util_source_close(void){
28524b69d49SMatthias Ringwald }
286