Skip to main content

software-defined radio digital signal processing library

Project description

liquid-dsp

Software-Defined Radio Digital Signal Processing Library - https://liquidsdr.org

Core CI Python CI codecov MIT License Packaging status

liquid-dsp is a free and open-source digital signal processing (DSP) library designed specifically for software-defined radios on embedded platforms. The aim is to provide a lightweight DSP library that does not rely on a myriad of external dependencies or proprietary and otherwise cumbersome frameworks. All signal processing elements are designed to be flexible, scalable, and dynamic, including filters, filter design, oscillators, modems, synchronizers, complex mathematical operations, and much more.

// get in, manipulate data, get out
#include <liquid/liquid.h>
int main() {
    unsigned int M  = 4;     // interpolation factor
    unsigned int m  = 12;    // filter delay [symbols]
    float        As = 60.0f; // filter stop-band attenuation [dB]

    // create interpolator from prototype
    firinterp_crcf interp = firinterp_crcf_create_kaiser(M,m,As);
    float complex x = 1.0f;  // input sample
    float complex y[M];      // interpolated output buffer

    // repeat on input sample data as needed
    {
        firinterp_crcf_execute(interp, x, y);
    }

    // destroy interpolator object
    firinterp_crcf_destroy(interp);
    return 0;
}

For more information, please refer to the documentation online.

Installation and Dependencies

liquid-dsp only relies on libc and libm (standard C and math) libraries to run; however liquid will take advantage of other libraries (such as FFTW) if they are available.

If you build from the Git repository you will also need to install autotools for generating the configure.sh script (e.g. brew install autoconf automake on macOS, sudo apt-get install automake autoconf on Debian variants).

Installation

The recommended way to obtain the source code is to clone the entire repository from GitHub:

git clone git://github.com/jgaeddert/liquid-dsp.git

Building and installing the main library is a simple as

./bootstrap.sh
./configure
make
sudo make install

If you are installing on Linux for the first time, you will also need to rebind your dynamic libraries with sudo ldconfig to make the shared object available. This is not necessary on macOS.

If you decide that you want to remove the installed DSP library, simply run

sudo make uninstall

Seriously, I won't be offended.

Run all test scripts

Source code validation is a critical step in any software library, particularly for verifying the portability of code to different processors and platforms. Packaged with liquid-dsp are a number of automatic test scripts to validate the correctness of the source code. The test scripts are located under each module's tests/ directory and take the form of a C source file. liquid includes a framework for compiling, linking, and running the tests, and can be invoked with the make target check, viz.

make check

There are currently more than 110,000 checks to verify functional correctness. Drop me a line if these aren't running on your platform.

Testing Code Coverage

In addition to the full test suite, you can configure gcc to export symbol files to check for code coverage and then use gcovr to generate a full report of precisely which lines are covered in the autotests. These symbol files aren't generated by default and need to be enabled at compile-time through a configure flag:

./configure --enable-coverage

Running the tests and generating the report through gcovr can be invoked with the coverage make target:

make coverage

Examples

Nearly all signal processing elements have a corresponding example in the examples/ directory. Most example scripts generate an output .m file for plotting with GNU octave All examples are built as stand-alone programs and can be compiled with the make target examples:

make examples

Sometimes, however, it is useful to build one example individually. This can be accomplished by directly targeting its binary (e.g. make examples/modem_example). The example then can be run at the command line, viz. ./examples/modem_example.

Benchmarking tool

Packaged with liquid are benchmarks to determine the speed each signal processing element can run on your machine. Initially the tool provides an estimate of the processor's clock frequency and will then estimate the number of trials so that each benchmark will take between 50 and 500 ms to run. You can build and run the benchmark program with the following command:

make bench

Linking the C Library to C++ Programs

Compiling and linking to C++ programs is straightforward. Just include <complex> before <liquid/liquid.h> and use std::complex<float> in favor of float complex. Here is the same example as the one above but in C++ instead of C:

// get in, manipulate data, get out
#include <complex>
#include <liquid/liquid.h>
int main() {
    unsigned int M  = 4;     // interpolation factor
    unsigned int m  = 12;    // filter delay [symbols]
    float        As = 60.0f; // filter stop-band attenuation [dB]

    // create interpolator from prototype
    firinterp_crcf interp = firinterp_crcf_create_kaiser(M,m,As);
    std::complex<float> x = 1.0f;   // input sample
    std::complex<float> y[M];       // interpolated output buffer

    // repeat on input sample data as needed
    {
        firinterp_crcf_execute(interp, x, y);
    }

    // destroy interpolator object
    firinterp_crcf_destroy(interp);
    return 0;
}

C++ Bindings

While C is (mostly) a subset of C++, sometimes having a class structure is more convenient than using C-style structs. These bindings do two things:

  1. Wrap the C-style functionality into a set of header-only C++ class libraries
  2. Bind these C++ classes into python3

The original C example can be re-written in C++ as follows:

// get in, manipulate data, get out
#include "firinterp.hh"
int main() {
    unsigned int M  = 4;     // interpolation factor
    unsigned int m  = 12;    // filter delay [symbols]
    float        As = 60.0f; // filter stop-band attenuation [dB]

    // instantiate interpolator object from prototype
    liquid::firinterp interp(M,m,As);
    std::complex<float> x = 1.0f;  // input sample
    std::complex<float> y[M];      // interpolated output buffer

    // repeat on input sample data as needed
    {
        interp.execute(x, y);
    }
    return 0;
}

Python Bindings

Building python bindings depends on pybind11, the python3 development libraries, and a compatible C++14 compiler (e.g. brew install pybind11 on macOS or sudo apt-get install pybind11-dev on Debian variants). Then install the python dependencies with sudo -H python3 -m pip install pybind11 numpy matplotlib.

Once these dependencies are installed, you can build the liquid-dsp python library with

pip install .

From python3 simply use import liquid as dsp. Our interpolation example used throughout this document can be written in python3 as:

# get in, manipulate data, get out
import liquid as dsp, numpy as np

# create the interpolator
interp = dsp.firinterp(M=4, m=12, As=60.)

# run on a single sample
buf = interp.execute(1+1j,)

PlatformIO

Install platformio (brew install platformio on macOS, sudo -H python3 -m pip install -U platformio on Linux). Add liquid-dsp to your platform.io list of dependencies:

[env:native]
platform = native
lib_deps = https://github.com/jgaeddert/liquid-dsp.git

Available Modules

  • agc: automatic gain control, received signal strength
  • audio: source audio encoders/decoders: cvsd, filterbanks
  • buffer: internal buffering, circular/static, ports (threaded)
  • channel: additive noise, multi-path fading, carrier phase/frequency offsets, timing phase/rate offsets
  • dotprod: inner dot products (real, complex), vector sum of squares
  • equalization: adaptive equalizers: least mean-squares, recursive least squares, semi-blind
  • fec: basic forward error correction codes including several Hamming codes, single error correction/double error detection, Golay block code, as well as several checksums and cyclic redundancy checks, interleaving, soft decoding
  • fft: fast Fourier transforms (arbitrary length), discrete sin/cos transforms
  • filter: finite/infinite impulse response, polyphase, hilbert, interpolation, decimation, filter design, resampling, symbol timing recovery
  • framing: flexible framing structures for amazingly easy packet software radio; dynamically adjust modulation and coding on the fly with single- and multi-carrier framing structures
  • math: transcendental functions not in the C standard library (gamma, besseli, etc.), polynomial operations (curve-fitting, root-finding, etc.)
  • matrix: basic math, LU/QR/Cholesky factorization, inversion, Gauss elimination, Gram-Schmidt decomposition, linear solver, sparse matrix representation
  • modem: modulate, demodulate, PSK, differential PSK, QAM, optimal QAM, as well as analog and non-linear digital modulations GMSK)
  • multichannel: filterbank channelizers, OFDM
  • nco: numerically-controlled oscillator: mixing, frequency synthesis, phase-locked loops
  • optim: (non-linear optimization) Newton-Raphson, evoluationary algorithms, gradient descent, line search
  • quantization: analog/digital converters, compression/expansion
  • random: (random number generators) uniform, exponential, gamma, Nakagami-m, Gauss, Rice-K, Weibull
  • sequence: linear feedback shift registers, complementary codes, maximal-length sequences
  • utility: useful miscellany, mostly bit manipulation (shifting, packing, and unpacking of arrays)
  • vector: generic vector operations

License

liquid projects are released under the X11/MIT license. By default, this project will try to link to FFTW if it is available on your build platform. Because FFTW starting with version 1.3 is licensed under the GNU General Public License v2 this unfortunately means that (and I'm clearly not a lawyer, here) you cannot distribute liquid-dsp without also distributing the source code if you link to FFTW. This is a similar situation with the classic libfec which uses the GNU Lesser GPL. Finally, liquid-dsp makes extensive use of GNU autoconf, automake, and related tools. These are fantastic libraires with amazing functionality and their authors should be lauded for their efforts. In a similar vain, much the software I write for a living I give away for free; however I believe in more permissive licenses to allow individuals the flexibility to use software with fewer limitations. If these restrictions are not acceptible, liquid-dsp can be compiled and run without use of these external libraries, albeit a bit slower and with limited functionality.

Short version: this code is copyrighted to me (Joseph D. Gaeddert), I give you full permission to do whatever you want with it except remove my name from the credits. Seriously, go nuts! but take caution when linking to other libraries with different licenses. See the license for specific terms.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

liquid_dsp-1.6.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded PyPy macOS 11.0+ ARM64

liquid_dsp-1.6.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy macOS 10.15+ x86-64

liquid_dsp-1.6.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded PyPy macOS 11.0+ ARM64

liquid_dsp-1.6.0-pp39-pypy39_pp73-macosx_10_15_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy macOS 10.15+ x86-64

liquid_dsp-1.6.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded PyPy macOS 11.0+ ARM64

liquid_dsp-1.6.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy macOS 10.9+ x86-64

liquid_dsp-1.6.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-pp37-pypy37_pp73-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded PyPy manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded PyPy macOS 10.9+ x86-64

liquid_dsp-1.6.0-cp312-cp312-musllinux_1_2_x86_64.whl (2.6 MB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.2+ x86-64

liquid_dsp-1.6.0-cp312-cp312-musllinux_1_2_i686.whl (2.8 MB view hashes)

Uploaded CPython 3.12 musllinux: musl 1.2+ i686

liquid_dsp-1.6.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.12 manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-cp312-cp312-macosx_13_0_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.12 macOS 13.0+ x86-64

liquid_dsp-1.6.0-cp312-cp312-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded CPython 3.12 macOS 11.0+ ARM64

liquid_dsp-1.6.0-cp312-cp312-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.12 macOS 10.9+ x86-64

liquid_dsp-1.6.0-cp311-cp311-musllinux_1_2_x86_64.whl (2.6 MB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.2+ x86-64

liquid_dsp-1.6.0-cp311-cp311-musllinux_1_2_i686.whl (2.8 MB view hashes)

Uploaded CPython 3.11 musllinux: musl 1.2+ i686

liquid_dsp-1.6.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.11 manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-cp311-cp311-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded CPython 3.11 macOS 11.0+ ARM64

liquid_dsp-1.6.0-cp311-cp311-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.11 macOS 10.9+ x86-64

liquid_dsp-1.6.0-cp310-cp310-musllinux_1_2_x86_64.whl (2.6 MB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.2+ x86-64

liquid_dsp-1.6.0-cp310-cp310-musllinux_1_2_i686.whl (2.8 MB view hashes)

Uploaded CPython 3.10 musllinux: musl 1.2+ i686

liquid_dsp-1.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.10 manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-cp310-cp310-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded CPython 3.10 macOS 11.0+ ARM64

liquid_dsp-1.6.0-cp310-cp310-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.10 macOS 10.9+ x86-64

liquid_dsp-1.6.0-cp39-cp39-musllinux_1_2_x86_64.whl (2.6 MB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.2+ x86-64

liquid_dsp-1.6.0-cp39-cp39-musllinux_1_2_i686.whl (2.8 MB view hashes)

Uploaded CPython 3.9 musllinux: musl 1.2+ i686

liquid_dsp-1.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.9 manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-cp39-cp39-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded CPython 3.9 macOS 11.0+ ARM64

liquid_dsp-1.6.0-cp39-cp39-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.9 macOS 10.9+ x86-64

liquid_dsp-1.6.0-cp38-cp38-musllinux_1_2_x86_64.whl (2.6 MB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.2+ x86-64

liquid_dsp-1.6.0-cp38-cp38-musllinux_1_2_i686.whl (2.8 MB view hashes)

Uploaded CPython 3.8 musllinux: musl 1.2+ i686

liquid_dsp-1.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.5 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.8 manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-cp38-cp38-macosx_11_0_arm64.whl (1.4 MB view hashes)

Uploaded CPython 3.8 macOS 11.0+ ARM64

liquid_dsp-1.6.0-cp38-cp38-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.8 macOS 10.9+ x86-64

liquid_dsp-1.6.0-cp37-cp37m-musllinux_1_2_x86_64.whl (2.6 MB view hashes)

Uploaded CPython 3.7m musllinux: musl 1.2+ x86-64

liquid_dsp-1.6.0-cp37-cp37m-musllinux_1_2_i686.whl (2.8 MB view hashes)

Uploaded CPython 3.7m musllinux: musl 1.2+ i686

liquid_dsp-1.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ x86-64

liquid_dsp-1.6.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl (1.6 MB view hashes)

Uploaded CPython 3.7m manylinux: glibc 2.17+ i686

liquid_dsp-1.6.0-cp37-cp37m-macosx_10_9_x86_64.whl (1.6 MB view hashes)

Uploaded CPython 3.7m macOS 10.9+ x86-64

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page