frequency: frequency

A type-safe, header-only C++20 library for frequency handling, modeled after std::chrono::duration.

📚 Full API Documentation

Features

  • Type-safe frequencies with distinct types for different precisions
  • Standard SI units: millihertz, hertz, kilohertz, megahertz, gigahertz, terahertz
  • Integer and floating-point representations for exact or fractional precision
  • Automatic conversions between precisions
  • Lossless implicit conversions (lossy conversions require explicit casts)
  • User-defined literals for concise notation
  • **std::format support** (when available)
  • Fully constexpr - all operations can be evaluated at compile time

Requirements

  • C++20 compiler (GCC 10+, Clang 10+, MSVC 19.26+)

Installation

CMake FetchContent

include(FetchContent)

FetchContent_Declare(

frequency

GIT_REPOSITORY https://github.com/cleishm/frequency-cpp.git

GIT_TAG v1.0.0

)

FetchContent_MakeAvailable(frequency)

target_link_libraries(your_target PRIVATE frequency::frequency)

vcpkg

vcpkg install cleishm-frequency-cpp

find_package(frequency CONFIG REQUIRED)

target_link_libraries(your_target PRIVATE frequency::frequency)

Manual

Copy include/frequency/frequency.hpp to your project.

Usage

using namespace freq;

hertz audio_sample_rate{44100};

auto f1 = 1000_Hz;

auto f2 = 80_kHz;

auto f3 = 2400_MHz;

auto f4 = 5_GHz;

millihertz precise{44100000};

hertz coarse = hertz(precise);

millihertz back = coarse;

auto sum = 1000_Hz + 500_Hz;

auto diff = 5_GHz - 2400_MHz;

auto scaled = 100_Hz * 3;

auto ratio = 1000_Hz / 100_Hz;

}

A frequency value with a representation and precision.

Frequency types and utilities.

std::string to_string(millihertz f)

User-defined literals for frequency types.

Frequency Types

Type Unit Precision
millihertz mHz 0.001 Hz
hertz Hz 1 Hz
kilohertz kHz 1,000 Hz
megahertz MHz 1,000,000 Hz
gigahertz GHz 1,000,000,000 Hz
terahertz THz 1,000,000,000,000 Hz

All types use int64_t representation by default. For fractional precision, use frequency<double, Precision> (see Floating-Point Frequencies section).

Literals

1000_mHz

1000_Hz

80_kHz

2400_MHz

5_GHz

1_THz

Conversion Rules

Conversions follow the same philosophy as std::chrono:

  • Implicit conversions are allowed when lossless (e.g., kilohertz → hertz)
  • Explicit conversions are required when lossy (e.g., hertz → kilohertz)

auto khz2 = frequency_cast<kilohertz>(hertz{2500});

Floating-Point Frequencies

The library supports floating-point representations for fractional precision. This is useful for:

  • Musical tuning and audio applications (e.g., concert pitch A = 440.0 Hz)
  • Scientific measurements with sub-unit precision
  • Calculations involving irrational ratios

hertz_d concert_a{440.0};

hertz_d c_sharp = concert_a.semitone_shift(4);

megahertz_d precise_radio{88.5};

kilohertz_d exact_note{261.626};

hertz_d f1{1000.5};

hertz_d f2{500.25};

hertz_d sum = f1 + f2;

hertz_d float_freq = hertz_d(int_freq);

float_freq = float_freq * 1.5;

hertz_d a4{440.0};

hertz_d a5 = a4.octave_shift(1.0);

hertz_d tritone = a4.octave_shift(0.5);

frequency semitone_shift(T semitones) const

Returns this frequency shifted by a number of semitones.

Important considerations:

  • Floating-point frequencies allow fractional values but sacrifice exact arithmetic
  • Implicit conversions between integer and floating-point frequencies follow the same lossless/lossy rules as precision conversions
  • Integer types are preferred when exact values and modulo operations are needed
  • Floating-point types are preferred for calculations involving division, musical intervals, or measurements with fractional precision

Building Tests

cmake -B build -DFREQUENCY_BUILD_TESTS=ON

cmake --build build

ctest --test-dir build

License

MIT License - see [LICENSE](LICENSE) for details.