Trusted in production by

reFX
Sound theory
AIVA.AI
Acustica Audio
Neural DSP
Neurovirtual
Pico Technology
W.M. Associates, Inc
Keilwerth Audio
KrakenRF
PlugLet
FlexRadio

Why KFR

Performance First

KFR functions and algorithms are carefully designed and implemented for maximum performance.

See FFT benchmark against 10 FFT libraries.

Confirmed by a third-party benchmark as well.

Proven in production

10 years of history. 1929 stars, 284 forks, 33 releases on GitHub. Every pushed commit runs through 200,934,195 checks across 12,735 test cases.

See companies using KFR in their products.

Portable

It is portable across SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX-512, NEON on ARMv7 and ARMv8 (AArch64), and RISC-V 64 with RVV, and is equally optimized for Intel and AMD CPUs.

See platform support.

FFT performance on AVX2 and NEON. KFR 7.1.0 is shown in red. Higher is better (GFLOPS).

What's inside

Discrete Fourier Transform

Real and complex transforms of any size, including non-power-of-2. Multidimensional FFTs are also supported.

DOCS

Biquad filters and filter design

Second-order sections for lowpass, highpass, EQ, shelving, cascades, streaming, and DC removal.

DOCS

IIR filter design

Butterworth, Bessel, Chebyshev, and elliptic prototypes transformed into digital SOS filters.

DOCS

FIR filters and design

Windowed-sinc filter design, short SIMD filters, runtime streaming filters, and moving sums.

DOCS

High quality Sample Rate Conversion

Polyphase resampling with configurable quality, linear phase, continuous streams, and delay compensation.

DOCS

EBU R 128 Loudness

EBU R128-compliant metering for momentary, short-term, integrated loudness, and loudness range.

DOCS

Window functions

Common analysis and FIR-design windows with symmetric or periodic sampling and configurable parameters.

DOCS

Mathematical and statistical functions

High-performance mathematical operations, reductions, interpolation, and statistics for scalar and SIMD data.

DOCS

Audio file reading/writing

Read and write WAV, W64, AIFF, CAF, FLAC, MP3, and raw audio through streaming-friendly APIs.

DOCS

Built for audio plugins, embedded and real-time processing, scientific computing, ML data pipelines and more.

What Our Customers Say

reFX: Nexus

We use kfrlib with great success. It has ready to use convolution, FFT and other goodies. Builds for x64, arm, etc. with full optimizations and native SIMD usage. We’re using it in Nexus for FFT and convolution.

LIGO, Virgo and KAGRA: Gravitational-wave research

The integration of KFR library, a modern C++ library actively maintained for around a decade, enables ROOT data analysis framework with two agnostic key features: rapid FFT calculations and advanced signal processing. KFR allows efficient handling of large signals through high-performance Fast Fourier Transform (FFT) computations in n-dimensions and also robust signal processing techniques, including windowing functions, Finite Impulse Response (FIR), and Infinite Impulse Response (IIR) filtering.

More →

Open Source Projects Using KFR

CERN, The European Organization for Nuclear Research
High-Energy Physics
LIGO, Virgo and KAGRA Collaborations
Gravitational Wave Research
Université de Bordeaux
Experimental Music
Université Bretagne Sud
Recognition of audio signals
Laboratoire d'Informatique de Robotique et de Microélectronique de Montpellier
Robotics applications

Code examples

// signal
constexpr size_t size = 1024;
univector<complex<float>, size> data;
data = make_complex(counter(0.f), zeros<float>());
univector<complex<float>, size> original = data;

// DFT plan
dft_plan<float> plan(size);
univector<u8> temp(plan.temp_size);

plan.execute(data, data, temp);       // forward, in place
plan.execute(data, data, temp, true); // inverse, in place
data = data / size;                   // restore the original scale

// The DFT plan is cached automatically.
// perform real DFT/FFT
univector<float> input;
univector<complex<float>> output = realdft(input);

// Make lowpass filter using bessel function
auto filt = iir_lowpass(bessel<float>(12), 1000, 48000);
// Convert to second-order sections
auto bqs  = to_sos(filt);
// Apply filter using fast implementation
output    = biquad<12>(bqs, input);

const std::array channels{ speaker_type::Left, speaker_type::Right };
ebu_r128<float> loudness(48000, channels);
univector<float> left(loudness.packet_size(), 0.25f);
univector<float> right(loudness.packet_size(), 0.25f);

loudness.process_packet({ left, right });

float M, S, I, RL, RH;
loudness.get_values(M, S, I, RL, RH);

/**
 * KFR (https://www.kfrlib.com)
 * Copyright (C) 2016-2026 Dan Casarin
 * See LICENSE.txt for details
 */

#include <kfr/base.hpp>
#include <kfr/dsp.hpp>
#include <kfr/io.hpp>
#include <kfr/audio.hpp>

using namespace kfr;

// Define constants for input and output sample rates and the length of the signal
constexpr size_t input_sr  = 96000; // Input sample rate (96 kHz)
constexpr size_t output_sr = 44100; // Output sample rate (44.1 kHz)
constexpr size_t len       = 96000 * 6; // Length of the signal (6 seconds at 96 kHz)

int main()
{
    // Print the version of the KFR library being used
    println(library_version());

    // Generate a swept sine wave signal with a duration of 'len' samples
    univector<fbase> swept_sine = swept(0.5, len);

    // --------------------------------------------------------------------------------------
    // ----------------------------- High Quality Resampling --------------------------------
    // --------------------------------------------------------------------------------------
    {
        // Create a high-quality resampler from input_sr to output_sr
        auto r = resampler<fbase>(resample_quality::high, output_sr, input_sr);

        // Create a buffer for the resampled signal, taking the resampler delay into account
        univector<fbase> resampled(len * output_sr / input_sr + r.get_delay());

        // Perform the resampling process
        r.process(resampled, swept_sine);

        auto written = encode_audio_file(
            "audio_high_quality.wav",
            audio_data_planar{ std::initializer_list<fbase*>{ resampled.data() }, resampled.size() },
            audiofile_format{ .container   = audiofile_container::wave,
                              .codec       = audiofile_codec::lpcm,
                              .bit_depth   = 32,
                              .channels    = 1,
                              .sample_rate = output_sr });
        if (!written)
            return -1;

        // Save a plot of the high-quality resampled audio
        plot_save("audio_high_quality", "audio_high_quality.wav", "");
    }

    // --------------------------------------------------------------------------------------
    // ----------------------------- Normal Quality Resampling ------------------------------
    // --------------------------------------------------------------------------------------
    {
        // Create a normal-quality resampler from input_sr to output_sr
        auto r = resampler<fbase>(resample_quality::normal, output_sr, input_sr);

        // Create a buffer for the resampled signal, taking the resampler delay into account
        univector<fbase> resampled(len * output_sr / input_sr + r.get_delay());

        // Perform the resampling process
        r.process(resampled, swept_sine);

        // Write the resampled signal to a WAV file
        auto written = encode_audio_file(
            "audio_normal_quality.wav",
            audio_data_planar{ std::initializer_list<fbase*>{ resampled.data() }, resampled.size() },
            audiofile_format{ .container   = audiofile_container::wave,
                              .codec       = audiofile_codec::lpcm,
                              .bit_depth   = 32,
                              .channels    = 1,
                              .sample_rate = output_sr });
        if (!written)
            return -1;

        // Save a plot of the normal-quality resampled audio
        plot_save("audio_normal_quality", "audio_normal_quality.wav", "");
    }

    // --------------------------------------------------------------------------------------
    // ----------------------------- Low Quality Resampling ---------------------------------
    // --------------------------------------------------------------------------------------
    {
        // Create a low-quality resampler from input_sr to output_sr
        auto r = resampler<fbase>(resample_quality::low, output_sr, input_sr);

        // Create a buffer for the resampled signal, taking the resampler delay into account
        univector<fbase> resampled(len * output_sr / input_sr + r.get_delay());

        // Perform the resampling process
        r.process(resampled, swept_sine);

        // Write the resampled signal to a WAV file
        auto written = encode_audio_file(
            "audio_low_quality.wav",
            audio_data_planar{ std::initializer_list<fbase*>{ resampled.data() }, resampled.size() },
            audiofile_format{ .container   = audiofile_container::wave,
                              .codec       = audiofile_codec::lpcm,
                              .bit_depth   = 32,
                              .channels    = 1,
                              .sample_rate = output_sr });
        if (!written)
            return -1;

        // Save a plot of the low-quality resampled audio
        plot_save("audio_low_quality", "audio_low_quality.wav", "");
    }

    // --------------------------------------------------------------------------------------
    // ----------------------------- Draft Quality Resampling -------------------------------
    // --------------------------------------------------------------------------------------
    {
        // Create a draft-quality resampler from input_sr to output_sr
        auto r = resampler<fbase>(resample_quality::draft, output_sr, input_sr);

        // Create a buffer for the resampled signal, taking the resampler delay into account
        univector<fbase> resampled(len * output_sr / input_sr + r.get_delay());

        // Perform the resampling process
        r.process(resampled, swept_sine);

        // Write the resampled signal to a WAV file
        auto written = encode_audio_file(
            "audio_draft_quality.wav",
            audio_data_planar{ std::initializer_list<fbase*>{ resampled.data() }, resampled.size() },
            audiofile_format{ .container   = audiofile_container::wave,
                              .codec       = audiofile_codec::lpcm,
                              .bit_depth   = 32,
                              .channels    = 1,
                              .sample_rate = output_sr });
        if (!written)
            return -1;

        // Save a plot of the draft-quality resampled audio
        plot_save("audio_draft_quality", "audio_draft_quality.wav", "");
    }

    println("SVG plots have been saved to svg directory");

    return 0;
}

constexpr float sample_rate = 48000.0f;
univector<float, 63> taps;
auto kaiser_window = to_handle(window_kaiser<float>(taps.size(), 6.0f));
fir_lowpass(taps, 4000.0f / sample_rate, kaiser_window, true);

tensor<float, 2> ramp = trender(
    lambda<float, 2>([](shape<2> index)
    {
        return float(10 * index[0] + index[1]);
    }),
    shape{ 2, 3 });

tensor<float, 2> squared = ramp * ramp;