14930cef6SMatthias Ringwald# Low Complexity Communication Codec (LC3) 24930cef6SMatthias Ringwald 3*6897da5cSDirk HelbigLC3 and LC3 Plus are audio codecs designed for low-latency audio transport. 44930cef6SMatthias Ringwald 5*6897da5cSDirk Helbig- LC3 is specified by [_the Bluetooth Special Interset Group for the LE Audio 6*6897da5cSDirk Helbig protocol_](https://www.bluetooth.org/DocMan/handlers/DownloadDoc.ashx?doc_id=502107&vId=542963) 7*6897da5cSDirk Helbig 8*6897da5cSDirk Helbig- LC3 Plus is defined by [_ETSI TS 103 634_](https://www.etsi.org/deliver/etsi_ts/103600_103699/103634/01.04.01_60/ts_103634v010401p.pdf) 9*6897da5cSDirk Helbig 10*6897da5cSDirk HelbigIn addition to LC3, following features of LC3 Plus are proposed: 11*6897da5cSDirk Helbig- Frame duration of 2.5 and 5ms. 12*6897da5cSDirk Helbig- High-Resolution mode, 48 KHz, and 96 kHz sampling rates. 134930cef6SMatthias Ringwald 144930cef6SMatthias Ringwald## Overview 154930cef6SMatthias Ringwald 164930cef6SMatthias RingwaldThe directory layout is as follows : 174930cef6SMatthias Ringwald- include: Library interface 184930cef6SMatthias Ringwald- src: Source files 194930cef6SMatthias Ringwald- tools: Standalone encoder/decoder tools 20*6897da5cSDirk Helbig- python: Python wrapper 21*6897da5cSDirk Helbig- test: Unit testing framework 22*6897da5cSDirk Helbig- fuzz: Roundtrip fuzz testing harness 234930cef6SMatthias Ringwald- build: Building outputs 244930cef6SMatthias Ringwald- bin: Compilation output 254930cef6SMatthias Ringwald 264930cef6SMatthias Ringwald## How to build 274930cef6SMatthias Ringwald 284930cef6SMatthias RingwaldThe default toolchain used is GCC. Invoke `make` to build the library. 294930cef6SMatthias Ringwald 304930cef6SMatthias Ringwald```sh 314930cef6SMatthias Ringwald$ make -j 324930cef6SMatthias Ringwald``` 334930cef6SMatthias Ringwald 34*6897da5cSDirk HelbigCompiled library `liblc3.so` will be found in `bin` directory. 35*6897da5cSDirk Helbig 36*6897da5cSDirk HelbigLC3 Plus features can be selectively disabled : 37*6897da5cSDirk Helbig- `LC3_PLUS=0` disable the support of 2.5ms and 5ms frame durations. 38*6897da5cSDirk Helbig- `LC3_PLUS_HR=0` turns off the support of the High-Resolution mode. 39*6897da5cSDirk Helbig 40*6897da5cSDirk HelbigOnly Bluetooth LC3 features will be included using the following command: 41*6897da5cSDirk Helbig 42*6897da5cSDirk Helbig```sh 43*6897da5cSDirk Helbig$ make LC3_PLUS=0 LC3_PLUS_HR=0 -j 44*6897da5cSDirk Helbig``` 454930cef6SMatthias Ringwald 464930cef6SMatthias Ringwald#### Cross compilation 474930cef6SMatthias Ringwald 484930cef6SMatthias RingwaldThe cc, as, ld and ar can be selected with respective Makefile variables `CC`, 494930cef6SMatthias Ringwald`AS`, `LD` and `AR`. The `AS` and `LD` selections are optionnal, and fallback 504930cef6SMatthias Ringwaldto `CC` selection when not defined. 514930cef6SMatthias Ringwald 524930cef6SMatthias RingwaldThe `LIBC` must be set to `bionic` for android cross-compilation. This switch 534930cef6SMatthias Ringwaldprevent link with `pthread` and `rt` libraries, that is included in the 544930cef6SMatthias Ringwaldbionic libc. 554930cef6SMatthias Ringwald 564930cef6SMatthias RingwaldFollowing example build for android, using NDK toolset. 574930cef6SMatthias Ringwald 584930cef6SMatthias Ringwald```sh 594930cef6SMatthias Ringwald$ make -j CC=path_to_android_ndk_prebuilt/toolchain-prefix-clang LIBC=bionic 604930cef6SMatthias Ringwald``` 614930cef6SMatthias Ringwald 624930cef6SMatthias RingwaldCompiled library will be found in `bin` directory. 634930cef6SMatthias Ringwald 64*6897da5cSDirk Helbig#### Web Assembly (WASM) 65*6897da5cSDirk Helbig 66*6897da5cSDirk HelbigWeb assembly compilation is supported using LLVM WebAssembly backend. 67*6897da5cSDirk HelbigInstallation of LLVM compiler and linker is needed: 68*6897da5cSDirk Helbig 69*6897da5cSDirk Helbig```sh 70*6897da5cSDirk Helbig# apt install clang lld 71*6897da5cSDirk Helbig``` 72*6897da5cSDirk Helbig 73*6897da5cSDirk HelbigThe webasm object is compiled using: 74*6897da5cSDirk Helbig```sh 75*6897da5cSDirk Helbig$ make CC="clang --target=wasm32" 76*6897da5cSDirk Helbig``` 77*6897da5cSDirk Helbig 784930cef6SMatthias Ringwald## Tools 794930cef6SMatthias Ringwald 80*6897da5cSDirk HelbigTools can be all compiled, while invoking `make` as follows : 814930cef6SMatthias Ringwald 824930cef6SMatthias Ringwald```sh 834930cef6SMatthias Ringwald$ make tools 844930cef6SMatthias Ringwald``` 854930cef6SMatthias Ringwald 864930cef6SMatthias RingwaldThe standalone encoder `elc3` take a `wave` file as input and encode it 874930cef6SMatthias Ringwaldaccording given parameter. The LC3 binary file format used is the non 884930cef6SMatthias Ringwaldstandard format described by the reference encoder / decoder tools. 894930cef6SMatthias RingwaldThe standalone decoder `dlc3` do the inverse operation. 904930cef6SMatthias Ringwald 914930cef6SMatthias RingwaldRefer to `elc3 -h` or `dlc3 -h` for options. 924930cef6SMatthias Ringwald 934930cef6SMatthias RingwaldNote that `elc3` output bitstream to standard output when output file is 944930cef6SMatthias Ringwaldomitted. On the other side `dlc3` read from standard input when input output 954930cef6SMatthias Ringwaldfile are omitted. 964930cef6SMatthias RingwaldIn such way you can easly test encoding / decoding loop with : 974930cef6SMatthias Ringwald 984930cef6SMatthias Ringwald```sh 99*6897da5cSDirk Helbig$ alias elc3="LD_LIBRARY_PATH=`pwd`/bin `pwd`/bin/elc3" 100*6897da5cSDirk Helbig$ alias dlc3="LD_LIBRARY_PATH=`pwd`/bin `pwd`/bin/dlc3" 101*6897da5cSDirk Helbig$ elc3 <in.wav> -b <bitrate> | dlc3 > <out.wav> 1024930cef6SMatthias Ringwald``` 1034930cef6SMatthias Ringwald 1044930cef6SMatthias RingwaldAdding Linux `aplay` tools, you will be able to instant hear the result : 1054930cef6SMatthias Ringwald 1064930cef6SMatthias Ringwald```sh 107*6897da5cSDirk Helbig$ alias elc3="LD_LIBRARY_PATH=`pwd`/bin `pwd`/bin/elc3" 108*6897da5cSDirk Helbig$ alias dlc3="LD_LIBRARY_PATH=`pwd`/bin `pwd`/bin/dlc3" 109*6897da5cSDirk Helbig$ elc3 <in.wav> -b <bitrate> | dlc3 | aplay -D pipewire 1104930cef6SMatthias Ringwald``` 1114930cef6SMatthias Ringwald 1124930cef6SMatthias Ringwald## Test 1134930cef6SMatthias Ringwald 1144930cef6SMatthias RingwaldA python implementation of the encoder is provided in `test` diretory. 1154930cef6SMatthias RingwaldThe C implementation is unitary validated against this implementation and 116*6897da5cSDirk Helbigintermediate values given in Appendix C of the LC3 specification. 1174930cef6SMatthias Ringwald 1184930cef6SMatthias Ringwald#### Prerequisite 1194930cef6SMatthias Ringwald 1204930cef6SMatthias Ringwald```sh 1214930cef6SMatthias Ringwald# apt install python3 python3-dev python3-pip 1224930cef6SMatthias Ringwald$ pip3 install scipy numpy 1234930cef6SMatthias Ringwald``` 1244930cef6SMatthias Ringwald 1254930cef6SMatthias Ringwald#### Running test suite 1264930cef6SMatthias Ringwald 1274930cef6SMatthias Ringwald```sh 1284930cef6SMatthias Ringwald$ make test 1294930cef6SMatthias Ringwald``` 1304930cef6SMatthias Ringwald 131*6897da5cSDirk Helbig## Fuzzing 1324930cef6SMatthias Ringwald 133*6897da5cSDirk HelbigRoundtrip fuzz testing harness is available in `fuzz` directory. 134*6897da5cSDirk HelbigLLVM `clang` and `clang++` compilers are needed to run fuzzing. 1354930cef6SMatthias Ringwald 136*6897da5cSDirk HelbigThe encoder and decoder fuzzers can be run, for 1 million iterations, using 137*6897da5cSDirk Helbigtarget respectively `dfuzz` and `efuzz`. The `fuzz` target runs both. 138*6897da5cSDirk Helbig 139*6897da5cSDirk Helbig```sh 140*6897da5cSDirk Helbig$ make efuzz # Run encoder fuzzer for 1M iteration 141*6897da5cSDirk Helbig$ make dfuzz # Run decoder fuzzer for 1M iteration 142*6897da5cSDirk Helbig$ make fuzz -j # Run encoder and decoder fuzzers in parallel 143*6897da5cSDirk Helbig``` 144*6897da5cSDirk Helbig 145*6897da5cSDirk Helbig## Qualification / Conformance 146*6897da5cSDirk Helbig 147*6897da5cSDirk HelbigThe implementation is qualified under the [_QDID 194161_](https://launchstudio.bluetooth.com/ListingDetails/160904) as part of Google Fluoride 1.5. 148*6897da5cSDirk Helbig 149*6897da5cSDirk HelbigThe conformance reports can be found [here](conformance/README.md) 1504930cef6SMatthias Ringwald 1514c4eb519SMatthias Ringwald## Listening Test 1524c4eb519SMatthias Ringwald 1534c4eb519SMatthias RingwaldThe codec was [_here_](https://hydrogenaud.io/index.php/topic,122575.0.html) 1544c4eb519SMatthias Ringwaldsubjectively evaluated in a blind listening test. 1554c4eb519SMatthias Ringwald 156*6897da5cSDirk Helbig 1574c4eb519SMatthias Ringwald## Meson build system 1584c4eb519SMatthias Ringwald 1594c4eb519SMatthias RingwaldMeson build system is also available to build and install lc3 codec in Linux 1604c4eb519SMatthias Ringwaldenvironment. 1614c4eb519SMatthias Ringwald 1624c4eb519SMatthias Ringwald```sh 163*6897da5cSDirk Helbig$ meson setup build 164*6897da5cSDirk Helbig$ cd build && meson install 1654c4eb519SMatthias Ringwald``` 1664c4eb519SMatthias Ringwald 167*6897da5cSDirk Helbig## Python wrapper 168*6897da5cSDirk Helbig 169*6897da5cSDirk HelbigA python wrapper, installed as follows, is available in the `python` directory. 170*6897da5cSDirk Helbig 171*6897da5cSDirk Helbig```sh 172*6897da5cSDirk Helbig$ python3 -m pip install . 173*6897da5cSDirk Helbig``` 174*6897da5cSDirk Helbig 175*6897da5cSDirk HelbigDecoding and encoding tools are provided in `python/tools`, like C tools, 176*6897da5cSDirk Helbigyou can easly test encoding / decoding loop with : 177*6897da5cSDirk Helbig 178*6897da5cSDirk Helbig```sh 179*6897da5cSDirk Helbig$ python3 ./python/tools/encoder.py <in.wav> --bitrate <bitrate> | \ 180*6897da5cSDirk Helbig python3 ./python/tools/decoder.py > <out.wav> 181*6897da5cSDirk Helbig``` 182