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
hertz audio_sample_rate{44100};
auto f1 = 1000_Hz;
auto f2 = 80_kHz;
auto f3 = 2400_MHz;
auto f4 = 5_GHz;
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};
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.