// Copyright (C) 2006 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATH_WINDOWS
#define DLIB_MATH_WINDOWS
#include <type_traits>
#include "bessel.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
/*! Strong types !*/
struct attenuation_t
{
/*!
WHAT THIS OBJECT REPRESENTS
This object represents a desired attenuation in dB.
This is automatically converted into a beta_t value suitable
for constructing a kaiser window.
See https://www.mathworks.com/help/signal/ug/kaiser-window.html on
filter design.
!*/
attenuation_t() = default;
explicit attenuation_t(double attenuation_db) : v{attenuation_db} {}
double v = 0.0;
};
struct beta_t
{
/*!
WHAT THIS OBJECT REPRESENTS
This value determines the shape of the kaiser window.
See https://en.wikipedia.org/wiki/Kaiser_window#Definition for more details.
!*/
beta_t() = default;
explicit beta_t(double beta) : v{beta} {}
beta_t(attenuation_t attenuation_db)
{
if (attenuation_db.v > 50.0)
v = 0.1102*(attenuation_db.v - 8.7);
else if (attenuation_db.v >= 21.0)
v = 0.5842*std::pow(attenuation_db.v - 21, 0.4) + 0.07886*(attenuation_db.v - 21);
}
double v = 0.0;
};
enum window_symmetry
{
/*!
WHAT THIS OBJECT REPRESENTS
This enum controls whether the window is a symmetric or periodic window.
See https://en.wikipedia.org/wiki/Window_function#Symmetry for a discussion on
symmetric vs periodic windows. This is using the same nomenclature as Matlab and Scipy
when describing windows as either symmetric or periodic.
!*/
SYMMETRIC,
PERIODIC
};
// ----------------------------------------------------------------------------------------
inline double kaiser(double x, double L, beta_t beta)
/*!
This computes the kaiser window function or kaiser-bessel window function.
See https://en.wikipedia.org/wiki/Kaiser_window.
ensures
- returns the kaiser window function when |x| <= L/2 where L is the window duration
- returns 0 otherwise
!*/
{
if (std::abs(x) <= L/2.0)
{
const double r = 2*x/L;
const double a = dlib::cyl_bessel_i(0, beta.v*std::sqrt(1-r*r));
const double b = dlib::cyl_bessel_i(0, beta.v);
return a / b;
}
else
{
return 0.0;
}
}
inline double kaiser(std::size_t i, std::size_t N, beta_t beta, window_symmetry type)
/*!
This computes the kaiser window function or kaiser-bessel window function.
See https://en.wikipedia.org/wiki/Kaiser_window
This variant is a short-cut for computing a window function and storing it
in an array of size N where 0 <= i < N is the array index.
requires
- 0 <= i < N
ensures
- returns kaiser(i - (N-1)/2, window_duration{N-1}, beta)
!*/
{
DLIB_ASSERT(i < N, "index out of range");
const std::size_t L = type == SYMMETRIC ? N-1 : N;
return kaiser(i - L / 2.0, (double)L, beta);
}
// ----------------------------------------------------------------------------------------
inline double hann(std::size_t i, std::size_t N, window_symmetry type)
/*!
This computes the hann window function.
See https://en.wikipedia.org/wiki/Window_function#Hann_and_Hamming_windows.
requires
- 0 <= i < N
!*/
{
DLIB_ASSERT(i < N, "index out of range");
const std::size_t size = type == SYMMETRIC ? N-1 : N;
const double phi = (2.0 * pi * i) / size;
return 0.5 - 0.5 * std::cos(phi);
}
// ----------------------------------------------------------------------------------------
inline double blackman(std::size_t i, std::size_t N, window_symmetry type)
/*!
This computes the Blackman window function.
See https://en.wikipedia.org/wiki/Window_function#Blackman_window and
https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.windows.blackman.html.
requires
- 0 <= i < N
!*/
{
DLIB_ASSERT(i < N, "index out of range");
const std::size_t size = type == SYMMETRIC ? N-1 : N;
const double phi = (2.0 * pi * i) / size;
return 0.42 -
0.5 * std::cos(phi) +
0.08 * std::cos(2.0 * phi);
}
// ----------------------------------------------------------------------------------------
inline double blackman_nuttall(std::size_t i, std::size_t N, window_symmetry type)
/*!
This computes the Blackman-Nuttall window function.
See https://en.wikipedia.org/wiki/Window_function#Blackman%E2%80%93Nuttall_window.
requires
- 0 <= i < N
!*/
{
DLIB_ASSERT(i < N, "index out of range");
const std::size_t size = type == SYMMETRIC ? N-1 : N;
const double phi = (2.0 * pi * i) / size;
return 0.3635819 -
0.4891775 * std::cos(phi) +
0.1365995 * std::cos(2*phi) -
0.0106411 * std::cos(3*phi);
}
// ----------------------------------------------------------------------------------------
inline double blackman_harris(std::size_t i, std::size_t N, window_symmetry type)
/*!
This computes the Blackman-Harris window function.
See https://en.wikipedia.org/wiki/Window_function#Blackman%E2%80%93Harris_window.
requires
- R is float, double, or long double
- 0 <= i < N
!*/
{
DLIB_ASSERT(i < N, "index out of range");
const std::size_t size = type == SYMMETRIC ? N-1 : N;
const double phi = (2.0 * pi * i) / size;
return 0.35875 -
0.48829 * std::cos(phi) +
0.14128 * std::cos(2*phi) -
0.01168 * std::cos(3*phi);
}
// ----------------------------------------------------------------------------------------
inline double blackman_harris7(std::size_t i, std::size_t N, window_symmetry type)
/*!
This computes the 7-order Blackman-Harris window function.
requires
- R is float, double, or long double
- 0 <= i < N
!*/
{
DLIB_ASSERT(i < N, "index out of range");
const std::size_t size = type == SYMMETRIC ? N-1 : N;
const double phi = (2.0 * pi * i) / size;
return 0.27105 -
0.43329 * std::cos(phi) +
0.21812 * std::cos(2*phi) -
0.06592 * std::cos(3*phi) +
0.01081 * std::cos(4*phi) -
0.00077 * std::cos(5*phi) +
0.00001 * std::cos(6*phi);
}
// ----------------------------------------------------------------------------------------
}
#endif //DLIB_MATH_WINDOWS