Getting started with KFR

24 September 2026

Getting started with KFR

KFR is a C++ framework for digital signal processing, audio applications, and general numerical work. It provides the low-level building blocks needed for fast array operations, then builds higher-level tools—such as Fourier transforms, filters, resamplers, and audio file codecs—on top of them.

This guide is intended as a first stop for someone who has just found KFR. It describes what the library contains, what is needed to build it, and how to choose an installation method. It does not try to cover every API. Once the library is available in a project, the KFR documentation has focused guides for the individual modules.

What KFR provides

KFR covers several layers of a typical signal-processing program. You can use only the core facilities, or combine them into a complete audio or DSP pipeline.

Core numerical and SIMD types

The core module contains mathematical functions, expressions, containers, random-number utilities, statistics, and multidimensional arrays. Its vec<T, N> type represents a fixed-size group of values and is used as the basis for portable SIMD code. The same source-level operations can target scalar code, x86 vector extensions, ARM NEON, or other supported architectures.

The main one-dimensional container is univector. It can represent a dynamic buffer, fixed-size storage, or a view over existing memory. KFR also provides tensor for multidimensional data and audio_data for planar or interleaved multi-channel audio. These types use aligned allocation when they own their storage, while views preserve the caller’s memory and ownership rules.

The Basics guide explains the containers, SIMD vectors, tensors, alignment, views, and the conventions used by the rest of the library.

Lazy expressions

Most operations on KFR arrays are expressions rather than immediate temporary arrays. For example, an expression such as sin(input * gain) + offset can be passed directly to a destination. KFR can evaluate the complete expression in one pass, which avoids some intermediate allocations and gives the SIMD layer more work to optimize.

This style is useful for both short numerical programs and performance- sensitive processing loops. It also means that a function can often accept a container, a view, or a composed expression without requiring a separate copy. The Expressions guide goes into the evaluation model in more detail.

The DFT module contains complex and real Fourier transforms, inverse transforms, discrete cosine transforms, multidimensional transforms, and convolution facilities. Transform sizes are not limited to powers of two. A dft_plan can be created once and reused when the same transform size is processed repeatedly; the convenience functions manage plan reuse for common cases.

The implementation also supports real-data layouts and scratch buffers, which are important when memory use and throughput matter. Start with How to apply the Fast Fourier Transform and the DFT introduction when you need more context before choosing an API.

Filters and sample-rate conversion

The DSP module includes finite impulse response (FIR) and infinite impulse response (IIR) processing, biquad cascades, filter-design functions, signal generators, convolution helpers, and sample-rate conversion.

Filter design supports common approximation families such as Butterworth, Chebyshev, elliptic, and Bessel filters. A design can then be applied to an expression or a buffer. The resampler offers selectable quality levels and reports its delay, so an application can account for the latency introduced by conversion.

Useful next reads are FIR filters, biquad filters, IIR filters, and sample-rate conversion.

Audio and data I/O

The I/O and audio modules provide facilities for reading and writing data files and for handling common audio containers and codecs. Audio samples are exposed through KFR’s floating-point audio_data representation, with helpers for converting to and from integer PCM formats, different bit depths, and byte orders.

audio_data can hold either planar channels or an interleaved buffer. Its channel views are expressions, so the same arithmetic and DSP operations used for ordinary arrays can be applied to individual channels. The audio file guide shows the basic read, inspect, process, and write workflow.

Platforms and requirements

KFR is built with CMake and requires a C++20 compiler. The regular support matrix includes Windows, Linux, macOS, iOS, Android, and WebAssembly through Emscripten. The supported CPU families include x86 and x86-64, ARM and ARM64, and RV64 RISC-V. On x86, KFR can use instruction sets from SSE2 through AVX-512; ARM builds can use NEON, and RISC-V builds can use RVV when available.

For a normal source or package integration, plan to have:

  • CMake 3.16 or newer.
  • A compiler with C++20 support. The tested compiler families include GCC 11 and newer, Clang 16 and newer, MSVC 2022 with toolset 19.30 or newer, and Xcode 13 or newer.
  • Ninja, if you want a fast single-configuration command-line build. Visual Studio and Xcode generators work as well.
  • Python 3.6 or newer only for optional plotting examples and filter-response generation. The core C++ build does not need the Python packages in the repository’s requirements.txt.

Clang and GCC are generally the simplest choices when compiling the DFT module or when comparing performance. MSVC is supported, although some computation- heavy paths may not reach the same throughput as builds made with Clang or GCC.

Some modules are optional compiled libraries. The core headers are always available, while the main CMake switches are:

Option Typical default Library target Contains
KFR_ENABLE_DSP On kfr_dsp Filters, resampling, and other DSP algorithms
KFR_ENABLE_DFT Compiler-dependent kfr_dft DFT, FFT, DCT, and convolution
KFR_ENABLE_IO On kfr_io General file and data I/O
KFR_ENABLE_AUDIO On kfr_audio Audio support; requires DSP and I/O
KFR_ENABLE_CAPI_BUILD Off kfr_capi The optional C API shared library

The DFT option is enabled by default with Clang and GCC in the usual builds and is disabled by default with MSVC. Check the configuration rather than assuming that every installed package contains every target.

The DSP build can obtain the standalone Boost.Math dependency through CMake’s FetchContent support for elliptic filters. If the build environment is offline or that dependency is not needed, configure with KFR_USE_BOOST_MATH=OFF. Cross-compilation also requires the appropriate toolchain file and target architecture settings. The complete installation documentation lists the platform-specific cases.

Choose how to install KFR

There are four practical routes:

  1. use a package from GitHub Releases,
  2. build and install KFR from source,
  3. add an existing KFR checkout with add_subdirectory, or
  4. let CMake download KFR with FetchContent.

The first two routes produce an installed package that another project finds with find_package. The last two make KFR targets part of the current CMake build. Pick the route that matches how your project manages dependencies; the application-side target names are intentionally similar in all four cases.

Option 1: use a release package

A release archive is convenient when the available binary matches your target platform, architecture, compiler runtime, and required modules.

  1. Download the archive for the required platform from KFR’s release page.
  2. Extract it into a stable directory. Call that directory <kfr-prefix>.
  3. Configure your application with CMAKE_PREFIX_PATH pointing to the prefix.

The prefix normally contains include/kfr, libraries under lib, and package metadata under lib/cmake/kfr. CMAKE_PREFIX_PATH should point to the prefix itself, not directly to the lib/cmake/kfr directory.

For example, an application can be configured and built like this:

cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/kfr-prefix
cmake --build build

On Windows, use a quoted path if the installation directory contains spaces, for example -DCMAKE_PREFIX_PATH="C:/Libraries/kfr". Alternatively, set KFR_DIR to the directory containing KFRConfig.cmake.

Release packages are not cross-platform binaries. A package made for Linux cannot be used by a Windows build, and a package made for one architecture or ABI should not be substituted for another. If the required combination is not available, build KFR from source instead.

Option 2: build and install from source

Source installation is useful when you need a particular compiler, CPU target, module selection, cross-compilation setup, or a local change to KFR.

A Ninja Release build can be configured and installed with:

git clone https://github.com/kfrlib/kfr.git
cd kfr

cmake -S . -B build-release -GNinja \
	-DCMAKE_BUILD_TYPE=Release \
	-DCMAKE_INSTALL_PREFIX=/path/to/kfr-prefix
cmake --build build-release
cmake --install build-release

Add a compiler selection or module options at configuration time when needed. For example:

cmake -S . -B build-release -GNinja \
	-DCMAKE_BUILD_TYPE=Release \
	-DCMAKE_INSTALL_PREFIX=/path/to/kfr-prefix \
	-DCMAKE_CXX_COMPILER=path/to/clang++ \
	-DKFR_ENABLE_DFT=ON \
	-DKFR_ENABLE_AUDIO=OFF

For Visual Studio or Xcode, configure once and choose the configuration while building:

cmake -S . -B build -G "Visual Studio 17 2022" \
	-DCMAKE_INSTALL_PREFIX=C:/Libraries/kfr
cmake --build build --config Release
cmake --install build --config Release

If you also install Debug, use the same prefix and run the build and install commands with --config Debug. KFR’s CMake package can then select the matching library configuration for the consuming project.

Use an installed package from your application

After either a release package or a source installation is available, use config-mode package discovery and link the targets that correspond to the headers in use:

cmake_minimum_required(VERSION 3.16)
project(example LANGUAGES CXX)

find_package(KFR CONFIG REQUIRED)

add_executable(example main.cpp)
target_link_libraries(example PRIVATE kfr kfr_dsp kfr_dft)

The kfr target supplies the public include directory and C++20 requirement. Add kfr_dsp for <kfr/dsp.hpp>, kfr_dft for <kfr/dft.hpp>, kfr_io for <kfr/io.hpp>, and kfr_audio for <kfr/audio.hpp>. Audio carries its DSP and I/O dependencies transitively. A program that only uses the core can link kfr by itself.

Do not hard-code an include directory or a library filename. The imported CMake targets carry the include paths, compile settings, transitive dependencies, and Debug/Release selection. Optional modules are decided when KFR is built; they are not downloaded by adding a component to find_package.

Option 3: add a checkout with add_subdirectory

If KFR is already in the source tree, perhaps as a submodule, add it to the parent project. Set KFR’s cache options before the add_subdirectory call:

cmake_minimum_required(VERSION 3.16)
project(example LANGUAGES CXX)

set(KFR_ENABLE_DFT ON CACHE BOOL "" FORCE)
set(KFR_ENABLE_AUDIO OFF CACHE BOOL "" FORCE)

add_subdirectory(external/kfr)

add_executable(example main.cpp)
target_link_libraries(example PRIVATE kfr kfr_dft)

There is no separate install or find_package step in this arrangement. KFR is configured in the same build as the application, and its targets and source headers become available immediately. If a parent project does not need KFR’s own tests or examples, disable them to reduce configuration and build time; in particular, use -DENABLE_EXAMPLES=OFF when examples are not wanted.

Option 4: download KFR with FetchContent

FetchContent is useful when the dependency should be downloaded during CMake configuration and is not checked into the project:

cmake_minimum_required(VERSION 3.16)
project(example LANGUAGES CXX)

include(FetchContent)

FetchContent_Declare(
	kfr
	GIT_REPOSITORY https://github.com/kfrlib/kfr.git
	GIT_TAG        7.0.1
	GIT_SHALLOW    TRUE
)

FetchContent_MakeAvailable(kfr)

add_executable(example main.cpp)
target_compile_features(example PRIVATE cxx_std_20)
target_link_libraries(example PRIVATE kfr)

Use a release tag, as in the example, when repeatable builds matter. Tracking main can be useful for testing current development but makes the dependency change over time. As with add_subdirectory, set KFR options before FetchContent_MakeAvailable, because that call configures the dependency.

Include the headers you need

KFR has a combined header for projects that want all modules:

#include <kfr/all.hpp>

For smaller dependencies, include individual module headers instead:

#include <kfr/base.hpp>   // containers, expressions, and core functions
#include <kfr/dft.hpp>    // DFT, FFT, DCT, and convolution
#include <kfr/dsp.hpp>    // filters and sample-rate conversion
#include <kfr/io.hpp>     // data and file I/O
#include <kfr/audio.hpp>  // audio processing and codecs

The header does not by itself determine whether a compiled module is available. If code includes a module that has compiled functionality, the corresponding KFR target must be present and linked. Starting with the smallest relevant header set makes it easier to see which part of KFR an application depends on.

A small first program

Once KFR is linked, a simple transform demonstrates the general workflow: put data in a KFR container, call an algorithm, and use the result as another KFR expression or container.

#include <kfr/base.hpp>
#include <kfr/dft.hpp>

using namespace kfr;

int main()
{
		univector<complex<double>, 256> samples =
				cexp(linspace(0.0, c_pi<double, 2>, 256) * make_complex(0.0, 1.0));

		univector<complex<double>, 256> spectrum = dft(samples);
		univector<complex<double>, 256> reconstructed = idft(spectrum) / 256.0;

		return reconstructed.empty();
}

The inverse transform in this example is divided by the transform length because KFR leaves inverse-transform scaling under the caller’s control. In a real application, you would normally inspect or process spectrum rather than discarding it. The DFT guide contains complete examples for plans, real transforms, and scaling.

The best next page depends on the work you want to do:

The important first decision is not which header to include, but which CMake integration route fits the project. After that, link the targets for the modules you use and let KFR’s containers and expressions carry data through the algorithms.