Skip to content

Commit 1002906

Browse files
committed
A2DP LHDC codec IO test and proper delay setup
1 parent ddfa790 commit 1002906

File tree

8 files changed

+90
-10
lines changed

8 files changed

+90
-10
lines changed

configure.ac

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# BlueALSA - configure.ac
22
# Copyright (c) 2016-2024 Arkadiusz Bokowy
33

4-
AC_PREREQ([2.60])
4+
AC_PREREQ([2.62])
55
AC_INIT([BlueALSA],
66
[m4_normalize(esyscmd([test -d .git && git describe --always --dirty || echo v4.3.1]))],
77
[arkadiusz.bokowy@gmail.com], [bluez-alsa], [https://github.com/arkq/bluez-alsa])
@@ -13,6 +13,7 @@ AC_CONFIG_MACRO_DIR([m4])
1313

1414
AC_USE_SYSTEM_EXTENSIONS
1515
m4_version_prereq(2.70, [AC_PROG_CC], [AC_PROG_CC_C99])
16+
AC_OPENMP
1617
AC_PROG_INSTALL
1718
AC_PROG_LN_S
1819
AC_PROG_MKDIR_P

src/a2dp-lhdc.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,10 @@ void *a2dp_lhdc_enc_thread(struct ba_transport_pcm *t_pcm) {
198198
goto fail_ffb;
199199
}
200200

201+
const unsigned int ldac_delay_frames = 1024;
202+
/* Get the total delay introduced by the codec. */
203+
t_pcm->codec_delay_dms = ldac_delay_frames * 10000 / rate;
204+
201205
rtp_header_t *rtp_header;
202206
rtp_lhdc_media_header_t *rtp_lhdc_media_header;
203207
/* initialize RTP headers and get anchor for payload */
@@ -216,6 +220,7 @@ void *a2dp_lhdc_enc_thread(struct ba_transport_pcm *t_pcm) {
216220
switch (io_poll_and_read_pcm(&io, t_pcm, &pcm)) {
217221
case -1:
218222
if (errno == ESTALE) {
223+
/* TODO: flush encoder internal buffers */
219224
ffb_rewind(&pcm);
220225
continue;
221226
}

src/shared/a2dp-codecs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -571,7 +571,7 @@ typedef struct a2dp_ldac {
571571

572572
#define LHDC_MAX_BITRATE_400K (1 << 1)
573573
#define LHDC_MAX_BITRATE_500K (1 << 0)
574-
#define LHDC_MAX_BITRATE_900K 0x00
574+
#define LHDC_MAX_BITRATE_900K (0)
575575

576576
#define LHDC_CH_SPLIT_MODE_NONE (1 << 0)
577577
#define LHDC_CH_SPLIT_MODE_TWS (1 << 1)

test/Makefile.am

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,11 @@ test_a2dp_SOURCES += ../src/a2dp-ldac.c
282282
test_io_SOURCES += ../src/a2dp-ldac.c
283283
endif
284284

285+
if ENABLE_LHDC
286+
test_a2dp_SOURCES += ../src/a2dp-lhdc.c
287+
test_io_SOURCES += ../src/a2dp-lhdc.c
288+
endif
289+
285290
if ENABLE_MPEG
286291
test_a2dp_SOURCES += ../src/a2dp-mpeg.c
287292
test_io_SOURCES += ../src/a2dp-mpeg.c
@@ -322,10 +327,13 @@ AM_CFLAGS = \
322327
@LDAC_ABR_CFLAGS@ \
323328
@LDAC_DEC_CFLAGS@ \
324329
@LDAC_ENC_CFLAGS@ \
330+
@LHDC_DEC_CFLAGS@ \
331+
@LHDC_ENC_CFLAGS@ \
325332
@LIBBSD_CFLAGS@ \
326333
@LIBUNWIND_CFLAGS@ \
327334
@MP3LAME_CFLAGS@ \
328335
@MPG123_CFLAGS@ \
336+
@OPENMP_CFLAGS@ \
329337
@OPUS_CFLAGS@ \
330338
@SBC_CFLAGS@ \
331339
@SNDFILE_CFLAGS@ \
@@ -345,6 +353,8 @@ LDADD = \
345353
@LDAC_ABR_LIBS@ \
346354
@LDAC_DEC_LIBS@ \
347355
@LDAC_ENC_LIBS@ \
356+
@LHDC_DEC_LIBS@ \
357+
@LHDC_ENC_LIBS@ \
348358
@LIBUNWIND_LIBS@ \
349359
@MP3LAME_LIBS@ \
350360
@MPG123_LIBS@ \

test/inc/btd.inc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ struct bt_dump *bt_dump_open(const char *path) {
174174
goto fail;
175175
}
176176

177-
uint16_t id;
177+
uint32_t id;
178178
if (bt_dump_read(btd, &id, sizeof(id)) == -1)
179179
goto fail;
180180
btd->transport_codec_id = be32toh(id);

test/mock/Makefile.am

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ bluealsad_mock_CFLAGS = \
6262
@LDAC_ABR_CFLAGS@ \
6363
@LDAC_DEC_CFLAGS@ \
6464
@LDAC_ENC_CFLAGS@ \
65+
@LHDC_DEC_CFLAGS@ \
66+
@LHDC_ENC_CFLAGS@ \
6567
@LIBBSD_CFLAGS@ \
6668
@LIBUNWIND_CFLAGS@ \
6769
@MP3LAME_CFLAGS@ \
@@ -83,6 +85,8 @@ bluealsad_mock_LDADD = \
8385
@LDAC_ABR_LIBS@ \
8486
@LDAC_DEC_LIBS@ \
8587
@LDAC_ENC_LIBS@ \
88+
@LHDC_DEC_LIBS@ \
89+
@LHDC_ENC_LIBS@ \
8690
@LIBUNWIND_LIBS@ \
8791
@MP3LAME_LIBS@ \
8892
@MPG123_LIBS@ \
@@ -124,6 +128,10 @@ if ENABLE_LDAC
124128
bluealsad_mock_SOURCES += ../../src/a2dp-ldac.c
125129
endif
126130

131+
if ENABLE_LHDC
132+
bluealsad_mock_SOURCES += ../../src/a2dp-lhdc.c
133+
endif
134+
127135
if ENABLE_MIDI
128136
bluealsad_mock_SOURCES += \
129137
../../src/ble-midi.c \

test/sndalign.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -92,26 +92,28 @@ int main(int argc, char *argv[]) {
9292
const size_t channels = sf1_info.channels;
9393
const size_t sf1_frames = sf1_info.frames;
9494
const size_t sf2_frames = sf2_info.frames;
95-
const size_t cross_correlation_frames = sf1_frames + sf2_frames;
95+
const size_t min_overlap = MIN(512, MIN(sf1_frames, sf2_frames));
96+
const size_t cross_correlation_frames = sf1_frames + sf2_frames - min_overlap;
9697
long long *cross_correlation = calloc(cross_correlation_frames, sizeof(long long));
97-
size_t min_overlap = MIN(512, MIN(sf1_frames, sf2_frames));
9898

99+
#pragma omp parallel for schedule(dynamic)
99100
for (size_t i = min_overlap; i < cross_correlation_frames; i++) {
100101

101102
size_t sf1_begin = i < sf2_frames ? 0 : i - sf2_frames;
102103
size_t sf2_begin = i < sf2_frames ? sf2_frames - i : 0;
103104
size_t sf1_end = i < sf1_frames ? i : sf1_frames;
104-
105105
const size_t overlap = sf1_end - sf1_begin;
106-
if (overlap < min_overlap)
107-
break;
108106

107+
long long cc_v = 0;
109108
for (size_t j = 0; j < overlap; j++)
110109
for (size_t k = 0; k < channels; k++)
111-
cross_correlation[i] +=
110+
cc_v +=
112111
sf1_data[(sf1_begin + j) * channels + k] *
113112
sf2_data[(sf2_begin + j) * channels + k];
114113

114+
#pragma omp atomic
115+
cross_correlation[i] += cc_v;
116+
115117
}
116118

117119
ssize_t max_i = 0;

test/test-io.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
#if ENABLE_LDAC_IO_TEST
3838
# include <ldacBT.h>
3939
#endif
40+
#if ENABLE_LHDC
41+
# include <lhdcBT.h>
42+
#endif
4043
#if HAVE_SNDFILE
4144
# include <sndfile.h>
4245
#endif
@@ -60,6 +63,9 @@
6063
#if ENABLE_LDAC_IO_TEST
6164
# include "a2dp-ldac.h"
6265
#endif
66+
#if ENABLE_LHDC
67+
# include "a2dp-lhdc.h"
68+
#endif
6369
#if ENABLE_MPEG
6470
# include "a2dp-mpeg.h"
6571
#endif
@@ -81,7 +87,7 @@
8187
#if ENABLE_OFONO
8288
# include "ofono.h"
8389
#endif
84-
#if ENABLE_LC3PLUS || ENABLE_LDAC_IO_TEST
90+
#if ENABLE_LC3PLUS || ENABLE_LDAC_IO_TEST || ENABLE_LHDC
8591
# include "rtp.h"
8692
#endif
8793
#include "storage.h"
@@ -112,6 +118,8 @@ void *a2dp_lc3plus_dec_thread(struct ba_transport_pcm *t_pcm);
112118
void *a2dp_lc3plus_enc_thread(struct ba_transport_pcm *t_pcm);
113119
void *a2dp_ldac_dec_thread(struct ba_transport_pcm *t_pcm);
114120
void *a2dp_ldac_enc_thread(struct ba_transport_pcm *t_pcm);
121+
void *a2dp_lhdc_dec_thread(struct ba_transport_pcm *t_pcm);
122+
void *a2dp_lhdc_enc_thread(struct ba_transport_pcm *t_pcm);
115123
void *a2dp_mp3_enc_thread(struct ba_transport_pcm *t_pcm);
116124
void *a2dp_mpeg_dec_thread(struct ba_transport_pcm *t_pcm);
117125
void *a2dp_opus_dec_thread(struct ba_transport_pcm *t_pcm);
@@ -212,6 +220,13 @@ static const a2dp_ldac_t config_ldac_48000_stereo = {
212220
.channel_mode = LDAC_CHANNEL_MODE_STEREO,
213221
};
214222

223+
__attribute__ ((unused))
224+
static const a2dp_lhdc_v3_t config_lhdc_44100_stereo = {
225+
.info = A2DP_VENDOR_INFO_INIT(LHDC_V3_VENDOR_ID, LHDC_V3_CODEC_ID),
226+
.sampling_freq = LHDC_SAMPLING_FREQ_44100,
227+
.bit_depth = LHDC_BIT_DEPTH_24,
228+
};
229+
215230
__attribute__ ((unused))
216231
static const a2dp_opus_t config_opus_48000_stereo = {
217232
.sampling_freq = OPUS_SAMPLING_FREQ_48000,
@@ -1301,6 +1316,39 @@ CK_START_TEST(test_a2dp_ldac) {
13011316
} CK_END_TEST
13021317
#endif
13031318

1319+
#if ENABLE_LHDC
1320+
CK_START_TEST(test_a2dp_lhdc) {
1321+
1322+
config.lhdc_eqmid = LHDCBT_QUALITY_HIGH;
1323+
1324+
struct ba_transport *t1 = test_transport_new_a2dp(device1,
1325+
BA_TRANSPORT_PROFILE_A2DP_SOURCE, "/path/lhdc", &a2dp_lhdc_source,
1326+
&config_lhdc_44100_stereo);
1327+
struct ba_transport *t2 = test_transport_new_a2dp(device2,
1328+
BA_TRANSPORT_PROFILE_A2DP_SINK, "/path/lhdc", &a2dp_lhdc_sink,
1329+
&config_lhdc_44100_stereo);
1330+
1331+
struct ba_transport_pcm *t1_pcm = &t1->a2dp.pcm;
1332+
struct ba_transport_pcm *t2_pcm = &t2->a2dp.pcm;
1333+
1334+
if (aging_duration) {
1335+
t1->mtu_read = t1->mtu_write = t2->mtu_read = t2->mtu_write =
1336+
RTP_HEADER_LEN + sizeof(rtp_media_header_t) + 990;
1337+
test_io(t1_pcm, t2_pcm, a2dp_lhdc_enc_thread, a2dp_lhdc_dec_thread, 4 * 1024);
1338+
}
1339+
else {
1340+
t1->mtu_read = t1->mtu_write = t2->mtu_read = t2->mtu_write =
1341+
RTP_HEADER_LEN + sizeof(rtp_media_header_t) + 990;
1342+
test_io(t1_pcm, t2_pcm, a2dp_lhdc_enc_thread, test_io_thread_dump_bt, 2 * 1024);
1343+
test_io(t1_pcm, t2_pcm, test_io_thread_dump_pcm, a2dp_lhdc_dec_thread, 2 * 1024);
1344+
}
1345+
1346+
ba_transport_destroy(t1);
1347+
ba_transport_destroy(t2);
1348+
1349+
} CK_END_TEST
1350+
#endif
1351+
13041352
#if ENABLE_OPUS
13051353
CK_START_TEST(test_a2dp_opus) {
13061354

@@ -1324,6 +1372,9 @@ CK_START_TEST(test_a2dp_opus) {
13241372
test_io(t1_pcm, t2_pcm, test_io_thread_dump_pcm, a2dp_opus_dec_thread, 2 * 1024);
13251373
}
13261374

1375+
ba_transport_destroy(t1);
1376+
ba_transport_destroy(t2);
1377+
13271378
} CK_END_TEST
13281379
#endif
13291380

@@ -1437,6 +1488,9 @@ int main(int argc, char *argv[]) {
14371488
#if ENABLE_LDAC_IO_TEST
14381489
{ a2dp_codecs_codec_id_to_string(A2DP_CODEC_VENDOR_ID(LDAC_VENDOR_ID, LDAC_CODEC_ID)), test_a2dp_ldac },
14391490
#endif
1491+
#if ENABLE_LHDC
1492+
{ a2dp_codecs_codec_id_to_string(A2DP_CODEC_VENDOR_ID(LHDC_V3_VENDOR_ID, LHDC_V3_CODEC_ID)), test_a2dp_lhdc },
1493+
#endif
14401494
#if ENABLE_OPUS
14411495
{ a2dp_codecs_codec_id_to_string(A2DP_CODEC_VENDOR_ID(OPUS_VENDOR_ID, OPUS_CODEC_ID)), test_a2dp_opus },
14421496
#endif

0 commit comments

Comments
 (0)