From d075cee8706ae5f1660db588229466d61ce1c36d Mon Sep 17 00:00:00 2001 From: Arkadiusz Bokowy Date: Mon, 3 Aug 2020 19:05:58 +0200 Subject: [PATCH] Link with apt-X/apt-X HD library by pali.rohar Closes #356 --- README.md | 2 + configure.ac | 30 ++- src/Makefile.am | 11 +- src/a2dp-audio.c | 185 ++++++++--------- src/a2dp.c | 9 +- src/bluealsa.c | 2 +- src/bluez.c | 2 +- src/codec-aptx.c | 371 +++++++++++++++++++++++++++++++++++ src/codec-aptx.h | 73 +++++++ src/{msbc.c => codec-msbc.c} | 6 +- src/{msbc.h => codec-msbc.h} | 8 +- src/{sbc.c => codec-sbc.c} | 6 +- src/{sbc.h => codec-sbc.h} | 8 +- src/main.c | 2 +- src/sco.c | 2 +- src/shared/log.c | 4 +- src/utils.c | 24 --- src/utils.h | 6 - test/bluealsa-mock.c | 9 +- test/test-io.c | 15 +- test/test-msbc.c | 2 +- 21 files changed, 597 insertions(+), 180 deletions(-) create mode 100644 src/codec-aptx.c create mode 100644 src/codec-aptx.h rename src/{msbc.c => codec-msbc.c} (98%) rename src/{msbc.h => codec-msbc.h} (93%) rename src/{sbc.c => codec-sbc.c} (97%) rename src/{sbc.h => codec-sbc.h} (79%) diff --git a/README.md b/README.md index ca9304f94..9b6d2f1ce 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ Dependencies: - [fdk-aac](https://github.com/mstorsjo/fdk-aac) (when AAC support is enabled with `--enable-aac`) - [openaptx](https://github.com/Arkq/openaptx) (when apt-X support is enabled with `--enable-aptx` and/or `--enable-aptx-hd`) +- [libopenaptx](https://github.com/pali/libopenaptx) (when apt-X support is enabled and + `--with-libopenaptx` is used) - [libldac](https://github.com/EHfive/ldacBT) (when LDAC support is enabled with `--enable-ldac`) - [docutils](https://docutils.sourceforge.io) (when man pages build is enabled with `--enable-manpages`) diff --git a/configure.ac b/configure.ac index 4bd1077fb..1c5281e54 100644 --- a/configure.ac +++ b/configure.ac @@ -61,7 +61,7 @@ AC_ARG_WITH([libunwind], AM_CONDITIONAL([WITH_LIBUNWIND], [test "x$with_libunwind" = "xyes"]) AM_COND_IF([WITH_LIBUNWIND], [ PKG_CHECK_MODULES([LIBUNWIND], [libunwind >= 1.1]) - AC_DEFINE([ENABLE_LIBUNWIND], [1], [Define to 1 if libunwind shall be used.]) + AC_DEFINE([WITH_LIBUNWIND], [1], [Define to 1 if libunwind shall be used.]) ], [ AC_CHECK_HEADERS([execinfo.h]) ]) @@ -95,11 +95,26 @@ AM_COND_IF([ENABLE_AAC], [ AC_DEFINE([ENABLE_AAC], [1], [Define to 1 if AAC is enabled.]) ]) +AC_ARG_WITH([libopenaptx], + [AS_HELP_STRING([--with-libopenaptx], [use libopenaptx by pali.rohar for apt-X (HD)])]) +AM_CONDITIONAL([WITH_LIBOPENAPTX], [test "x$with_libopenaptx" = "xyes"]) +AM_COND_IF([WITH_LIBOPENAPTX], [ + PKG_CHECK_MODULES([APTX], [libopenaptx >= 0.2.0]) + AC_DEFINE([HAVE_APTX_DECODE], [1], [Define to 1 if you have apt-X decode library.]) + AC_DEFINE([HAVE_APTX_HD_DECODE], [1], [Define to 1 if you have apt-X HD decode library.]) + AC_DEFINE([WITH_LIBOPENAPTX], [1], [Define to 1 if libopenaptx shall be used.]) +]) + AC_ARG_ENABLE([aptx], [AS_HELP_STRING([--enable-aptx], [enable apt-X support])]) AM_CONDITIONAL([ENABLE_APTX], [test "x$enable_aptx" = "xyes"]) AM_COND_IF([ENABLE_APTX], [ - PKG_CHECK_MODULES([APTX], [openaptx >= 1.2.0]) + AM_COND_IF([WITH_LIBOPENAPTX], [], [ + PKG_CHECK_MODULES([APTX], [openaptx >= 1.2.0]) + if test "$($PKG_CONFIG --variable=aptxdecoder openaptx)" = "true"; then + AC_DEFINE([HAVE_APTX_DECODE], [1], [Define to 1 if you have apt-X decode library.]) + fi + ]) AC_DEFINE([ENABLE_APTX], [1], [Define to 1 if apt-X is enabled.]) ]) @@ -107,10 +122,19 @@ AC_ARG_ENABLE([aptx_hd], [AS_HELP_STRING([--enable-aptx-hd], [enable apt-X HD support])]) AM_CONDITIONAL([ENABLE_APTX_HD], [test "x$enable_aptx_hd" = "xyes"]) AM_COND_IF([ENABLE_APTX_HD], [ - PKG_CHECK_MODULES([APTX_HD], [openaptxhd >= 1.2.0]) + AM_COND_IF([WITH_LIBOPENAPTX], [], [ + PKG_CHECK_MODULES([APTX_HD], [openaptxhd >= 1.2.0]) + if test "$($PKG_CONFIG --variable=aptxdecoder openaptxhd)" = "true"; then + AC_DEFINE([HAVE_APTX_HD_DECODE], [1], [Define to 1 if you have apt-X HD decode library.]) + fi + ]) AC_DEFINE([ENABLE_APTX_HD], [1], [Define to 1 if apt-X HD is enabled.]) ]) +# OR-ed conditional which can be used in the Makefile.am +AM_CONDITIONAL([ENABLE_APTX_OR_APTX_HD], [ + test "x$enable_aptx" = "xyes" -o "x$enable_aptx_hd" = "xyes"]) + AC_ARG_ENABLE([ldac], [AS_HELP_STRING([--enable-ldac], [enable LDAC support])]) AM_CONDITIONAL([ENABLE_LDAC], [test "x$enable_ldac" = "xyes"]) diff --git a/src/Makefile.am b/src/Makefile.am index cf97f12fd..6e108b9f2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ # BlueALSA - Makefile.am -# Copyright (c) 2016-2020 Arkadiusz Bokowy +# Copyright (c) 2016-2021 Arkadiusz Bokowy bin_PROGRAMS = bluealsa SUBDIRS = asound @@ -24,16 +24,21 @@ bluealsa_SOURCES = \ bluealsa-iface.c \ bluez.c \ bluez-iface.c \ + codec-sbc.c \ dbus.c \ hci.c \ - sbc.c \ sco.c \ utils.c \ main.c +if ENABLE_APTX_OR_APTX_HD +bluealsa_SOURCES += \ + codec-aptx.c +endif + if ENABLE_MSBC bluealsa_SOURCES += \ - msbc.c + codec-msbc.c endif if ENABLE_OFONO diff --git a/src/a2dp-audio.c b/src/a2dp-audio.c index f1754932d..ef7c7ed63 100644 --- a/src/a2dp-audio.c +++ b/src/a2dp-audio.c @@ -32,9 +32,6 @@ # define AACENCODER_LIB_VERSION LIB_VERSION( \ AACENCODER_LIB_VL0, AACENCODER_LIB_VL1, AACENCODER_LIB_VL2) #endif -#if ENABLE_APTX || ENABLE_APTX_HD -# include -#endif #if ENABLE_MP3LAME # include #endif @@ -51,7 +48,10 @@ #include "a2dp-rtp.h" #include "audio.h" #include "bluealsa.h" -#include "sbc.h" +#if ENABLE_APTX || ENABLE_APTX_HD +# include "codec-aptx.h" +#endif +#include "codec-sbc.h" #include "utils.h" #include "shared/defs.h" #include "shared/ffb.h" @@ -1556,7 +1556,7 @@ static void *a2dp_source_aac(struct ba_transport_thread *th) { } #endif -#if ENABLE_APTX && OPENAPTX_DECODER +#if ENABLE_APTX && HAVE_APTX_DECODE static void *a2dp_sink_aptx(struct ba_transport_thread *th) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); @@ -1569,14 +1569,10 @@ static void *a2dp_sink_aptx(struct ba_transport_thread *th) { }; if (a2dp_validate_bt_sink(t) != 0) - goto fail_open; - - APTXDEC handle = malloc(SizeofAptxbtdec()); - pthread_cleanup_push(PTHREAD_CLEANUP(free), handle); - pthread_cleanup_push(PTHREAD_CLEANUP(aptxbtdec_destroy), handle); + goto fail_init; - if (handle == NULL || - aptxbtdec_init(handle, __BYTE_ORDER == __LITTLE_ENDIAN) != 0) { + HANDLE_APTX handle; + if ((handle = aptxdec_init()) == NULL) { error("Couldn't initialize apt-X decoder: %s", strerror(errno)); goto fail_init; } @@ -1585,8 +1581,11 @@ static void *a2dp_sink_aptx(struct ba_transport_thread *th) { ffb_t pcm = { 0 }; pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &bt); pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &pcm); + pthread_cleanup_push(PTHREAD_CLEANUP(aptxdec_destroy), handle); - if (ffb_init_int16_t(&pcm, t->mtu_read / 4 * 8) == -1 || + /* Note, that we are allocating space for one extra output packed, which is + * required by the aptx_decode_sync() function of libopenaptx library. */ + if (ffb_init_int16_t(&pcm, (t->mtu_read / 4 + 1) * 8) == -1 || ffb_init_uint8_t(&bt, t->mtu_read) == -1) { error("Couldn't create data buffers: %s", strerror(errno)); goto fail_ffb; @@ -1610,28 +1609,23 @@ static void *a2dp_sink_aptx(struct ba_transport_thread *th) { if (t->a2dp.pcm.fd == -1) continue; - uint16_t *input = bt.data; - size_t input_codewords = len / sizeof(uint16_t); + uint8_t *input = bt.data; + size_t input_len = len; ffb_rewind(&pcm); - int16_t *output = pcm.data; + while (input_len >= 4) { - while (input_codewords >= 2) { + size_t decoded = ffb_len_in(&pcm); + ssize_t len; - int32_t pcm_l[4], pcm_r[4]; - if (aptxbtdec_decodestereo(handle, pcm_l, pcm_r, input) != 0) { + if ((len = aptxdec_decode(handle, input, input_len, pcm.tail, &decoded)) <= 0) { error("Apt-X decoding error: %s", strerror(errno)); break; } - input += 2; - input_codewords -= 2; - - ffb_seek(&pcm, 2 * ARRAYSIZE(pcm_l)); - for (size_t i = 0; i < ARRAYSIZE(pcm_l); i++) { - *output++ = pcm_l[i]; - *output++ = pcm_r[i]; - } + input += len; + input_len -= len; + ffb_seek(&pcm, decoded); } @@ -1646,10 +1640,8 @@ static void *a2dp_sink_aptx(struct ba_transport_thread *th) { fail_ffb: pthread_cleanup_pop(1); pthread_cleanup_pop(1); -fail_init: - pthread_cleanup_pop(1); pthread_cleanup_pop(1); -fail_open: +fail_init: pthread_cleanup_pop(1); return NULL; } @@ -1668,10 +1660,8 @@ static void *a2dp_source_aptx(struct ba_transport_thread *th) { .t_locked = !ba_transport_thread_cleanup_lock(th), }; - APTXENC handle = malloc(SizeofAptxbtenc()); - pthread_cleanup_push(PTHREAD_CLEANUP(aptxbtenc_destroy_free), handle); - - if (handle == NULL || aptxbtenc_init(handle, __BYTE_ORDER == __LITTLE_ENDIAN) != 0) { + HANDLE_APTX handle; + if ((handle = aptxenc_init()) == NULL) { error("Couldn't initialize apt-X encoder: %s", strerror(errno)); goto fail_init; } @@ -1680,6 +1670,7 @@ static void *a2dp_source_aptx(struct ba_transport_thread *th) { ffb_t pcm = { 0 }; pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &bt); pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &pcm); + pthread_cleanup_push(PTHREAD_CLEANUP(aptxenc_destroy), handle); const unsigned int channels = t->a2dp.pcm.channels; const size_t aptx_pcm_samples = 4 * channels; @@ -1708,32 +1699,32 @@ static void *a2dp_source_aptx(struct ba_transport_thread *th) { } int16_t *input = pcm.data; - size_t input_len = samples; + size_t input_samples = samples; /* encode and transfer obtained data */ - while (input_len >= aptx_pcm_samples) { + while (input_samples >= aptx_pcm_samples) { size_t output_len = ffb_len_in(&bt); - size_t pcm_frames = 0; + size_t pcm_samples = 0; /* Generate as many apt-X frames as possible to fill the output buffer * without overflowing it. The size of the output buffer is based on * the socket MTU, so such a transfer should be most efficient. */ - while (input_len >= aptx_pcm_samples && output_len >= aptx_code_len) { + while (input_samples >= aptx_pcm_samples && output_len >= aptx_code_len) { - int32_t pcm_l[4] = { input[0], input[2], input[4], input[6] }; - int32_t pcm_r[4] = { input[1], input[3], input[5], input[7] }; + size_t encoded = output_len; + ssize_t len; - if (aptxbtenc_encodestereo(handle, pcm_l, pcm_r, (uint16_t *)bt.tail) != 0) { + if ((len = aptxenc_encode(handle, input, input_samples, bt.tail, &encoded)) <= 0) { error("Apt-X encoding error: %s", strerror(errno)); break; } - input += 4 * channels; - input_len -= 4 * channels; - ffb_seek(&bt, aptx_code_len); - output_len -= aptx_code_len; - pcm_frames += 4; + input += len; + input_samples -= len; + ffb_seek(&bt, encoded); + output_len -= encoded; + pcm_samples += len; } @@ -1743,7 +1734,7 @@ static void *a2dp_source_aptx(struct ba_transport_thread *th) { } /* keep data transfer at a constant bit rate */ - asrsync_sync(&io.asrs, pcm_frames); + asrsync_sync(&io.asrs, pcm_samples / channels); /* update busy delay (encoding overhead) */ t->a2dp.pcm.delay = asrsync_get_busy_usec(&io.asrs) / 100; @@ -1757,7 +1748,7 @@ static void *a2dp_source_aptx(struct ba_transport_thread *th) { * have to append new data to the existing one. Since we do not use * ring buffer, we will simply move unprocessed data to the front * of our linear buffer. */ - ffb_shift(&pcm, samples - input_len); + ffb_shift(&pcm, samples - input_samples); } @@ -1767,14 +1758,14 @@ static void *a2dp_source_aptx(struct ba_transport_thread *th) { fail_ffb: pthread_cleanup_pop(1); pthread_cleanup_pop(1); -fail_init: pthread_cleanup_pop(1); +fail_init: pthread_cleanup_pop(1); return NULL; } #endif -#if ENABLE_APTX_HD && OPENAPTX_DECODER +#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE static void *a2dp_sink_aptx_hd(struct ba_transport_thread *th) { pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); @@ -1788,15 +1779,11 @@ static void *a2dp_sink_aptx_hd(struct ba_transport_thread *th) { }; if (a2dp_validate_bt_sink(t) != 0) - goto fail_open; - - APTXDEC handle = malloc(SizeofAptxbtdec()); - pthread_cleanup_push(PTHREAD_CLEANUP(free), handle); - pthread_cleanup_push(PTHREAD_CLEANUP(aptxhdbtdec_destroy), handle); + goto fail_init; - if (handle == NULL || - aptxhdbtdec_init(handle, false) != 0) { - error("Couldn't initialize apt-X decoder: %s", strerror(errno)); + HANDLE_APTX handle; + if ((handle = aptxhddec_init()) == NULL) { + error("Couldn't initialize apt-X HD decoder: %s", strerror(errno)); goto fail_init; } @@ -1804,8 +1791,11 @@ static void *a2dp_sink_aptx_hd(struct ba_transport_thread *th) { ffb_t pcm = { 0 }; pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &bt); pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &pcm); + pthread_cleanup_push(PTHREAD_CLEANUP(aptxhddec_destroy), handle); - if (ffb_init_int32_t(&pcm, t->mtu_read / 6 * 8) == -1 || + /* Note, that we are allocating space for one extra output packed, which is + * required by the aptx_decode_sync() function of libopenaptx library. */ + if (ffb_init_int32_t(&pcm, (t->mtu_read / 6 + 1) * 8) == -1 || ffb_init_uint8_t(&bt, t->mtu_read) == -1) { error("Couldn't create data buffers: %s", strerror(errno)); goto fail_ffb; @@ -1836,32 +1826,21 @@ static void *a2dp_sink_aptx_hd(struct ba_transport_thread *th) { continue; size_t rtp_payload_len = len - (rtp_payload - (uint8_t *)bt.data); - size_t input_codewords = rtp_payload_len / 3; ffb_rewind(&pcm); - int32_t *output = pcm.data; - - while (input_codewords >= 2) { + while (rtp_payload_len >= 6) { - int32_t pcm_l[4]; - int32_t pcm_r[4]; + size_t decoded = ffb_len_in(&pcm); + ssize_t len; - uint32_t code[2] = { - (rtp_payload[0] << 16) | (rtp_payload[1] << 8) | rtp_payload[2], - (rtp_payload[3] << 16) | (rtp_payload[4] << 8) | rtp_payload[5] }; - if (aptxhdbtdec_decodestereo(handle, pcm_l, pcm_r, code) != 0) { + if ((len = aptxhddec_decode(handle, rtp_payload, rtp_payload_len, pcm.tail, &decoded)) <= 0) { error("Apt-X decoding error: %s", strerror(errno)); break; } - rtp_payload += 6; - input_codewords -= 2; - - ffb_seek(&pcm, 2 * ARRAYSIZE(pcm_l)); - for (size_t i = 0; i < ARRAYSIZE(pcm_l); i++) { - *output++ = pcm_l[i]; - *output++ = pcm_r[i]; - } + rtp_payload += len; + rtp_payload_len -= len; + ffb_seek(&pcm, decoded); } @@ -1876,10 +1855,8 @@ static void *a2dp_sink_aptx_hd(struct ba_transport_thread *th) { fail_ffb: pthread_cleanup_pop(1); pthread_cleanup_pop(1); -fail_init: - pthread_cleanup_pop(1); pthread_cleanup_pop(1); -fail_open: +fail_init: pthread_cleanup_pop(1); return NULL; } @@ -1898,10 +1875,8 @@ static void *a2dp_source_aptx_hd(struct ba_transport_thread *th) { .t_locked = !ba_transport_thread_cleanup_lock(th), }; - APTXENC handle = malloc(SizeofAptxhdbtenc()); - pthread_cleanup_push(PTHREAD_CLEANUP(aptxhdbtenc_destroy_free), handle); - - if (handle == NULL || aptxhdbtenc_init(handle, false) != 0) { + HANDLE_APTX handle; + if ((handle = aptxhdenc_init()) == NULL) { error("Couldn't initialize apt-X HD encoder: %s", strerror(errno)); goto fail_init; } @@ -1910,6 +1885,7 @@ static void *a2dp_source_aptx_hd(struct ba_transport_thread *th) { ffb_t pcm = { 0 }; pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &bt); pthread_cleanup_push(PTHREAD_CLEANUP(ffb_free), &pcm); + pthread_cleanup_push(PTHREAD_CLEANUP(aptxhdenc_destroy), handle); const unsigned int channels = t->a2dp.pcm.channels; const unsigned int samplerate = t->a2dp.pcm.sampling; @@ -1946,43 +1922,35 @@ static void *a2dp_source_aptx_hd(struct ba_transport_thread *th) { } int32_t *input = pcm.data; - size_t input_len = samples; + size_t input_samples = samples; /* encode and transfer obtained data */ - while (input_len >= aptx_pcm_samples) { + while (input_samples >= aptx_pcm_samples) { /* anchor for RTP payload */ bt.tail = rtp_payload; size_t output_len = ffb_len_in(&bt); - size_t pcm_frames = 0; + size_t pcm_samples = 0; /* Generate as many apt-X frames as possible to fill the output buffer * without overflowing it. The size of the output buffer is based on * the socket MTU, so such a transfer should be most efficient. */ - while (input_len >= aptx_pcm_samples && output_len >= aptx_code_len) { + while (input_samples >= aptx_pcm_samples && output_len >= aptx_code_len) { - int32_t pcm_l[4] = { input[0], input[2], input[4], input[6] }; - int32_t pcm_r[4] = { input[1], input[3], input[5], input[7] }; - uint32_t code[2]; + size_t encoded = output_len; + ssize_t len; - if (aptxhdbtenc_encodestereo(handle, pcm_l, pcm_r, code) != 0) { + if ((len = aptxhdenc_encode(handle, input, input_samples, bt.tail, &encoded)) <= 0) { error("Apt-X HD encoding error: %s", strerror(errno)); break; } - ((uint8_t *)bt.tail)[0] = code[0] >> 16; - ((uint8_t *)bt.tail)[1] = code[0] >> 8; - ((uint8_t *)bt.tail)[2] = code[0]; - ((uint8_t *)bt.tail)[3] = code[1] >> 16; - ((uint8_t *)bt.tail)[4] = code[1] >> 8; - ((uint8_t *)bt.tail)[5] = code[1]; - - input += 4 * channels; - input_len -= 4 * channels; - ffb_seek(&bt, aptx_code_len); - output_len -= aptx_code_len; - pcm_frames += 4; + input += len; + input_samples -= len; + ffb_seek(&bt, encoded); + output_len -= encoded; + pcm_samples += len; } @@ -1992,6 +1960,7 @@ static void *a2dp_source_aptx_hd(struct ba_transport_thread *th) { } /* keep data transfer at a constant bit rate */ + unsigned int pcm_frames = pcm_samples / channels; asrsync_sync(&io.asrs, pcm_frames); timestamp += pcm_frames * 10000 / samplerate; @@ -2010,7 +1979,7 @@ static void *a2dp_source_aptx_hd(struct ba_transport_thread *th) { * have to append new data to the existing one. Since we do not use * ring buffer, we will simply move unprocessed data to the front * of our linear buffer. */ - ffb_shift(&pcm, samples - input_len); + ffb_shift(&pcm, samples - input_samples); } @@ -2020,8 +1989,8 @@ static void *a2dp_source_aptx_hd(struct ba_transport_thread *th) { fail_ffb: pthread_cleanup_pop(1); pthread_cleanup_pop(1); -fail_init: pthread_cleanup_pop(1); +fail_init: pthread_cleanup_pop(1); return NULL; } @@ -2405,11 +2374,11 @@ int a2dp_audio_thread_create(struct ba_transport *t) { case A2DP_CODEC_MPEG24: return ba_transport_thread_create(th, a2dp_sink_aac, "ba-a2dp-aac"); #endif -#if ENABLE_APTX && OPENAPTX_DECODER +#if ENABLE_APTX && HAVE_APTX_DECODE case A2DP_CODEC_VENDOR_APTX: return ba_transport_thread_create(th, a2dp_sink_aptx, "ba-a2dp-aptx"); #endif -#if ENABLE_APTX_HD && OPENAPTX_DECODER +#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE case A2DP_CODEC_VENDOR_APTX_HD: return ba_transport_thread_create(th, a2dp_sink_aptx_hd, "ba-a2dp-aptx-hd"); #endif diff --git a/src/a2dp.c b/src/a2dp.c index 30ee442cc..3bdbf923a 100644 --- a/src/a2dp.c +++ b/src/a2dp.c @@ -15,14 +15,11 @@ #include #include -#if ENABLE_APTX || ENABLE_APTX_HD -# include -#endif #include "a2dp-codecs.h" #include "bluealsa.h" +#include "codec-sbc.h" #include "hci.h" -#include "sbc.h" #include "shared/defs.h" #include "shared/log.h" @@ -474,13 +471,13 @@ const struct a2dp_codec *a2dp_codecs[] = { #endif #if ENABLE_APTX_HD &a2dp_codec_source_aptx_hd, -# if OPENAPTX_DECODER +# if HAVE_APTX_HD_DECODE &a2dp_codec_sink_aptx_hd, # endif #endif #if ENABLE_APTX &a2dp_codec_source_aptx, -# if OPENAPTX_DECODER +# if HAVE_APTX_DECODE &a2dp_codec_sink_aptx, # endif #endif diff --git a/src/bluealsa.c b/src/bluealsa.c index 0dcee9ef1..de544b79b 100644 --- a/src/bluealsa.c +++ b/src/bluealsa.c @@ -17,8 +17,8 @@ # include #endif +#include "codec-sbc.h" #include "hfp.h" -#include "sbc.h" /* Initialize global configuration variable. */ struct ba_config config = { diff --git a/src/bluez.c b/src/bluez.c index 7f6e28b4a..691aa830c 100644 --- a/src/bluez.c +++ b/src/bluez.c @@ -36,9 +36,9 @@ #include "bluealsa.h" #include "bluealsa-dbus.h" #include "bluez-iface.h" +#include "codec-sbc.h" #include "dbus.h" #include "hci.h" -#include "sbc.h" #include "sco.h" #include "utils.h" #include "shared/defs.h" diff --git a/src/codec-aptx.c b/src/codec-aptx.c new file mode 100644 index 000000000..28429cd4a --- /dev/null +++ b/src/codec-aptx.c @@ -0,0 +1,371 @@ +/* + * BlueALSA - codec-aptx.c + * Copyright (c) 2016-2021 Arkadiusz Bokowy + * + * This file is a part of bluez-alsa. + * + * This project is licensed under the terms of the MIT license. + * + */ + +#include "codec-aptx.h" + +#include +#include +#include + +#include + +#include "shared/defs.h" +#include "shared/log.h" + +#if ENABLE_APTX +/** + * Initialize apt-X encoder handler. + * + * @returns On success, this function returns initialized apt-X encoder + * handler. On error, NULL is returned. */ +HANDLE_APTX aptxenc_init(void) { +#if WITH_LIBOPENAPTX + return aptx_init(0); +#else + APTXENC handle; + if ((handle = malloc(SizeofAptxbtenc())) == NULL || + aptxbtenc_init(handle, __BYTE_ORDER == __LITTLE_ENDIAN) != 0) { + free(handle); + return NULL; + } + return handle; +#endif +} +#endif + +#if ENABLE_APTX && HAVE_APTX_DECODE +/** + * Initialize apt-X decoder handler. + * + * @returns On success, this function returns initialized apt-X decoder + * handler. On error, NULL is returned. */ +HANDLE_APTX aptxdec_init(void) { +#if WITH_LIBOPENAPTX + return aptx_init(0); +#else + APTXDEC handle; + if ((handle = malloc(SizeofAptxbtdec())) == NULL || + aptxbtdec_init(handle, __BYTE_ORDER == __LITTLE_ENDIAN) != 0) { + free(handle); + return NULL; + } + return handle; +#endif +} +#endif + +#if ENABLE_APTX_HD +/** + * Initialize apt-X HD encoder handler. + * + * @returns On success, this function returns initialized apt-X encoder + * handler. On error, NULL is returned. */ +HANDLE_APTX aptxhdenc_init(void) { +#if WITH_LIBOPENAPTX + return aptx_init(1); +#else + APTXENC handle; + if ((handle = malloc(SizeofAptxhdbtenc())) == NULL || + aptxhdbtenc_init(handle, false) != 0) { + free(handle); + return NULL; + } + return handle; +#endif +} +#endif + +#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE +/** + * Initialize apt-X HD decoder handler. + * + * @returns On success, this function returns initialized apt-X decoder + * handler. On error, NULL is returned. */ +HANDLE_APTX aptxhddec_init(void) { +#if WITH_LIBOPENAPTX + return aptx_init(1); +#else + APTXDEC handle; + if ((handle = malloc(SizeofAptxhdbtdec())) == NULL || + aptxhdbtdec_init(handle, false) != 0) { + free(handle); + return NULL; + } + return handle; +#endif +} +#endif + +#if ENABLE_APTX +/** + * Encode stereo PCM. + * + * @returns On success, this function returns the number of processed input + * samples. On error, -1 is returned. */ +ssize_t aptxenc_encode(HANDLE_APTX handle, const int16_t *input, size_t samples, + void *output, size_t *len) { + + if (samples < 8 || *len < 4) + return errno = EINVAL, -1; + +#if WITH_LIBOPENAPTX + + const uint8_t pcm[3 /* 24bit */ * 8 /* 4 samples * 2 channels */] = { + 0, input[0], input[0] >> 8, 0, input[1], input[1] >> 8, + 0, input[2], input[2] >> 8, 0, input[3], input[3] >> 8, + 0, input[4], input[4] >> 8, 0, input[5], input[5] >> 8, + 0, input[6], input[6] >> 8, 0, input[7], input[7] >> 8, + }; + + size_t rv; + if ((rv = aptx_encode(handle, pcm, sizeof(pcm), output, *len, len)) != sizeof(pcm)) + return -1; + + return rv / 3; + +#else + + int32_t pcm_l[4] = { input[0], input[2], input[4], input[6] }; + int32_t pcm_r[4] = { input[1], input[3], input[5], input[7] }; + + if (aptxbtenc_encodestereo(handle, pcm_l, pcm_r, output) != 0) + return -1; + + *len = 4; + return 8; + +#endif +} +#endif + +#if ENABLE_APTX && HAVE_APTX_DECODE +/** + * Decode stereo PCM. + * + * @returns On success, this function returns the number of processed input + * bytes. On error, -1 is returned. */ +ssize_t aptxdec_decode(HANDLE_APTX handle, const void *input, size_t len, + int16_t *output, size_t *samples) { + + if (len < 4 || *samples < 8) + return errno = EINVAL, -1; + +#if WITH_LIBOPENAPTX + + uint8_t pcm[3 /* 24bit */ * 8 /* 4 samples * 2 channels */ * 2]; + size_t written, dropped; + int synced; + + if ((len = aptx_decode_sync(handle, input, 4, pcm, sizeof(pcm), + &written, &synced, &dropped)) != 4) + return -1; + + if (!synced) + info("Apt-X stream out of sync: Dropped bytes: %zd", dropped); + + size_t i; + for (i = 0; i < written / 3 / 2; i++) { + *output++ = pcm[i * 6 + 0 + 1] | (pcm[i * 6 + 0 + 2] << 8); + *output++ = pcm[i * 6 + 3 + 1] | (pcm[i * 6 + 3 + 2] << 8); + } + + *samples = written / 3; + return len; + +#else + + int32_t pcm_l[4], pcm_r[4]; + if (aptxbtdec_decodestereo(handle, pcm_l, pcm_r, input) != 0) + return -1; + + size_t i; + for (i = 0; i < ARRAYSIZE(pcm_l); i++) { + *output++ = pcm_l[i]; + *output++ = pcm_r[i]; + } + + *samples = 8; + return 4; + +#endif +} +#endif + +#if ENABLE_APTX_HD +/** + * Encode stereo PCM (HD variant). + * + * @returns On success, this function returns the number of processed input + * samples. On error, -1 is returned. */ +ssize_t aptxhdenc_encode(HANDLE_APTX handle, const int32_t *input, size_t samples, + void *output, size_t *len) { + + if (samples < 8 || *len < 6) + return errno = EINVAL, -1; + +#if WITH_LIBOPENAPTX + + const uint8_t pcm[3 /* 24bit */ * 8 /* 4 samples * 2 channels */] = { + input[0], input[0] >> 8, input[0] >> 16, input[1], input[1] >> 8, input[1] >> 16, + input[2], input[2] >> 8, input[2] >> 16, input[3], input[3] >> 8, input[3] >> 16, + input[4], input[4] >> 8, input[4] >> 16, input[5], input[5] >> 8, input[5] >> 16, + input[6], input[6] >> 8, input[6] >> 16, input[7], input[7] >> 8, input[7] >> 16, + }; + + size_t rv; + if ((rv = aptx_encode(handle, pcm, sizeof(pcm), output, *len, len)) != sizeof(pcm)) + return -1; + + return rv / 3; + +#else + + int32_t pcm_l[4] = { input[0], input[2], input[4], input[6] }; + int32_t pcm_r[4] = { input[1], input[3], input[5], input[7] }; + uint32_t code[2]; + + if (aptxhdbtenc_encodestereo(handle, pcm_l, pcm_r, code) != 0) + return -1; + + ((uint8_t *)output)[0] = code[0] >> 16; + ((uint8_t *)output)[1] = code[0] >> 8; + ((uint8_t *)output)[2] = code[0]; + ((uint8_t *)output)[3] = code[1] >> 16; + ((uint8_t *)output)[4] = code[1] >> 8; + ((uint8_t *)output)[5] = code[1]; + + *len = 6; + return 8; + +#endif +} +#endif + +#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE +/** + * Decode stereo PCM (HD variant). + * + * @returns On success, this function returns the number of processed input + * bytes. On error, -1 is returned. */ +ssize_t aptxhddec_decode(HANDLE_APTX handle, const void *input, size_t len, + int32_t *output, size_t *samples) { + + if (len < 6 || *samples < 8) + return errno = EINVAL, -1; + +#if WITH_LIBOPENAPTX + + uint8_t pcm[3 /* 24bit */ * 8 /* 4 samples * 2 channels */ * 2]; + size_t written, dropped; + int synced; + + if ((len = aptx_decode_sync(handle, input, 6, pcm, sizeof(pcm), + &written, &synced, &dropped)) != 6) + return -1; + + if (!synced) + info("Apt-X HD stream out of sync: Dropped bytes: %zd", dropped); + + size_t i; + int32_t base; + for (i = 0; i < written / 3 / 2; i++) { + base = pcm[i * 6 + 0 + 2] & 0x80 ? 0xFF000000 : 0; + *output++ = base | pcm[i * 6 + 0 + 0] | (pcm[i * 6 + 0 + 1] << 8) | (pcm[i * 6 + 0 + 2] << 16); + base = pcm[i * 6 + 3 + 2] & 0x80 ? 0xFF000000 : 0; + *output++ = base | pcm[i * 6 + 3 + 0] | (pcm[i * 6 + 3 + 1] << 8) | (pcm[i * 6 + 3 + 2] << 16); + } + + *samples = written / 3; + return len; + +#else + + const uint32_t code[2] = { + (((uint8_t *)input)[0] << 16) | (((uint8_t *)input)[1] << 8) | ((uint8_t *)input)[2], + (((uint8_t *)input)[3] << 16) | (((uint8_t *)input)[4] << 8) | ((uint8_t *)input)[5] }; + int32_t pcm_l[4], pcm_r[4]; + + if (aptxhdbtdec_decodestereo(handle, pcm_l, pcm_r, code) != 0) + return -1; + + size_t i; + for (i = 0; i < ARRAYSIZE(pcm_l); i++) { + *output++ = pcm_l[i]; + *output++ = pcm_r[i]; + } + + *samples = 8; + return 6; + +#endif +} +#endif + +#if ENABLE_APTX +/** + * Destroy apt-X encoder and free handler. + * + * @param handle Initialized encoder handler. */ +void aptxenc_destroy(HANDLE_APTX handle) { +#if WITH_LIBOPENAPTX + aptx_finish(handle); +#else + if (aptxbtenc_destroy != NULL) + aptxbtenc_destroy(handle); + free(handle); +#endif +} +#endif + +#if ENABLE_APTX && HAVE_APTX_DECODE +/** + * Destroy apt-X decoder and free handler. + * + * @param handle Initialized decoder handler. */ +void aptxdec_destroy(HANDLE_APTX handle) { +#if WITH_LIBOPENAPTX + aptx_finish(handle); +#else + aptxbtdec_destroy(handle); + free(handle); +#endif +} +#endif + +#if ENABLE_APTX_HD +/** + * Destroy apt-X HD encoder and free handler. + * + * @param handle Initialized encoder handler. */ +void aptxhdenc_destroy(HANDLE_APTX handle) { +#if WITH_LIBOPENAPTX + aptx_finish(handle); +#else + if (aptxhdbtenc_destroy != NULL) + aptxhdbtenc_destroy(handle); + free(handle); +#endif +} +#endif + +#if ENABLE_APTX_HD && HAVE_APTX_HD_DECODE +/** + * Destroy apt-X HD decoder and free handler. + * + * @param handle Initialized decoder handler. */ +void aptxhddec_destroy(HANDLE_APTX handle) { +#if WITH_LIBOPENAPTX + aptx_finish(handle); +#else + aptxhdbtdec_destroy(handle); + free(handle); +#endif +} +#endif diff --git a/src/codec-aptx.h b/src/codec-aptx.h new file mode 100644 index 000000000..b88e2ac06 --- /dev/null +++ b/src/codec-aptx.h @@ -0,0 +1,73 @@ +/* + * BlueALSA - codec-aptx.h + * Copyright (c) 2016-2021 Arkadiusz Bokowy + * + * This file is a part of bluez-alsa. + * + * This project is licensed under the terms of the MIT license. + * + */ + +#ifndef BLUEALSA_CODECAPTX_H_ +#define BLUEALSA_CODECAPTX_H_ + +#if HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +/** + * Opaque apt-X encoder/decoder handle. */ +typedef void * HANDLE_APTX; + +#if ENABLE_APTX +HANDLE_APTX aptxenc_init(void); +# if HAVE_APTX_DECODE +HANDLE_APTX aptxdec_init(void); +# endif +#endif + +#if ENABLE_APTX_HD +HANDLE_APTX aptxhdenc_init(void); +# if HAVE_APTX_HD_DECODE +HANDLE_APTX aptxhddec_init(void); +# endif +#endif + +#if ENABLE_APTX +ssize_t aptxenc_encode(HANDLE_APTX handle, const int16_t *input, size_t samples, + void *output, size_t *len); +# if HAVE_APTX_DECODE +ssize_t aptxdec_decode(HANDLE_APTX handle, const void *input, size_t len, + int16_t *output, size_t *samples); +# endif +#endif + +#if ENABLE_APTX_HD +ssize_t aptxhdenc_encode(HANDLE_APTX handle, const int32_t *input, size_t samples, + void *output, size_t *len); +# if HAVE_APTX_HD_DECODE +ssize_t aptxhddec_decode(HANDLE_APTX handle, const void *input, size_t len, + int32_t *output, size_t *samples); +# endif +#endif + +#if ENABLE_APTX +void aptxenc_destroy(HANDLE_APTX handle); +# if HAVE_APTX_DECODE +void aptxdec_destroy(HANDLE_APTX handle); +# endif +#endif + +#if ENABLE_APTX_HD +void aptxhdenc_destroy(HANDLE_APTX handle); +# if HAVE_APTX_HD_DECODE +void aptxhddec_destroy(HANDLE_APTX handle); +# endif +#endif + + +#endif diff --git a/src/msbc.c b/src/codec-msbc.c similarity index 98% rename from src/msbc.c rename to src/codec-msbc.c index 0d2808333..496f7550d 100644 --- a/src/msbc.c +++ b/src/codec-msbc.c @@ -1,6 +1,6 @@ /* - * BlueALSA - msbc.c - * Copyright (c) 2016-2020 Arkadiusz Bokowy + * BlueALSA - codec-msbc.c + * Copyright (c) 2016-2021 Arkadiusz Bokowy * 2017 Juha Kuikka * * This file is a part of bluez-alsa. @@ -9,7 +9,7 @@ * */ -#include "msbc.h" +#include "codec-msbc.h" #include #include diff --git a/src/msbc.h b/src/codec-msbc.h similarity index 93% rename from src/msbc.h rename to src/codec-msbc.h index 5bd6bcebf..abf0d72f3 100644 --- a/src/msbc.h +++ b/src/codec-msbc.h @@ -1,6 +1,6 @@ /* - * BlueALSA - msbc.h - * Copyright (c) 2016-2019 Arkadiusz Bokowy + * BlueALSA - codec-msbc.h + * Copyright (c) 2016-2021 Arkadiusz Bokowy * * This file is a part of bluez-alsa. * @@ -8,8 +8,8 @@ * */ -#ifndef BLUEALSA_MSBC_H_ -#define BLUEALSA_MSBC_H_ +#ifndef BLUEALSA_CODECMSBC_H_ +#define BLUEALSA_CODECMSBC_H_ #if HAVE_CONFIG_H # include diff --git a/src/sbc.c b/src/codec-sbc.c similarity index 97% rename from src/sbc.c rename to src/codec-sbc.c index dfdcbeea1..698ffdb8a 100644 --- a/src/sbc.c +++ b/src/codec-sbc.c @@ -1,6 +1,6 @@ /* - * BlueALSA - sbc.c - * Copyright (c) 2016-2020 Arkadiusz Bokowy + * BlueALSA - codec-sbc.c + * Copyright (c) 2016-2021 Arkadiusz Bokowy * * This file is a part of bluez-alsa. * @@ -8,7 +8,7 @@ * */ -#include "sbc.h" +#include "codec-sbc.h" #include #include diff --git a/src/sbc.h b/src/codec-sbc.h similarity index 79% rename from src/sbc.h rename to src/codec-sbc.h index a05fde864..3aae18282 100644 --- a/src/sbc.h +++ b/src/codec-sbc.h @@ -1,6 +1,6 @@ /* - * BlueALSA - sbc.h - * Copyright (c) 2016-2020 Arkadiusz Bokowy + * BlueALSA - codec-sbc.h + * Copyright (c) 2016-2021 Arkadiusz Bokowy * * This file is a part of bluez-alsa. * @@ -8,8 +8,8 @@ * */ -#ifndef BLUEALSA_SBC_H_ -#define BLUEALSA_SBC_H_ +#ifndef BLUEALSA_CODECSBC_H_ +#define BLUEALSA_CODECSBC_H_ #if HAVE_CONFIG_H # include diff --git a/src/main.c b/src/main.c index ea21626a2..f1b5182df 100644 --- a/src/main.c +++ b/src/main.c @@ -34,10 +34,10 @@ #include "bluealsa-dbus.h" #include "bluealsa-iface.h" #include "bluez.h" +#include "codec-sbc.h" #if ENABLE_OFONO # include "ofono.h" #endif -#include "sbc.h" #include "utils.h" #if ENABLE_UPOWER # include "upower.h" diff --git a/src/sco.c b/src/sco.c index a9f328a1e..eb59eec2e 100644 --- a/src/sco.c +++ b/src/sco.c @@ -27,9 +27,9 @@ #include "a2dp-audio.h" #include "ba-device.h" #include "bluealsa.h" +#include "codec-msbc.h" #include "hci.h" #include "hfp.h" -#include "msbc.h" #include "utils.h" #include "shared/defs.h" #include "shared/ffb.h" diff --git a/src/shared/log.c b/src/shared/log.c index e5c8569c1..98ea9ef5b 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -19,7 +19,7 @@ #include #include -#if ENABLE_LIBUNWIND +#if WITH_LIBUNWIND # define UNW_LOCAL_ONLY # include #elif HAVE_EXECINFO_H @@ -110,7 +110,7 @@ void callstackdump(const char *label) { char buffer[1024 * 2] = "Call stack backtrace not supported"; char *ptr = buffer; -#if ENABLE_LIBUNWIND +#if WITH_LIBUNWIND unw_cursor_t cursor; unw_context_t context; diff --git a/src/utils.c b/src/utils.c index d2fa8f3e1..5549f9d9a 100644 --- a/src/utils.c +++ b/src/utils.c @@ -573,30 +573,6 @@ const char *aacenc_strerror(AACENC_ERROR err) { } #endif -#if ENABLE_APTX -/** - * Destroy apt-X encoder and free handler. - * - * @param enc Initialized encoder handler. */ -void aptxbtenc_destroy_free(APTXENC enc) { - if (aptxbtenc_destroy != NULL) - aptxbtenc_destroy(enc); - free(enc); -} -#endif - -#if ENABLE_APTX_HD -/** - * Destroy apt-X HD encoder and free handler. - * - * @param enc Initialized encoder handler. */ -void aptxhdbtenc_destroy_free(APTXENC enc) { - if (aptxhdbtenc_destroy != NULL) - aptxhdbtenc_destroy(enc); - free(enc); -} -#endif - #if ENABLE_LDAC /** * Get string representation of the LDAC error code. diff --git a/src/utils.h b/src/utils.h index 5efd20377..e475eb035 100644 --- a/src/utils.h +++ b/src/utils.h @@ -54,12 +54,6 @@ const char *aacdec_strerror(AAC_DECODER_ERROR err); const char *aacenc_strerror(AACENC_ERROR err); #endif -#if ENABLE_APTX || ENABLE_APTX_HD -# include -void aptxbtenc_destroy_free(APTXENC enc); -void aptxhdbtenc_destroy_free(APTXENC enc); -#endif - #if ENABLE_LDAC const char *ldacBT_strerror(int err); #endif diff --git a/test/bluealsa-mock.c b/test/bluealsa-mock.c index 6d7542c34..e099f48bc 100644 --- a/test/bluealsa-mock.c +++ b/test/bluealsa-mock.c @@ -1,6 +1,6 @@ /* * bluealsa-mock.c - * Copyright (c) 2016-2020 Arkadiusz Bokowy + * Copyright (c) 2016-2021 Arkadiusz Bokowy * * This file is a part of bluez-alsa. * @@ -46,10 +46,13 @@ #include "../src/bluealsa-dbus.c" #include "../src/bluealsa-iface.c" #include "../src/bluealsa.c" +#if ENABLE_APTX || ENABLE_APTX_HD +# include "../src/codec-aptx.c" +#endif +#include "../src/codec-msbc.c" +#include "../src/codec-sbc.c" #include "../src/dbus.c" #include "../src/hci.c" -#include "../src/msbc.c" -#include "../src/sbc.c" #include "../src/sco.c" #include "../src/utils.c" #include "../src/shared/ffb.c" diff --git a/test/test-io.c b/test/test-io.c index 09de63931..445a6534f 100644 --- a/test/test-io.c +++ b/test/test-io.c @@ -26,10 +26,13 @@ #include "../src/ba-device.c" #include "../src/ba-transport.c" #include "../src/bluealsa.c" +#if ENABLE_APTX || ENABLE_APTX_HD +# include "../src/codec-aptx.c" +#endif +#include "../src/codec-msbc.c" +#include "../src/codec-sbc.c" #include "../src/dbus.c" #include "../src/hci.c" -#include "../src/msbc.c" -#include "../src/sbc.c" #include "../src/sco.c" #include "../src/utils.c" #include "../src/shared/ffb.c" @@ -514,7 +517,7 @@ START_TEST(test_a2dp_aptx) { t1->release = t2->release = test_transport_release_bt_a2dp; if (aging_duration) { -#if OPENAPTX_DECODER +#if HAVE_APTX_DECODE t1->mtu_write = t2->mtu_read = 400; test_a2dp(t1, t2, a2dp_source_aptx, a2dp_sink_aptx); #endif @@ -522,7 +525,7 @@ START_TEST(test_a2dp_aptx) { else { t1->mtu_write = t2->mtu_read = 40; test_a2dp(t1, t2, a2dp_source_aptx, test_io_thread_a2dp_dump_bt); -#if OPENAPTX_DECODER +#if HAVE_APTX_DECODE test_a2dp(t1, t2, test_io_thread_a2dp_dump_pcm, a2dp_sink_aptx); #endif }; @@ -545,7 +548,7 @@ START_TEST(test_a2dp_aptx_hd) { t1->release = t2->release = test_transport_release_bt_a2dp; if (aging_duration) { -#if OPENAPTX_DECODER +#if HAVE_APTX_HD_DECODE t1->mtu_write = t2->mtu_read = 600; test_a2dp(t1, t2, a2dp_source_aptx_hd, a2dp_sink_aptx_hd); #endif @@ -553,7 +556,7 @@ START_TEST(test_a2dp_aptx_hd) { else { t1->mtu_write = t2->mtu_read = 60; test_a2dp(t1, t2, a2dp_source_aptx_hd, test_io_thread_a2dp_dump_bt); -#if OPENAPTX_DECODER +#if HAVE_APTX_HD_DECODE test_a2dp(t1, t2, test_io_thread_a2dp_dump_pcm, a2dp_sink_aptx_hd); #endif }; diff --git a/test/test-msbc.c b/test/test-msbc.c index 394713310..55d412b80 100644 --- a/test/test-msbc.c +++ b/test/test-msbc.c @@ -11,7 +11,7 @@ #include #include "inc/sine.inc" -#include "../src/msbc.c" +#include "../src/codec-msbc.c" #include "../src/shared/defs.h" #include "../src/shared/ffb.c" #include "../src/shared/log.c"