xref: /btstack/example/le_audio_demo_util_source.c (revision 24b69d49bc179fd737e711799d7dd499cbeb047f)
1*24b69d49SMatthias Ringwald /*
2*24b69d49SMatthias Ringwald  * Copyright (C) {copyright_year} BlueKitchen GmbH
3*24b69d49SMatthias Ringwald  *
4*24b69d49SMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*24b69d49SMatthias Ringwald  * modification, are permitted provided that the following conditions
6*24b69d49SMatthias Ringwald  * are met:
7*24b69d49SMatthias Ringwald  *
8*24b69d49SMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*24b69d49SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*24b69d49SMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*24b69d49SMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*24b69d49SMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*24b69d49SMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*24b69d49SMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*24b69d49SMatthias Ringwald  *    from this software without specific prior written permission.
16*24b69d49SMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*24b69d49SMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*24b69d49SMatthias Ringwald  *    monetary gain.
19*24b69d49SMatthias Ringwald  *
20*24b69d49SMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*24b69d49SMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*24b69d49SMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*24b69d49SMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*24b69d49SMatthias Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*24b69d49SMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*24b69d49SMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*24b69d49SMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*24b69d49SMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*24b69d49SMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*24b69d49SMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*24b69d49SMatthias Ringwald  * SUCH DAMAGE.
32*24b69d49SMatthias Ringwald  *
33*24b69d49SMatthias Ringwald  * Please inquire about commercial licensing options at
34*24b69d49SMatthias Ringwald  * [email protected]
35*24b69d49SMatthias Ringwald  *
36*24b69d49SMatthias Ringwald  */
37*24b69d49SMatthias Ringwald 
38*24b69d49SMatthias Ringwald #define BTSTACK_FILE__ "le_audio_demo_util_source.c"
39*24b69d49SMatthias Ringwald 
40*24b69d49SMatthias Ringwald #include "le_audio_demo_util_source.h"
41*24b69d49SMatthias Ringwald 
42*24b69d49SMatthias Ringwald #include "btstack_bool.h"
43*24b69d49SMatthias Ringwald #include "btstack_config.h"
44*24b69d49SMatthias Ringwald #include <btstack_debug.h>
45*24b69d49SMatthias Ringwald #include <printf.h>
46*24b69d49SMatthias Ringwald 
47*24b69d49SMatthias Ringwald #include "hci.h"
48*24b69d49SMatthias Ringwald #include "btstack_audio.h"
49*24b69d49SMatthias Ringwald #include "btstack_lc3_google.h"
50*24b69d49SMatthias Ringwald #include "btstack_lc3plus_fraunhofer.h"
51*24b69d49SMatthias Ringwald 
52*24b69d49SMatthias Ringwald #include "hxcmod.h"
53*24b69d49SMatthias Ringwald #include "mods/mod.h"
54*24b69d49SMatthias Ringwald 
55*24b69d49SMatthias Ringwald #ifdef HAVE_POSIX_FILE_IO
56*24b69d49SMatthias Ringwald #include "wav_util.h"
57*24b69d49SMatthias Ringwald #include "btstack_ring_buffer.h"
58*24b69d49SMatthias Ringwald 
59*24b69d49SMatthias Ringwald #endif
60*24b69d49SMatthias Ringwald 
61*24b69d49SMatthias Ringwald //#define DEBUG_PLC
62*24b69d49SMatthias Ringwald #ifdef DEBUG_PLC
63*24b69d49SMatthias Ringwald #define printf_plc(...) printf(__VA_ARGS__)
64*24b69d49SMatthias Ringwald #else
65*24b69d49SMatthias Ringwald #define printf_plc(...)  (void)(0);
66*24b69d49SMatthias Ringwald #endif
67*24b69d49SMatthias Ringwald 
68*24b69d49SMatthias Ringwald #define MAX_CHANNELS 2
69*24b69d49SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480
70*24b69d49SMatthias Ringwald #define MAX_LC3_FRAME_BYTES   155
71*24b69d49SMatthias Ringwald 
72*24b69d49SMatthias Ringwald // playback
73*24b69d49SMatthias Ringwald #define MAX_NUM_LC3_FRAMES   15
74*24b69d49SMatthias Ringwald #define MAX_BYTES_PER_SAMPLE 4
75*24b69d49SMatthias Ringwald #define PLAYBACK_BUFFER_SIZE (MAX_NUM_LC3_FRAMES * MAX_SAMPLES_PER_FRAME * MAX_BYTES_PER_SAMPLE)
76*24b69d49SMatthias Ringwald #define PLAYBACK_START_MS (MAX_NUM_LC3_FRAMES * 20 / 3)
77*24b69d49SMatthias Ringwald 
78*24b69d49SMatthias Ringwald #define ANSI_COLOR_RED     "\x1b[31m"
79*24b69d49SMatthias Ringwald #define ANSI_COLOR_GREEN   "\x1b[32m"
80*24b69d49SMatthias Ringwald #define ANSI_COLOR_YELLOW  "\x1b[33m"
81*24b69d49SMatthias Ringwald #define ANSI_COLOR_BLUE    "\x1b[34m"
82*24b69d49SMatthias Ringwald #define ANSI_COLOR_MAGENTA "\x1b[35m"
83*24b69d49SMatthias Ringwald #define ANSI_COLOR_CYAN    "\x1b[36m"
84*24b69d49SMatthias Ringwald #define ANSI_COLOR_RESET   "\x1b[0m"
85*24b69d49SMatthias Ringwald 
86*24b69d49SMatthias Ringwald // analysis
87*24b69d49SMatthias Ringwald #define PACKET_PREFIX_LEN 10
88*24b69d49SMatthias Ringwald 
89*24b69d49SMatthias Ringwald // SOURCE
90*24b69d49SMatthias Ringwald 
91*24b69d49SMatthias Ringwald // input signal: pre-computed int16 sine wave, 96000 Hz at 300 Hz
92*24b69d49SMatthias Ringwald static const int16_t sine_int16[] = {
93*24b69d49SMatthias Ringwald         0,    643,   1286,   1929,   2571,   3212,   3851,   4489,   5126,   5760,
94*24b69d49SMatthias Ringwald         6393,   7022,   7649,   8273,   8894,   9512,  10126,  10735,  11341,  11943,
95*24b69d49SMatthias Ringwald         12539,  13131,  13718,  14300,  14876,  15446,  16011,  16569,  17121,  17666,
96*24b69d49SMatthias Ringwald         18204,  18736,  19260,  19777,  20286,  20787,  21280,  21766,  22242,  22710,
97*24b69d49SMatthias Ringwald         23170,  23620,  24062,  24494,  24916,  25329,  25732,  26126,  26509,  26882,
98*24b69d49SMatthias Ringwald         27245,  27597,  27938,  28269,  28589,  28898,  29196,  29482,  29757,  30021,
99*24b69d49SMatthias Ringwald         30273,  30513,  30742,  30958,  31163,  31356,  31537,  31705,  31862,  32006,
100*24b69d49SMatthias Ringwald         32137,  32257,  32364,  32458,  32540,  32609,  32666,  32710,  32742,  32761,
101*24b69d49SMatthias Ringwald         32767,  32761,  32742,  32710,  32666,  32609,  32540,  32458,  32364,  32257,
102*24b69d49SMatthias Ringwald         32137,  32006,  31862,  31705,  31537,  31356,  31163,  30958,  30742,  30513,
103*24b69d49SMatthias Ringwald         30273,  30021,  29757,  29482,  29196,  28898,  28589,  28269,  27938,  27597,
104*24b69d49SMatthias Ringwald         27245,  26882,  26509,  26126,  25732,  25329,  24916,  24494,  24062,  23620,
105*24b69d49SMatthias Ringwald         23170,  22710,  22242,  21766,  21280,  20787,  20286,  19777,  19260,  18736,
106*24b69d49SMatthias Ringwald         18204,  17666,  17121,  16569,  16011,  15446,  14876,  14300,  13718,  13131,
107*24b69d49SMatthias Ringwald         12539,  11943,  11341,  10735,  10126,   9512,   8894,   8273,   7649,   7022,
108*24b69d49SMatthias Ringwald         6393,   5760,   5126,   4489,   3851,   3212,   2571,   1929,   1286,    643,
109*24b69d49SMatthias Ringwald         0,   -643,  -1286,  -1929,  -2571,  -3212,  -3851,  -4489,  -5126,  -5760,
110*24b69d49SMatthias Ringwald         -6393,  -7022,  -7649,  -8273,  -8894,  -9512, -10126, -10735, -11341, -11943,
111*24b69d49SMatthias Ringwald         -12539, -13131, -13718, -14300, -14876, -15446, -16011, -16569, -17121, -17666,
112*24b69d49SMatthias Ringwald         -18204, -18736, -19260, -19777, -20286, -20787, -21280, -21766, -22242, -22710,
113*24b69d49SMatthias Ringwald         -23170, -23620, -24062, -24494, -24916, -25329, -25732, -26126, -26509, -26882,
114*24b69d49SMatthias Ringwald         -27245, -27597, -27938, -28269, -28589, -28898, -29196, -29482, -29757, -30021,
115*24b69d49SMatthias Ringwald         -30273, -30513, -30742, -30958, -31163, -31356, -31537, -31705, -31862, -32006,
116*24b69d49SMatthias Ringwald         -32137, -32257, -32364, -32458, -32540, -32609, -32666, -32710, -32742, -32761,
117*24b69d49SMatthias Ringwald         -32767, -32761, -32742, -32710, -32666, -32609, -32540, -32458, -32364, -32257,
118*24b69d49SMatthias Ringwald         -32137, -32006, -31862, -31705, -31537, -31356, -31163, -30958, -30742, -30513,
119*24b69d49SMatthias Ringwald         -30273, -30021, -29757, -29482, -29196, -28898, -28589, -28269, -27938, -27597,
120*24b69d49SMatthias Ringwald         -27245, -26882, -26509, -26126, -25732, -25329, -24916, -24494, -24062, -23620,
121*24b69d49SMatthias Ringwald         -23170, -22710, -22242, -21766, -21280, -20787, -20286, -19777, -19260, -18736,
122*24b69d49SMatthias Ringwald         -18204, -17666, -17121, -16569, -16011, -15446, -14876, -14300, -13718, -13131,
123*24b69d49SMatthias Ringwald         -12539, -11943, -11341, -10735, -10126,  -9512,  -8894,  -8273,  -7649,  -7022,
124*24b69d49SMatthias Ringwald         -6393,  -5760,  -5126,  -4489,  -3851,  -3212,  -2571,  -1929,  -1286,   -643,
125*24b69d49SMatthias Ringwald };
126*24b69d49SMatthias Ringwald 
127*24b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_octets_per_frame;
128*24b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_packet_sequence_numbers[MAX_CHANNELS];
129*24b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_iso_frame_counter;
130*24b69d49SMatthias Ringwald static uint32_t le_audio_demo_source_sampling_frequency_hz;
131*24b69d49SMatthias Ringwald static btstack_lc3_frame_duration_t le_audio_demo_source_frame_duration;
132*24b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_num_channels;
133*24b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_num_streams;
134*24b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_num_channels_per_stream;
135*24b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_num_samples_per_frame;
136*24b69d49SMatthias Ringwald 
137*24b69d49SMatthias Ringwald 
138*24b69d49SMatthias Ringwald static uint8_t le_audio_demo_source_iso_payload[MAX_CHANNELS * MAX_LC3_FRAME_BYTES];
139*24b69d49SMatthias Ringwald 
140*24b69d49SMatthias Ringwald // lc3 encoder
141*24b69d49SMatthias Ringwald static const btstack_lc3_encoder_t * le_audio_demo_source_lc3_encoder;
142*24b69d49SMatthias Ringwald static btstack_lc3_encoder_google_t  le_audio_demo_source_encoder_contexts[MAX_CHANNELS];
143*24b69d49SMatthias Ringwald static int16_t                       le_audio_demo_source_pcm[MAX_CHANNELS * MAX_SAMPLES_PER_FRAME];
144*24b69d49SMatthias Ringwald 
145*24b69d49SMatthias Ringwald // sine generator
146*24b69d49SMatthias Ringwald static uint8_t  le_audio_demo_source_sine_step;
147*24b69d49SMatthias Ringwald static uint16_t le_audio_demo_source_sine_phases[MAX_CHANNELS];
148*24b69d49SMatthias Ringwald 
149*24b69d49SMatthias Ringwald // mod player
150*24b69d49SMatthias Ringwald static bool                 le_audio_demo_source_hxcmod_initialized;
151*24b69d49SMatthias Ringwald static modcontext           le_audio_demo_source_hxcmod_context;
152*24b69d49SMatthias Ringwald static tracker_buffer_state le_audio_demo_source_hxcmod_trkbuf;
153*24b69d49SMatthias Ringwald 
154*24b69d49SMatthias Ringwald void le_audio_demo_util_source_init(void){
155*24b69d49SMatthias Ringwald }
156*24b69d49SMatthias Ringwald 
157*24b69d49SMatthias Ringwald static void le_audio_demo_source_setup_lc3_encoder(void){
158*24b69d49SMatthias Ringwald     uint8_t channel;
159*24b69d49SMatthias Ringwald     for (channel = 0 ; channel < le_audio_demo_source_num_channels ; channel++){
160*24b69d49SMatthias Ringwald         btstack_lc3_encoder_google_t * context = &le_audio_demo_source_encoder_contexts[channel];
161*24b69d49SMatthias Ringwald         le_audio_demo_source_lc3_encoder = btstack_lc3_encoder_google_init_instance(context);
162*24b69d49SMatthias 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);
163*24b69d49SMatthias Ringwald     }
164*24b69d49SMatthias Ringwald 
165*24b69d49SMatthias Ringwald     printf("LC3 Encoder config: %u hz, frame duration %s ms, num samples %u, num octets %u\n",
166*24b69d49SMatthias Ringwald            le_audio_demo_source_sampling_frequency_hz, le_audio_demo_source_frame_duration == BTSTACK_LC3_FRAME_DURATION_7500US ? "7.5" : "10",
167*24b69d49SMatthias Ringwald            le_audio_demo_source_num_samples_per_frame, le_audio_demo_source_octets_per_frame);
168*24b69d49SMatthias Ringwald }
169*24b69d49SMatthias Ringwald 
170*24b69d49SMatthias Ringwald static void le_audio_demo_source_setup_mod_player(void){
171*24b69d49SMatthias Ringwald     if (!le_audio_demo_source_hxcmod_initialized) {
172*24b69d49SMatthias Ringwald         le_audio_demo_source_hxcmod_initialized = hxcmod_init(&le_audio_demo_source_hxcmod_context);
173*24b69d49SMatthias Ringwald         btstack_assert(le_audio_demo_source_hxcmod_initialized != 0);
174*24b69d49SMatthias Ringwald     }
175*24b69d49SMatthias Ringwald     hxcmod_unload(&le_audio_demo_source_hxcmod_context);
176*24b69d49SMatthias Ringwald     hxcmod_setcfg(&le_audio_demo_source_hxcmod_context, le_audio_demo_source_sampling_frequency_hz, 16, 1, 1, 1);
177*24b69d49SMatthias Ringwald     hxcmod_load(&le_audio_demo_source_hxcmod_context, (void *) &mod_data, mod_len);
178*24b69d49SMatthias Ringwald }
179*24b69d49SMatthias Ringwald 
180*24b69d49SMatthias Ringwald void le_audio_demo_util_source_configure(uint8_t num_streams, uint8_t num_channels_per_stream, uint32_t sampling_frequency_hz,
181*24b69d49SMatthias Ringwald                                          btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame) {
182*24b69d49SMatthias Ringwald     le_audio_demo_source_sampling_frequency_hz = sampling_frequency_hz;
183*24b69d49SMatthias Ringwald     le_audio_demo_source_frame_duration = frame_duration;
184*24b69d49SMatthias Ringwald     le_audio_demo_source_octets_per_frame = octets_per_frame;
185*24b69d49SMatthias Ringwald     le_audio_demo_source_num_streams = num_streams;
186*24b69d49SMatthias Ringwald     le_audio_demo_source_num_channels_per_stream = num_channels_per_stream;
187*24b69d49SMatthias Ringwald 
188*24b69d49SMatthias Ringwald     le_audio_demo_source_num_channels = num_streams * num_channels_per_stream;
189*24b69d49SMatthias Ringwald     btstack_assert((le_audio_demo_source_num_channels == 1) || (le_audio_demo_source_num_channels == 2));
190*24b69d49SMatthias Ringwald 
191*24b69d49SMatthias Ringwald     le_audio_demo_source_num_samples_per_frame = btstack_lc3_samples_per_frame(sampling_frequency_hz, frame_duration);
192*24b69d49SMatthias Ringwald     btstack_assert(le_audio_demo_source_num_samples_per_frame <= MAX_SAMPLES_PER_FRAME);
193*24b69d49SMatthias Ringwald 
194*24b69d49SMatthias Ringwald     // setup encoder
195*24b69d49SMatthias Ringwald     le_audio_demo_source_setup_lc3_encoder();
196*24b69d49SMatthias Ringwald 
197*24b69d49SMatthias Ringwald     // setup sine generator
198*24b69d49SMatthias Ringwald     if (sampling_frequency_hz == 44100){
199*24b69d49SMatthias Ringwald         le_audio_demo_source_sine_step = 2;
200*24b69d49SMatthias Ringwald     } else {
201*24b69d49SMatthias Ringwald         le_audio_demo_source_sine_step = 96000 / sampling_frequency_hz;
202*24b69d49SMatthias Ringwald     }
203*24b69d49SMatthias Ringwald 
204*24b69d49SMatthias Ringwald     // setup mod player
205*24b69d49SMatthias Ringwald     le_audio_demo_source_setup_mod_player();
206*24b69d49SMatthias Ringwald };
207*24b69d49SMatthias Ringwald 
208*24b69d49SMatthias Ringwald void le_audio_demo_util_source_generate_iso_frame(le_audio_demo_source_generator generator) {
209*24b69d49SMatthias Ringwald     btstack_assert(le_audio_demo_source_octets_per_frame != 0);
210*24b69d49SMatthias Ringwald     uint16_t sample;
211*24b69d49SMatthias Ringwald     bool encode_pcm = true;
212*24b69d49SMatthias Ringwald     switch (generator){
213*24b69d49SMatthias Ringwald         case AUDIO_SOURCE_COUNTER:
214*24b69d49SMatthias Ringwald             encode_pcm = false;
215*24b69d49SMatthias Ringwald             memset(le_audio_demo_source_iso_payload, le_audio_demo_source_iso_frame_counter++, sizeof(le_audio_demo_source_iso_payload));
216*24b69d49SMatthias Ringwald             break;
217*24b69d49SMatthias Ringwald         case AUDIO_SOURCE_SINE:
218*24b69d49SMatthias Ringwald             // generate sine wave for all channels
219*24b69d49SMatthias Ringwald             for (sample = 0 ; sample < le_audio_demo_source_num_samples_per_frame ; sample++){
220*24b69d49SMatthias Ringwald                 uint8_t i;
221*24b69d49SMatthias Ringwald                 for (i = 0; i < le_audio_demo_source_num_channels; i++) {
222*24b69d49SMatthias Ringwald                     int16_t value = sine_int16[le_audio_demo_source_sine_phases[i]] / 4;
223*24b69d49SMatthias Ringwald                     le_audio_demo_source_pcm[sample * le_audio_demo_source_num_channels + i] = value;
224*24b69d49SMatthias Ringwald                     le_audio_demo_source_sine_phases[i] += le_audio_demo_source_sine_step * (1 + i);    // second channel, double frequency
225*24b69d49SMatthias Ringwald                     if (le_audio_demo_source_sine_phases[i] >= (sizeof(sine_int16) / sizeof(int16_t))) {
226*24b69d49SMatthias Ringwald                         le_audio_demo_source_sine_phases[i] = 0;
227*24b69d49SMatthias Ringwald                     }
228*24b69d49SMatthias Ringwald                 }
229*24b69d49SMatthias Ringwald             }
230*24b69d49SMatthias Ringwald             break;
231*24b69d49SMatthias Ringwald         case AUDIO_SOURCE_MODPLAYER:
232*24b69d49SMatthias Ringwald             // mod player configured for stereo
233*24b69d49SMatthias 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);
234*24b69d49SMatthias Ringwald             if (le_audio_demo_source_num_channels == 1) {
235*24b69d49SMatthias Ringwald                 // stereo -> mono
236*24b69d49SMatthias Ringwald                 uint8_t i;
237*24b69d49SMatthias Ringwald                 for (i=0;i<le_audio_demo_source_num_samples_per_frame;i++){
238*24b69d49SMatthias Ringwald                     le_audio_demo_source_pcm[i] = (le_audio_demo_source_pcm[2*i] / 2) + (le_audio_demo_source_pcm[2*i+1] / 2);
239*24b69d49SMatthias Ringwald                 }
240*24b69d49SMatthias Ringwald             }
241*24b69d49SMatthias Ringwald             break;
242*24b69d49SMatthias Ringwald         default:
243*24b69d49SMatthias Ringwald             btstack_unreachable();
244*24b69d49SMatthias Ringwald             break;
245*24b69d49SMatthias Ringwald     }
246*24b69d49SMatthias Ringwald 
247*24b69d49SMatthias Ringwald     if (encode_pcm){
248*24b69d49SMatthias Ringwald         uint8_t i;
249*24b69d49SMatthias Ringwald         for (i=0;i<le_audio_demo_source_num_channels;i++){
250*24b69d49SMatthias 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]);
251*24b69d49SMatthias Ringwald         }
252*24b69d49SMatthias Ringwald     }
253*24b69d49SMatthias Ringwald };
254*24b69d49SMatthias Ringwald 
255*24b69d49SMatthias Ringwald void le_audio_demo_util_source_send(uint8_t stream_index, hci_con_handle_t con_handle){
256*24b69d49SMatthias Ringwald     btstack_assert(le_audio_demo_source_octets_per_frame != 0);
257*24b69d49SMatthias Ringwald 
258*24b69d49SMatthias Ringwald     bool ok = hci_reserve_packet_buffer();
259*24b69d49SMatthias Ringwald     btstack_assert(ok);
260*24b69d49SMatthias Ringwald 
261*24b69d49SMatthias Ringwald     uint8_t * buffer = hci_get_outgoing_packet_buffer();
262*24b69d49SMatthias Ringwald     // complete SDU, no TimeStamp
263*24b69d49SMatthias Ringwald     little_endian_store_16(buffer, 0, ((uint16_t) con_handle) | (2 << 12));
264*24b69d49SMatthias Ringwald     // len
265*24b69d49SMatthias Ringwald     little_endian_store_16(buffer, 2, 0 + 4 + le_audio_demo_source_num_channels_per_stream * le_audio_demo_source_octets_per_frame);
266*24b69d49SMatthias Ringwald     // TimeStamp if TS flag is set
267*24b69d49SMatthias Ringwald     // packet seq nr
268*24b69d49SMatthias Ringwald     little_endian_store_16(buffer, 4, le_audio_demo_source_packet_sequence_numbers[stream_index]);
269*24b69d49SMatthias Ringwald     // iso sdu len
270*24b69d49SMatthias Ringwald     little_endian_store_16(buffer, 6, le_audio_demo_source_num_channels_per_stream * le_audio_demo_source_octets_per_frame);
271*24b69d49SMatthias Ringwald     uint16_t offset = 8;
272*24b69d49SMatthias Ringwald     // copy encoded payload
273*24b69d49SMatthias Ringwald     uint8_t i;
274*24b69d49SMatthias Ringwald     for (i=0; i<le_audio_demo_source_num_channels_per_stream;i++) {
275*24b69d49SMatthias Ringwald         memcpy(&buffer[offset], &le_audio_demo_source_iso_payload[i * MAX_LC3_FRAME_BYTES], le_audio_demo_source_octets_per_frame);
276*24b69d49SMatthias Ringwald         offset += le_audio_demo_source_octets_per_frame;
277*24b69d49SMatthias Ringwald     }
278*24b69d49SMatthias Ringwald     // send
279*24b69d49SMatthias Ringwald     hci_send_iso_packet_buffer(offset);
280*24b69d49SMatthias Ringwald 
281*24b69d49SMatthias Ringwald     le_audio_demo_source_packet_sequence_numbers[stream_index]++;
282*24b69d49SMatthias Ringwald }
283*24b69d49SMatthias Ringwald 
284*24b69d49SMatthias Ringwald void le_audio_demo_util_source_close(void){
285*24b69d49SMatthias Ringwald }
286