Skip to content

Commit

Permalink
Merge pull request #76 from gsgou/hamming_hanning_periodic
Browse files Browse the repository at this point in the history
implements HammingPeriodic and HanningPeriodic
  • Loading branch information
swharden committed Aug 21, 2023
2 parents 68b9545 + 37117f5 commit 58379f1
Show file tree
Hide file tree
Showing 17 changed files with 147 additions and 7 deletions.
Binary file modified dev/quickstart/windows.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 28 additions & 1 deletion src/FftSharp.Tests/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,16 @@ public void Test_EvenLength_CenterTwoAreSame()
foreach (IWindow window in FftSharp.Window.GetWindows())
{
double[] values = window.Create(12);
Assert.AreEqual(values[5], values[6], 1e-5, window.Name);
if (window.IsSymmetric)
{
Assert.AreEqual(values[5], values[6], 1e-5, window.Name);
Assert.AreEqual(values.First(), values.Last(), 1e-5, window.Name);
}
else
{
Assert.AreNotEqual(values[5], values[6], window.Name);
Assert.AreNotEqual(values.First(), values.Last(), window.Name);
}
}
}

Expand Down Expand Up @@ -121,5 +130,23 @@ public void Test_Window_Reflection()
IWindow[] window = FftSharp.Window.GetWindows();
Assert.IsNotEmpty(window);
}

[Test]
public void Test_PlotAllWindows()
{
foreach (IWindow window in FftSharp.Window.GetWindows())
{
double[] values = window.Create(32);
ScottPlot.Plot plt = new();
var sig = plt.AddSignal(values);
sig.OffsetX = -values.Length / 2 + .5;
plt.Title(window.Name);
plt.AddVerticalLine(0);

string filename = Path.GetFullPath($"test_window_{window.Name}.png");
Console.WriteLine(filename);
plt.SaveFig(filename);
}
}
}
}
20 changes: 19 additions & 1 deletion src/FftSharp.Tests/WindowValueTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using NUnit.Framework;
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -70,6 +70,15 @@ public void Test_Hamming()
AssertEqual(Known_hamming_14, new Windows.Hamming().Create(14));
}

[Test]
public void Test_HammingPeriodic()
{
double[] Known_hamming_periodic_13 = { 0.08, 0.13269023, 0.27869022, 0.48455313, 0.70311825, 0.88431494,0.98663324, 0.98663324, 0.88431494, 0.70311825, 0.48455313, 0.27869022, 0.13269023 };
double[] Known_hamming_periodic_14 = { 0.08, 0.12555432, 0.25319469, 0.43764037, 0.64235963, 0.82680531, 0.95444568, 1.0, 0.95444568, 0.82680531, 0.64235963, 0.43764037, 0.25319469, 0.12555432 };
AssertEqual(Known_hamming_periodic_13, new Windows.HammingPeriodic().Create(13));
AssertEqual(Known_hamming_periodic_14, new Windows.HammingPeriodic().Create(14));
}

[Test]
public void Test_Hanning()
{
Expand All @@ -79,6 +88,15 @@ public void Test_Hanning()
AssertEqual(Known_hanning_14, new Windows.Hanning().Create(14));
}

[Test]
public void Test_HanningPeriodic()
{
double[] Known_hanning_periodic_13 = { 0.0, 0.05727199, 0.21596763, 0.43973166, 0.67730244, 0.87425537, 0.98547091, 0.98547091, 0.87425537, 0.67730244, 0.43973166, 0.21596763, 0.05727199 };
double[] Known_hanning_periodic_14 = { 0.0, 0.04951557, 0.1882551, 0.38873953, 0.61126047, 0.8117449, 0.95048443, 1.0, 0.95048443, 0.8117449, 0.61126047, 0.38873953, 0.1882551, 0.04951557 };
AssertEqual(Known_hanning_periodic_13, new Windows.HanningPeriodic().Create(13));
AssertEqual(Known_hanning_periodic_14, new Windows.HanningPeriodic().Create(14));
}

[Test]
public void Test_Rectangular()
{
Expand Down
5 changes: 5 additions & 0 deletions src/FftSharp/IWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,10 @@ public interface IWindow
/// A brief description of what makes this window unique and what it is typically used for.
/// </summary>
string Description { get; }

/// <summary>
/// Indicates whether the window is symmetric around its midpoint
/// </summary>
bool IsSymmetric { get; }
}
}
2 changes: 2 additions & 0 deletions src/FftSharp/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ public abstract class Window : IWindow

public abstract string Description { get; }

public abstract bool IsSymmetric { get; }

public override string ToString() => Name;

public abstract double[] Create(int size, bool normalize = false);
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Bartlett.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class Bartlett : Window, IWindow
"The Bartlett–Hann window is triangular in shape (a 2nd order B-spline) which is effectively the " +
"convolution of two half-sized rectangular windows.";

public override bool IsSymmetric => true;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Blackman.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ public class Blackman : Window, IWindow
"The Blackman-Harris window is similar to Hamming and Hanning windows. " +
"The resulting spectrum has a wide peak, but good side lobe compression.";

public override bool IsSymmetric => true;

public Blackman()
{
}
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Cosine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public class Cosine : Window, IWindow
public override string Description =>
"This window is simply a cosine function. It reaches zero on both sides and is similar to " +
"Blackman, Hamming, Hanning, and flat top windows, but probably should not be used in practice.";

public override bool IsSymmetric => true;

public override double[] Create(int size, bool normalize = false)
{
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/FlatTop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ public class FlatTop : Window, IWindow
"The flat top window crosses the zero line causing a broader peak in the frequency domain, " +
"which is closer to the true amplitude of the signal than with other windows";

public override bool IsSymmetric => true;

public readonly double A0 = 0.21557895;
public readonly double A1 = 0.41663158;
public readonly double A2 = 0.277263158;
Expand Down
11 changes: 8 additions & 3 deletions src/FftSharp/Windows/Hamming.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,24 @@ public class Hamming : Window, IWindow
public override string Description =>
"The Hamming window has a sinusoidal shape does NOT touch zero at the edges (unlike the similar Hanning window). " +
"It is similar to the Hanning window but its abrupt edges are designed to cancel the largest side lobe. " +
"It may be a good choice for low-quality (8-bit) auto where side lobes lie beyond the quantization noise floor.";
"It may be a good choice for low-quality (8-bit) auto where side lobes lie beyond the quantization noise floor." +
"A symmetric window, for use in filter design.";

public override bool IsSymmetric => true;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];

double phaseStep = (2.0 * Math.PI) / (size - 1.0);

for (int i = 0; i < size; i++)
window[i] = 0.54 - 0.46 * Math.Cos(2 * Math.PI * i / (size - 1));
window[i] = 0.54 - 0.46 * Math.Cos(i * phaseStep);

if (normalize)
NormalizeInPlace(window);

return window;
}
}
}
}
31 changes: 31 additions & 0 deletions src/FftSharp/Windows/HammingPeriodic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;

namespace FftSharp.Windows
{
public class HammingPeriodic : Window, IWindow
{
public override string Name => "HammingPeriodic";
public override string Description =>
"The Hamming window has a sinusoidal shape does NOT touch zero at the edges (unlike the similar Hanning window). " +
"It is similar to the Hanning window but its abrupt edges are designed to cancel the largest side lobe. " +
"It may be a good choice for low-quality (8-bit) auto where side lobes lie beyond the quantization noise floor." +
"A periodic window, for use in spectral analysis.";

public override bool IsSymmetric => false;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];

double phaseStep = (2.0 * Math.PI) / size;

for (int i = 0; i < size; i++)
window[i] = 0.54 - 0.46 * Math.Cos(i * phaseStep);

if (normalize)
NormalizeInPlace(window);

return window;
}
}
}
9 changes: 7 additions & 2 deletions src/FftSharp/Windows/Hanning.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ public class Hanning : Window, IWindow
public override string Description =>
"The Hanning window has a sinusoidal shape which touches zero at the edges (unlike the similar Hamming window). " +
"It has good frequency resolution, low spectral leakage, and is satisfactory for 95 percent of use cases. " +
"If you do not know the nature of the signal but you want to apply a smoothing window, start with the Hann window.";
"If you do not know the nature of the signal but you want to apply a smoothing window, start with the Hann window." +
"A symmetric window, for use in filter design.";

public override bool IsSymmetric => true;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];

double phaseStep = (2.0 * Math.PI) / (size - 1.0);

for (int i = 0; i < size; i++)
window[i] = 0.5 - 0.5 * Math.Cos(2 * Math.PI * i / (size - 1));
window[i] = 0.5 - 0.5 * Math.Cos(i * phaseStep);

if (normalize)
NormalizeInPlace(window);
Expand Down
31 changes: 31 additions & 0 deletions src/FftSharp/Windows/HanningPeriodic.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;

namespace FftSharp.Windows
{
public class HanningPeriodic : Window, IWindow
{
public override string Name => "HanningPeriodic";
public override string Description =>
"The Hanning window has a sinusoidal shape which touches zero at the edges (unlike the similar Hamming window). " +
"It has good frequency resolution, low spectral leakage, and is satisfactory for 95 percent of use cases. " +
"If you do not know the nature of the signal but you want to apply a smoothing window, start with the Hann window." +
"A periodic window, for use in spectral analysis.";

public override bool IsSymmetric => false;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];

double phaseStep = (2.0 * Math.PI) / size;

for (int i = 0; i < size; i++)
window[i] = 0.5 - 0.5 * Math.Cos(i * phaseStep);

if (normalize)
NormalizeInPlace(window);

return window;
}
}
}
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Kaiser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class Kaiser : Window, IWindow
"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 override bool IsSymmetric => true;

public Kaiser()
{
Beta = 15;
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Rectangular.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class Rectangular : Window, IWindow
"equivalent to replacing all but N values of a data sequence by zeros, making it appear as though " +
"the waveform suddenly turns on and off. This window preserves transients at the start and end of the signal.";

public override bool IsSymmetric => true;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Tukey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ public class Tukey : Window, IWindow
"Tukey windows are ideal for analyzing transient data since the amplitude of transient signal " +
"in the time domain is less likely to be altered compared to using Hanning or flat top.";

public override bool IsSymmetric => true;

public Tukey()
{
Alpha = .5;
Expand Down
2 changes: 2 additions & 0 deletions src/FftSharp/Windows/Welch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class Welch : Window, IWindow
"Its frequency response is better than that of the Bartlett windowed cosc function below pi, " +
"but it shows again a rather distinctive bump above.";

public override bool IsSymmetric => true;

public override double[] Create(int size, bool normalize = false)
{
double[] window = new double[size];
Expand Down

0 comments on commit 58379f1

Please sign in to comment.