A generic cross platform decoder for producing PCM data from encoded audio media formats.
Developed at Spotify 2019-2022, Discontinued and handed over to new maintainers January 2023
At Spotify we have performed studies that show the efficacy of using native backed solutions for interfacing to backends, especially when it came to the battery life of certain devices. In order to carry this forward in the cross-platform C++ world, we created this library that provides a common interface to many audio codecs. We found that many of the current solutions that claimed to do this lacked key supports for many kinds of platforms, and ended up being libraries that heavily favoured 1 platform and gave the other platforms a generic implementation. We also wanted something that could extend to new codecs or protocols as they become available.
NFDecoder
is designed as a common C++ interface to convert audio codecs to PCM! The API allows you to create decoders
that use a common interface to convert to pcm. There is one main Factory
that generates a Decoder
. Both can be platform specific and use native decoders when necessary.
The interfaces are as follows:
- DataProvider An interface inspired by C-like file handling APIs that the decoder uses to read data from the audio source.
- Decrypter An interface defining how to decrypt frames of data in cause the audio is encrypted.
- Manifest An interface describing how to interpret audio retrived from the web and in a
JSON
format. - Factory An interface to create codec decoders. In order to create the decoder, you pass in a path to the audio source, the mime type and provide instances to the previously described interfaces.
- MPEG2TS
- Ogg Vorbis
- WAV
- MP3
- AAC
- Ogg Opus
- FLAC
- speex
NFDecoder
is a Cmake project, while you are free to download the prebuilt static libraries it is recommended to use Cmake to install this project into your wider project. In order to add this into a wider Cmake project (who needs monorepos anyway?), simply add the following line to your CMakeLists.txt
file:
add_subdirectory(NFDecoder)
and, it is required to install gyp
.
$ cd tools/gyp/
$ python setup.py install
Generate an Xcode project from the Cmake project like so:
$ git submodule update --init --recursive
$ mkdir build
$ cd build
$ cmake .. -GXcode
Generate a Ninja project from the Cmake project like so:
$ git submodule update --init --recursive
$ mkdir build
$ cd build
$ cmake .. -GNinja
Use gradle
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.spotify.nfdecodertest_android"
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
externalNativeBuild {
cmake {
cppFlags ""
arguments "-DANDROID_APP=1 -DANDROID=1"
}
}
}
sourceSets {
main {
jniLibs.srcDirs = ['src/main/cpp']
}
}
externalNativeBuild {
cmake {
path "../CMakeLists.txt"
}
}
}
When making changes that will affect audio output, please regenerate and check all inputs. To do this run:
sh ci/osx.sh build
For now one test is provided to the public that tests audio retrieved from the web and ogg playback. We have tested all other formats publicly internally.
An example CLI program is in source/cli/NFDecoderCLI.cpp
.
Contributions are welcomed, have a look at the CONTRIBUTING.md document for more information.
The project is available under the Apache 2.0 license.