DSPark 1.6.1
Header-only audio DSP framework in pure C++20 — zero dependencies
Loading...
Searching...
No Matches
WindowFunctions.h
Go to the documentation of this file.
1// DSPark -- Professional Audio DSP Framework
2// Copyright (c) 2026 Cristian Moresi -- MIT License
3
4#pragma once
5
35#include <algorithm>
36#include <cassert>
37#include <cmath>
38#include <cstddef>
39#include <numbers>
40
41namespace dspark {
42
58template <typename T>
60{
61 // Prevent instantiation (static-only utility class)
62 WindowFunctions() = delete;
63
69 static void rectangular(T* output, int size) noexcept
70 {
71 assert(output != nullptr);
72 if (size <= 0) return;
73 std::fill(output, output + size, T(1));
74 }
75
82 static void triangular(T* output, int size, bool periodic = true) noexcept
83 {
84 assert(output != nullptr);
85 if (size <= 0) return;
86 if (size == 1) { output[0] = T(1); return; }
87
88 const int N = periodic ? size : size - 1;
89 const double halfN = static_cast<double>(N) / 2.0;
90
91 for (int i = 0; i < size; ++i)
92 output[i] = static_cast<T>(1.0 - std::abs((static_cast<double>(i) - halfN) / halfN));
93 }
94
101 static void hann(T* output, int size, bool periodic = true) noexcept
102 {
103 static constexpr double kCoeffs[] = { 0.5, -0.5 };
104 cosineSum(output, size, periodic, kCoeffs);
105 }
106
113 static void hamming(T* output, int size, bool periodic = true) noexcept
114 {
115 static constexpr double kCoeffs[] = { 0.54, -0.46 };
116 cosineSum(output, size, periodic, kCoeffs);
117 }
118
125 static void blackman(T* output, int size, bool periodic = true) noexcept
126 {
127 static constexpr double kCoeffs[] = { 0.42, -0.5, 0.08 };
128 cosineSum(output, size, periodic, kCoeffs);
129 }
130
137 static void blackmanHarris(T* output, int size, bool periodic = true) noexcept
138 {
139 // Harris 1978, 4-term minimum side-lobe coefficients.
140 static constexpr double kCoeffs[] = { 0.35875, -0.48829, 0.14128, -0.01168 };
141 cosineSum(output, size, periodic, kCoeffs);
142 }
143
150 static void flatTop(T* output, int size, bool periodic = true) noexcept
151 {
152 // ISO 18431-2 / MATLAB flattopwin coefficients.
153 static constexpr double kCoeffs[] = { 0.21557895, -0.41663158, 0.277263158,
154 -0.083578947, 0.006947368 };
155 cosineSum(output, size, periodic, kCoeffs);
156 }
157
165 static void kaiser(T* output, int size, T beta, bool periodic = true) noexcept
166 {
167 assert(output != nullptr);
168 if (size <= 0) return;
169 if (size == 1) { output[0] = T(1); return; }
170
171 const int N = periodic ? size : size - 1;
172 const double b = static_cast<double>(beta);
173 const double invDenominator = 1.0 / besselI0(b);
174
175 for (int i = 0; i < size; ++i)
176 {
177 const double x = 2.0 * static_cast<double>(i) / static_cast<double>(N) - 1.0;
178 // Protected against rounding making (1 - x*x) strictly negative.
179 const double arg = b * std::sqrt(std::max(0.0, 1.0 - x * x));
180 output[i] = static_cast<T>(besselI0(arg) * invDenominator);
181 }
182 }
183
184 // -- Utility methods -------------------------------------------------------
185
196 static void apply(T* signal, const T* window, int size) noexcept
197 {
198 assert(signal != nullptr && window != nullptr);
199
200 // No alignment assumption: std::assume_aligned<32> on a pointer that is
201 // not actually 32-byte aligned is undefined behaviour, and these buffers
202 // come from arbitrary callers (sub-views, vectors -> typically 16-byte).
203 for (int i = 0; i < size; ++i)
204 signal[i] *= window[i];
205 }
206
218 [[nodiscard]] static T coherentGain(const T* window, int size) noexcept
219 {
220 assert(window != nullptr);
221 if (size <= 0) return T(0);
222
223 double sum = 0.0;
224 for (int i = 0; i < size; ++i)
225 sum += static_cast<double>(window[i]);
226
227 return static_cast<T>(sum / static_cast<double>(size));
228 }
229
240 [[nodiscard]] static T energyGain(const T* window, int size) noexcept
241 {
242 assert(window != nullptr);
243 if (size <= 0) return T(0);
244
245 double sumSq = 0.0;
246 for (int i = 0; i < size; ++i)
247 {
248 const double w = static_cast<double>(window[i]);
249 sumSq += w * w;
250 }
251
252 return static_cast<T>(std::sqrt(sumSq / static_cast<double>(size)));
253 }
254
255private:
262 template <std::size_t NumTerms>
263 static void cosineSum(T* output, int size, bool periodic,
264 const double (&coeffs)[NumTerms]) noexcept
265 {
266 assert(output != nullptr);
267 if (size <= 0) return;
268 if (size == 1) { output[0] = T(1); return; }
269
270 const int N = periodic ? size : size - 1;
271 const double twoPiInvN = 2.0 * std::numbers::pi_v<double> / static_cast<double>(N);
272
273 for (int i = 0; i < size; ++i)
274 {
275 const double x = twoPiInvN * static_cast<double>(i);
276 double acc = coeffs[0];
277 for (std::size_t t = 1; t < NumTerms; ++t)
278 acc += coeffs[t] * std::cos(static_cast<double>(t) * x);
279 output[i] = static_cast<T>(acc);
280 }
281 }
282
290 [[nodiscard]] static double besselI0(double x) noexcept
291 {
292 double sum = 1.0;
293 double term = 1.0;
294 const double halfX = x / 2.0;
295
296 for (int k = 1; k < 50; ++k)
297 {
298 const double f = halfX / static_cast<double>(k);
299 term *= f * f;
300 sum += term;
301 if (term < sum * 1e-12) break; // converged
302 }
303
304 return sum;
305 }
306};
307
308} // namespace dspark
Main namespace for the DSPark framework.
Static utility generating window functions for DSP analysis/synthesis.
static void kaiser(T *output, int size, T beta, bool periodic=true) noexcept
Kaiser window with configurable shape parameter beta.
static void hann(T *output, int size, bool periodic=true) noexcept
Hann (raised cosine) window.
static void triangular(T *output, int size, bool periodic=true) noexcept
Triangular (Bartlett) window.
static void blackman(T *output, int size, bool periodic=true) noexcept
Blackman window.
static void blackmanHarris(T *output, int size, bool periodic=true) noexcept
Blackman-Harris window (4-term, -92 dB side lobes).
static void hamming(T *output, int size, bool periodic=true) noexcept
Hamming window.
static T coherentGain(const T *window, int size) noexcept
Computes the coherent gain of a window (mean of its samples).
static T energyGain(const T *window, int size) noexcept
Computes the energy gain (RMS) of a window.
static void apply(T *signal, const T *window, int size) noexcept
Applies a window to a signal buffer in-place.
static void flatTop(T *output, int size, bool periodic=true) noexcept
Flat-top window (amplitude-accurate: scallop loss < 0.01 dB).
static void rectangular(T *output, int size) noexcept
Rectangular window (no windowing – all ones).