Files

55 lines
2.0 KiB
C#
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
using System;
namespace FftSharp.Windows
{
public class Kaiser : Window, IWindow
{
public readonly double Beta;
public override string Name => $"Kaiser-Bessel";
public override string Description =>
"A Kaiser-Bessel window strikes a balance among the various conflicting goals of amplitude " +
"accuracy, side lobe distance, and side lobe height. It compares roughly to the BlackmanHarris window functions, " +
"but for the same main lobe width, the near side lobes tend to be higher, but the further out side lobes are lower. " +
"Choosing this window often reveals signals close to the noise floor";
public Kaiser()
{
Beta = 15;
}
public Kaiser(double beta)
{
Beta = beta;
}
public static double I0(double x)
{
// Derived from code workby oygx210/navguide:
// https://github.com/oygx210/navguide/blob/master/src/common/bessel.c
double ax = Math.Abs(x);
if (ax < 3.75)
{
double y = Math.Pow(x / 3.75, 2);
double[] m = { 3.5156229, 3.0899424, 1.2067492, 0.2659732, 0.360768e-1, 0.45813e-2 };
return 1.0 + y * (m[0] + y * (m[1] + y * (m[2] + y * (m[3] + y * (m[4] + y * m[5])))));
}
else
{
double y = 3.75 / ax;
double[] m = { 0.39894228, 0.1328592e-1, 0.225319e-2, -0.157565e-2, 0.916281e-2, -0.2057706e-1, 0.2635537e-1, -0.1647633e-1, 0.392377e-2 };
return (Math.Exp(ax) / Math.Sqrt(ax)) * (m[0] + y * (m[1] + y * (m[2] + y * (m[3] + y * (m[4] + y * (m[5] + y * (m[6] + y * (m[7] + y * m[8]))))))));
}
}
protected override double windowValue(int index, int size)
{
int M = size;
double alpha = (M - 1) / 2.0;
return I0(Beta * Math.Sqrt(1 - Math.Pow((index - alpha) / alpha, 2))) / I0(Beta);
}
}
}