@@ -144,6 +144,219 @@ static struct named_lc3_preset lc3_broadcast_presets[] = {
144
144
/* Default to 16_2_1 */
145
145
static struct named_lc3_preset * default_preset = & lc3_unicast_presets [3 ];
146
146
147
+ static uint32_t get_next_seq_num (uint32_t interval_us )
148
+ {
149
+ static int64_t last_ticks ;
150
+ int64_t uptime_ticks , delta_ticks ;
151
+ uint64_t delta_us ;
152
+ uint64_t seq_num_incr ;
153
+ uint64_t next_seq_num ;
154
+
155
+ /* Note: This does not handle wrapping of ticks when they go above
156
+ * 2^(62-1)
157
+ */
158
+ uptime_ticks = k_uptime_ticks ();
159
+ delta_ticks = uptime_ticks - last_ticks ;
160
+ last_ticks = uptime_ticks ;
161
+
162
+ delta_us = k_ticks_to_us_near64 ((uint64_t )delta_ticks );
163
+ seq_num_incr = delta_us / interval_us ;
164
+ next_seq_num = (seq_num_incr + seq_num );
165
+
166
+ return (uint32_t )next_seq_num ;
167
+ }
168
+
169
+ #if defined(CONFIG_LIBLC3 )
170
+ NET_BUF_POOL_FIXED_DEFINE (sine_tx_pool , CONFIG_BT_ISO_TX_BUF_COUNT ,
171
+ CONFIG_BT_ISO_TX_MTU + BT_ISO_CHAN_SEND_RESERVE ,
172
+ 8 , NULL );
173
+
174
+ #include "lc3.h"
175
+ #include "math.h"
176
+
177
+ #define MAX_SAMPLE_RATE 48000
178
+ #define MAX_FRAME_DURATION_US 10000
179
+ #define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC)
180
+ #define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */
181
+ #define AUDIO_TONE_FREQUENCY_HZ 400
182
+
183
+ static int16_t audio_buf [MAX_NUM_SAMPLES ];
184
+ static lc3_encoder_t lc3_encoder ;
185
+ static lc3_encoder_mem_48k_t lc3_encoder_mem ;
186
+ static int freq_hz ;
187
+ static int frame_duration_us ;
188
+ static int frame_duration_100us ;
189
+ static int frames_per_sdu ;
190
+ static int octets_per_frame ;
191
+
192
+ /**
193
+ * Use the math lib to generate a sine-wave using 16 bit samples into a buffer.
194
+ *
195
+ * @param buf Destination buffer
196
+ * @param length_us Length of the buffer in microseconds
197
+ * @param frequency_hz frequency in Hz
198
+ * @param sample_rate_hz sample-rate in Hz.
199
+ */
200
+ static void fill_audio_buf_sin (int16_t * buf , int length_us , int frequency_hz , int sample_rate_hz )
201
+ {
202
+ const uint32_t sine_period_samples = sample_rate_hz / frequency_hz ;
203
+ const size_t num_samples = (length_us * sample_rate_hz ) / USEC_PER_SEC ;
204
+ const float step = 2 * 3.1415 / sine_period_samples ;
205
+
206
+ for (size_t i = 0 ; i < num_samples ; i ++ ) {
207
+ const float sample = sin (i * step );
208
+
209
+ buf [i ] = (int16_t )(AUDIO_VOLUME * sample );
210
+ }
211
+ }
212
+
213
+ static void init_lc3 (void )
214
+ {
215
+ size_t num_samples ;
216
+
217
+ freq_hz = bt_codec_cfg_get_freq (& default_preset -> preset .codec );
218
+ frame_duration_us = bt_codec_cfg_get_frame_duration_us (& default_preset -> preset .codec );
219
+ octets_per_frame = bt_codec_cfg_get_octets_per_frame (& default_preset -> preset .codec );
220
+ frames_per_sdu = bt_codec_cfg_get_frame_blocks_per_sdu (& default_preset -> preset .codec , true);
221
+ octets_per_frame = bt_codec_cfg_get_octets_per_frame (& default_preset -> preset .codec );
222
+
223
+ if (freq_hz < 0 ) {
224
+ printk ("Error: Codec frequency not set, cannot start codec." );
225
+ return ;
226
+ }
227
+
228
+ if (frame_duration_us < 0 ) {
229
+ printk ("Error: Frame duration not set, cannot start codec." );
230
+ return ;
231
+ }
232
+
233
+ if (octets_per_frame < 0 ) {
234
+ printk ("Error: Octets per frame not set, cannot start codec." );
235
+ return ;
236
+ }
237
+
238
+ frame_duration_100us = frame_duration_us / 100 ;
239
+
240
+ /* Fill audio buffer with Sine wave only once and repeat encoding the same tone frame */
241
+ fill_audio_buf_sin (audio_buf , frame_duration_us , AUDIO_TONE_FREQUENCY_HZ , freq_hz );
242
+
243
+ num_samples = ((frame_duration_us * freq_hz ) / USEC_PER_SEC );
244
+ for (size_t i = 0 ; i < num_samples ; i ++ ) {
245
+ printk ("%zu: %6i\n" , i , audio_buf [i ]);
246
+ }
247
+
248
+ /* Create the encoder instance. This shall complete before stream_started() is called. */
249
+ lc3_encoder = lc3_setup_encoder (frame_duration_us , freq_hz ,
250
+ 0 , /* No resampling */
251
+ & lc3_encoder_mem );
252
+
253
+ if (lc3_encoder == NULL ) {
254
+ printk ("ERROR: Failed to setup LC3 encoder - wrong parameters?\n" );
255
+ }
256
+ }
257
+
258
+ static void lc3_audio_timer_timeout (struct k_work * work )
259
+ {
260
+ /* For the first call-back we push multiple audio frames to the buffer to use the
261
+ * controller ISO buffer to handle jitter.
262
+ */
263
+ const uint8_t prime_count = 2 ;
264
+ static bool lc3_initialized ;
265
+ static int64_t start_time ;
266
+ static int32_t sdu_cnt ;
267
+ int64_t run_time_100us ;
268
+ int32_t sdu_goal_cnt ;
269
+ int64_t run_time_ms ;
270
+ int64_t uptime ;
271
+
272
+ if (!lc3_initialized ) {
273
+ init_lc3 ();
274
+ lc3_initialized = true;
275
+ }
276
+
277
+ if (lc3_encoder == NULL ) {
278
+ printk ("LC3 encoder not setup, cannot encode data.\n" );
279
+ return ;
280
+ }
281
+
282
+ k_work_schedule (k_work_delayable_from_work (work ),
283
+ K_USEC (default_preset -> preset .qos .interval ));
284
+
285
+ if (start_time == 0 ) {
286
+ /* Read start time and produce the number of frames needed to catch up with any
287
+ * inaccuracies in the timer. by calculating the number of frames we should
288
+ * have sent and compare to how many were actually sent.
289
+ */
290
+ start_time = k_uptime_get ();
291
+ }
292
+
293
+ uptime = k_uptime_get ();
294
+ run_time_ms = uptime - start_time ;
295
+
296
+ /* PDU count calculations done in 100us units to allow 7.5ms framelength in fixed-point */
297
+ run_time_100us = run_time_ms * 10 ;
298
+ sdu_goal_cnt = run_time_100us / (frame_duration_100us * frames_per_sdu );
299
+
300
+ /* Add primer value to ensure the controller do not run low on data due to jitter */
301
+ sdu_goal_cnt += prime_count ;
302
+
303
+ if ((sdu_cnt % 100 ) == 0 ) {
304
+ printk ("LC3 encode %d frames in %d SDUs\n" ,
305
+ (sdu_goal_cnt - sdu_cnt ) * frames_per_sdu ,
306
+ (sdu_goal_cnt - sdu_cnt ));
307
+ }
308
+
309
+ seq_num = get_next_seq_num (default_preset -> preset .qos .interval );
310
+
311
+ while (sdu_cnt < sdu_goal_cnt ) {
312
+ const uint16_t tx_sdu_len = frames_per_sdu * octets_per_frame ;
313
+ struct net_buf * buf ;
314
+ uint8_t * net_buffer ;
315
+ off_t offset = 0 ;
316
+ int err ;
317
+
318
+ buf = net_buf_alloc (& sine_tx_pool , K_FOREVER );
319
+ net_buf_reserve (buf , BT_ISO_CHAN_SEND_RESERVE );
320
+
321
+ net_buffer = net_buf_tail (buf );
322
+ buf -> len += tx_sdu_len ;
323
+
324
+ for (int i = 0 ; i < frames_per_sdu ; i ++ ) {
325
+ int lc3_ret ;
326
+
327
+ lc3_ret = lc3_encode (lc3_encoder , LC3_PCM_FORMAT_S16 ,
328
+ audio_buf , 1 , octets_per_frame ,
329
+ net_buffer + offset );
330
+ offset += octets_per_frame ;
331
+
332
+ if (lc3_ret == -1 ) {
333
+ printk ("LC3 encoder failed - wrong parameters?: %d" ,
334
+ lc3_ret );
335
+ net_buf_unref (buf );
336
+ return ;
337
+ }
338
+ }
339
+
340
+ err = bt_audio_stream_send (default_stream , buf , seq_num ,
341
+ BT_ISO_TIMESTAMP_NONE );
342
+ if (err < 0 ) {
343
+ printk ("Failed to send LC3 audio data (%d)\n" ,
344
+ err );
345
+ net_buf_unref (buf );
346
+ return ;
347
+ }
348
+
349
+ if ((sdu_cnt % 100 ) == 0 ) {
350
+ printk ("TX LC3: %zu\n" , tx_sdu_len );
351
+ }
352
+ sdu_cnt ++ ;
353
+ seq_num ++ ;
354
+ }
355
+ }
356
+
357
+ static K_WORK_DELAYABLE_DEFINE (audio_send_work , lc3_audio_timer_timeout ) ;
358
+ #endif /* CONFIG_LIBLC3 */
359
+
147
360
static void print_codec (const struct bt_codec * codec )
148
361
{
149
362
int i ;
@@ -1155,11 +1368,32 @@ static void audio_recv(struct bt_audio_stream *stream,
1155
1368
{
1156
1369
shell_print (ctx_shell , "Incoming audio on stream %p len %u\n" , stream , buf -> len );
1157
1370
}
1371
+ #endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SINK */
1372
+
1373
+ static void stream_started_cb (struct bt_audio_stream * stream )
1374
+ {
1375
+ printk ("Stream %p started\n" , stream );
1376
+ }
1377
+
1378
+ static void stream_stopped_cb (struct bt_audio_stream * stream )
1379
+ {
1380
+ printk ("Stream %p stopped\n" , stream );
1381
+
1382
+
1383
+ #if defined(CONFIG_LIBLC3 )
1384
+ if (stream == default_stream ) {
1385
+ k_work_cancel_delayable (& audio_send_work );
1386
+ }
1387
+ #endif /* CONFIG_LIBLC3 */
1388
+ }
1158
1389
1159
1390
static struct bt_audio_stream_ops stream_ops = {
1160
- . recv = audio_recv
1161
- };
1391
+ #if defined( CONFIG_BT_AUDIO_UNICAST ) || defined( CONFIG_BT_AUDIO_BROADCAST_SINK )
1392
+ . recv = audio_recv ,
1162
1393
#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SINK */
1394
+ .started = stream_started_cb ,
1395
+ .stopped = stream_stopped_cb ,
1396
+ };
1163
1397
1164
1398
#if defined(CONFIG_BT_AUDIO_BROADCAST_SOURCE )
1165
1399
static int cmd_select_broadcast_source (const struct shell * sh , size_t argc ,
@@ -1517,34 +1751,19 @@ static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
1517
1751
& stream_ops );
1518
1752
}
1519
1753
#endif /* CONFIG_BT_AUDIO_BROADCAST_SOURCE */
1754
+
1755
+ #if defined(CONFIG_BT_AUDIO_BROADCAST_SOURCE )
1756
+ for (i = 0 ; i < ARRAY_SIZE (broadcast_source_streams ); i ++ ) {
1757
+ bt_audio_stream_cb_register (& broadcast_source_streams [i ],
1758
+ & stream_ops );
1759
+ }
1760
+ #endif /* CONFIG_BT_AUDIO_BROADCAST_SOURCE */
1520
1761
return 0 ;
1521
1762
}
1522
1763
1523
1764
#define DATA_MTU CONFIG_BT_ISO_TX_MTU
1524
1765
NET_BUF_POOL_FIXED_DEFINE (tx_pool , 1 , DATA_MTU , 8 , NULL );
1525
1766
1526
- static uint32_t get_next_seq_num (uint32_t interval_us )
1527
- {
1528
- static int64_t last_ticks ;
1529
- int64_t uptime_ticks , delta_ticks ;
1530
- uint64_t delta_us ;
1531
- uint64_t seq_num_incr ;
1532
- uint64_t next_seq_num ;
1533
-
1534
- /* Note: This does not handle wrapping of ticks when they go above
1535
- * 2^(62-1)
1536
- */
1537
- uptime_ticks = k_uptime_ticks ();
1538
- delta_ticks = uptime_ticks - last_ticks ;
1539
- last_ticks = uptime_ticks ;
1540
-
1541
- delta_us = k_ticks_to_us_near64 ((uint64_t )delta_ticks );
1542
- seq_num_incr = delta_us / interval_us ;
1543
- next_seq_num = (seq_num_incr + seq_num );
1544
-
1545
- return (uint32_t )next_seq_num ;
1546
- }
1547
-
1548
1767
static int cmd_send (const struct shell * sh , size_t argc , char * argv [])
1549
1768
{
1550
1769
static uint8_t data [DATA_MTU - BT_ISO_CHAN_SEND_RESERVE ];
@@ -1583,6 +1802,22 @@ static int cmd_send(const struct shell *sh, size_t argc, char *argv[])
1583
1802
return 0 ;
1584
1803
}
1585
1804
1805
+ #if defined(CONFIG_LIBLC3 )
1806
+ static int cmd_start_sine (const struct shell * sh , size_t argc , char * argv [])
1807
+ {
1808
+ k_work_schedule (& audio_send_work , K_MSEC (0 ));
1809
+
1810
+ return 0 ;
1811
+ }
1812
+
1813
+ static int cmd_stop_sine (const struct shell * sh , size_t argc , char * argv [])
1814
+ {
1815
+ k_work_cancel_delayable (& audio_send_work );
1816
+
1817
+ return 0 ;
1818
+ }
1819
+ #endif /* CONFIG_LIBLC3 */
1820
+
1586
1821
SHELL_STATIC_SUBCMD_SET_CREATE (audio_cmds ,
1587
1822
SHELL_CMD_ARG (init , NULL , NULL , cmd_init , 1 , 0 ),
1588
1823
#if defined(CONFIG_BT_AUDIO_BROADCAST_SOURCE )
@@ -1633,6 +1868,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(audio_cmds,
1633
1868
"<stream>" , cmd_select_unicast , 2 , 0 ),
1634
1869
SHELL_CMD_ARG (send , NULL , "Send to Audio Stream [data]" ,
1635
1870
cmd_send , 1 , 1 ),
1871
+ #if defined(CONFIG_LIBLC3 )
1872
+ SHELL_CMD_ARG (start_sine , NULL , "Start sending a LC3 encoded sine wave" ,
1873
+ cmd_start_sine , 1 , 0 ),
1874
+ SHELL_CMD_ARG (stop_sine , NULL , "Stop sending a LC3 encoded sine wave" ,
1875
+ cmd_stop_sine , 1 , 0 ),
1876
+ #endif /* CONFIG_LIBLC3 */
1636
1877
SHELL_COND_CMD_ARG (CONFIG_BT_AUDIO_CAPABILITY , set_location , NULL ,
1637
1878
"<direction: sink, source> <location bitmask>" ,
1638
1879
cmd_set_loc , 3 , 0 ),
0 commit comments