GithubHelp home page GithubHelp logo

isabella232 / nfdriver Goto Github PK

View Code? Open in Web Editor NEW

This project forked from nativeformat/nfdriver

0.0 0.0 0.0 314 KB

A cross platform C++ audio driver with low latency.

License: Apache License 2.0

CMake 4.27% Java 0.64% Python 26.41% Shell 2.47% PowerShell 0.77% C++ 55.84% Objective-C++ 9.60%

nfdriver's Introduction

NFDriver

CircleCI Build status License Spotify FOSS Slack Readme Score

A cross platform C++ audio driver with low latency.

  • πŸ“± iOS 9.0+
  • πŸ’» OS X 10.11+
  • 🐧 Ubuntu Bionic 18.04+ (clang 3.9 or gcc 7.5)
  • πŸ€– Android NDK r17b+
  • πŸ–₯️ Microsoft Windows Store 10

Raison D'Γͺtre πŸ’­

During the development of innovative new audio experiences, we required a driver that would reliably work on a number of different platforms for our experimentation purposes. We noticed that at the time of development no such open source software existed (that managed to support all the platforms we were looking for), so we decided to create a new one. Given that the common language we could use across our experimentation platforms was C++ we decided on that as the language of choice for our interface. It is also worth noting that this wasn't just designed for front end use cases, and as such has the ability to write out WAV files to disk at above real time speeds to support backend rendering use cases.

Architecture πŸ“

NFDriver is designed as a common C++ interface to write information to different systems sound drivers in a low latency. The API simply allows you to create a driver that will then call the callbacks fed into it every time a new block of audio data is requested. It uses very basic C functions in order to reduce the amount of latency when interfacing to it, and to prevent unwanted locks in some implementations of the C++ 11 STL. It always has a fixed block size of 1024 samples it will ask for at any one time. It also has the ability to report errors, stutters, and give callbacks before and after the rendering of a block.

You may notice it has a fixed samplerate and number of channels. This was done due to this being the standard configuration in music output, so in order to lower the complexity of the API and the way each wrapper acts with the system we decided to hardcode these values.

It is designed with 2 major layers:

  • The Normalisation layer, which takes input and resamples it to whatever channel format and samplerate the driver expects.
  • The System Layer, which interfaces to the operating systems audio drivers.

Our support table looks like so:

OS Underlying Framework Status
iOS Core Audio Stable
OSX Core Audio Stable
Linux ALSA Stable
Android OpenSL ES Beta
Windows Media Foundation Alpha

In terms of bouncing to files, our support table looks like so:

Format Options Comments Support
WAV wavsize : int Writes a WAV file to the output destination. iOS, OSX, Linux, Android, Windows
MP3 bitrate : int Writes an MP3 file to the output destination. iOS, OSX, Linux, Android
AAC bitrate : int Writes an AAC file to the output destination. iOS, OSX

Note that using MP3 will require you to define the environment variable LAME_DYLIB. Make sure you allow your users the option to replace this library to comply with its LGPL License. We do not statically link against LAME so we do not take on its LGPL status and retain our MIT license.

Installation πŸ“₯

NFDriver is a cmake project, while you can feel 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, simply add the following line to your CMakeLists.txt file:

add_subdirectory(NFDriver)

For iOS/OSX

Generate an Xcode project from the Cmake project like so:

$ mkdir build
$ cd build
$ cmake .. -GXcode

For Linux

Generate a Ninja project from the Cmake project like so:

$ mkdir build
$ cd build
$ cmake .. -GNinja

For Android

Use gradle to include the NFDriver project like so:

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.spotify.nfdrivertest_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"
        }
    }
}

For Windows

Generate a Visual Studio project from the Cmake project like so:

$ mkdir build
$ cd build
$ cmake .. -G "Visual Studio 12 2013 Win64"

Usage example πŸ‘€

For examples of this in use, see the demo program src/cli/NFDriverCLI.cpp. The API is rather small, it basically has a create function, and a stop/start interface on the created class. You feed the create function with the necessary callbacks used for inputting audio data and then press play.

NF_STUTTER_CALLBACK stutter_callback = [](void *clientdata) {
  printf("Driver Stuttered...\n");
};

NF_RENDER_CALLBACK render_callback = [](void *clientdata, float *frames, int numberOfFrames) {
  const float samplerate = 2000.0f;
  const float multiplier = (2.0f * float(M_PI) * samplerate) / float(NF_DRIVER_SAMPLERATE);
  static unsigned int sinewave = 0;
  for (int n = 0; n < numberOfFrames; n++) {
    float audio = sinf(multiplier * sinewave++);
    for (int i = 0; i < NF_DRIVER_CHANNELS; ++i) {
      *frames++ = audio;
    }
  }
  return numberOfFrames;

};
NF_ERROR_CALLBACK error_callback = [](void *clientdata, const char *errorMessage, int errorCode) {
  printf("Driver Error (%d): %s\n", errorCode, errorMessage);
};

NF_WILL_RENDER_CALLBACK will_render_callback = [](void *clientdata) {};

NF_DID_RENDER_CALLBACK did_render_callback = [](void *clientdata) {};

NFDriver *driver = nativeformat::driver::createDriver(nullptr /* Anything client specific to use in the callbacks */,
                                                      stutter_callback /* called on stutter */,
                                                      render_callback /* called when we have samples to output */,
                                                      error_callback /* called upon driver error */,
                                                      will_render_callback /* Called before render_callback */,
                                                      did_render_callback /* Called after render callback */,
                                                      nativeformat::driver::OutputTypeSoundCard);
driver->setPlaying(true);

The above will output a sine wave at 2kHz on the audio card.

Contributing πŸ“¬

Contributions are welcomed, have a look at the CONTRIBUTING.md document for more information.

License πŸ“

The project is available under the Apache 2.0 license.

Acknowledgements

  • Icon in readme banner is β€œAudio” by Becris from the Noun Project.

Contributors

nfdriver's People

Contributors

8w9ag avatar astrocox avatar drubinstein avatar korilakkuma avatar syoyo avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.