Getting started with KFR
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.
Fourier transforms and related algorithms
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:
- use a package from GitHub Releases,
- build and install KFR from source,
- add an existing KFR checkout with
add_subdirectory, or - 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.
- Download the archive for the required platform from KFR’s release page.
- Extract it into a stable directory. Call that directory
<kfr-prefix>. - Configure your application with
CMAKE_PREFIX_PATHpointing 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.
What to read next
The best next page depends on the work you want to do:
- Read Basics to understand
vec,univector,tensor,audio_data, views, and alignment. - Read Expressions before composing several operations into a processing pipeline.
- Read How to apply the FFT for spectral analysis, convolution, or transform plans.
- Read FIR filters, biquad filters, or sample-rate conversion for common DSP tasks.
- Read How to read or write audio when the program works with files rather than raw sample buffers.
- Read the licensing overview before distributing an application that uses KFR. KFR is available under GPLv2-or-later or a commercial license; the full license terms govern any particular use.
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.