summaryrefslogtreecommitdiff
path: root/test/test-window-function.cpp
blob: 959d81edd183bb9a596cbea777ff1aa0d4e7b3bc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/*
 * Copyright (c) 2020-2021 Vasile Vilvoiu <vasi@vilvoiu.ro>
 *
 * specgram is free software; you can redistribute it and/or modify
 * it under the terms of the MIT license. See LICENSE for details.
 */
#include "test.hpp"
#include "../src/window-function.hpp"
#include <list>

static std::vector<WindowFunctionType> ALL_WF_TYPES {
    WindowFunctionType::kBlackman,
    WindowFunctionType::kHamming,
    WindowFunctionType::kHann,
    WindowFunctionType::kNuttall,
    WindowFunctionType::kNone
};

static constexpr double EPSILON = 1e-7;

void run_tests(const std::list<std::vector<double>>& tests, WindowFunctionType type)
{
    for (const auto& test : tests) {
        /* create window */
        auto win = WindowFunction::Build(type, test.size());
        /* create identity input */
        ComplexWindow input(test.size());
        for (auto& i : input) { i = 1.0; }
        /* apply */
        auto out = win->Apply(input);
        EXPECT_EQ(out.size(), test.size());
        /* check */
        for (size_t i = 0; i < test.size(); i++) {
            EXPECT_LE(std::abs(out[i] - test[i]), EPSILON);
        }
    }
}

TEST(TestWindowFunction, FactoryWrongType)
{
    EXPECT_THROW_MATCH(auto ret = WindowFunction::Build((WindowFunctionType)999, 10),
                       std::runtime_error, "unknown window function");
}

TEST(TestWindowFunction, TypeBlackman)
{
    /* np.blackman */
    std::list<std::vector<double>> tests;
    tests.push_back( { 1.0 });
    tests.push_back( { -1.38777878e-17, -1.38777878e-17 });
    tests.push_back( { -1.38777878e-17,  1.00000000e+00, -1.38777878e-17 });
    tests.push_back( { -1.38777878e-17,  3.40000000e-01,  1.00000000e+00,  3.40000000e-01,
                       -1.38777878e-17 });
    tests.push_back({ -1.38777878e-17,  5.08696327e-02,  2.58000502e-01,  6.30000000e-01,
                      9.51129866e-01,  9.51129866e-01,  6.30000000e-01,  2.58000502e-01,
                      5.08696327e-02, -1.38777878e-17 });
    tests.push_back({ -1.38777878e-17,  6.31911916e-03,  2.69872981e-02,  6.64466094e-02,
                      1.30000000e-01,  2.21308445e-01,  3.40000000e-01,  4.80127490e-01,
                      6.30000000e-01,  7.73553391e-01,  8.93012702e-01,  9.72244945e-01,
                      1.00000000e+00,  9.72244945e-01,  8.93012702e-01,  7.73553391e-01,
                      6.30000000e-01,  4.80127490e-01,  3.40000000e-01,  2.21308445e-01,
                      1.30000000e-01,  6.64466094e-02,  2.69872981e-02,  6.31911916e-03,
                      -1.38777878e-17 });

    run_tests(tests, WindowFunctionType::kBlackman);
}

TEST(TestWindowFunction, TypeHamming)
{
    /* np.hamming */
    std::list<std::vector<double>> tests;
    tests.push_back( { 1.0 });
    tests.push_back( { 0.08, 0.08 });
    tests.push_back( { 0.08, 1.  , 0.08 });
    tests.push_back( { 0.08, 0.54, 1.  , 0.54, 0.08 });
    tests.push_back( { 0.08      , 0.18761956, 0.46012184, 0.77      , 0.97225861,
                       0.97225861, 0.77      , 0.46012184, 0.18761956, 0.08 });
    tests.push_back( { 0.08      , 0.09567412, 0.14162831, 0.21473088, 0.31      ,
                       0.42094324, 0.54      , 0.65905676, 0.77      , 0.86526912,
                       0.93837169, 0.98432588, 1.        , 0.98432588, 0.93837169,
                       0.86526912, 0.77      , 0.65905676, 0.54      , 0.42094324,
                       0.31      , 0.21473088, 0.14162831, 0.09567412, 0.08 });

    run_tests(tests, WindowFunctionType::kHamming);
}

TEST(TestWindowFunction, TypeHann)
{
    /* np.hanning */
    std::list<std::vector<double>> tests;
    tests.push_back( { 1.0 });
    tests.push_back( { 0., 0. });
    tests.push_back( { 0., 1., 0. });
    tests.push_back( { 0. , 0.5, 1. , 0.5, 0. });
    tests.push_back( { 0.        , 0.11697778, 0.41317591, 0.75      , 0.96984631,
                       0.96984631, 0.75      , 0.41317591, 0.11697778, 0. });
    tests.push_back( { 0.        , 0.01703709, 0.0669873 , 0.14644661, 0.25      ,
                       0.37059048, 0.5       , 0.62940952, 0.75      , 0.85355339,
                       0.9330127 , 0.98296291, 1.        , 0.98296291, 0.9330127 ,
                       0.85355339, 0.75      , 0.62940952, 0.5       , 0.37059048,
                       0.25      , 0.14644661, 0.0669873 , 0.01703709, 0. });

    run_tests(tests, WindowFunctionType::kHann);
}

TEST(TestWindowFunction, TypeNuttall)
{
    /* scipy.signal.nuttall */
    /* NOTE: Nuttall4c from https://holometer.fnal.gov/GH_FFT.pdf */
    std::list<std::vector<double>> tests;
    tests.push_back( { 1. });
    tests.push_back( { 0.0003628, 0.0003628 });
    tests.push_back( { 3.628e-04, 1.000e+00, 3.628e-04 });
    tests.push_back( { 3.628000e-04, 2.269824e-01, 1.000000e+00, 2.269824e-01,
                       3.628000e-04 });
    tests.push_back( { 3.62800000e-04, 1.78909987e-02, 1.55596126e-01, 5.29229800e-01,
                       9.33220225e-01, 9.33220225e-01, 5.29229800e-01, 1.55596126e-01,
                       1.78909987e-02, 3.62800000e-04 });
    tests.push_back( { 3.62800000e-04, 1.84696229e-03, 8.24150804e-03, 2.52055665e-02,
                       6.13345000e-02, 1.26199203e-01, 2.26982400e-01, 3.64367322e-01,
                       5.29229800e-01, 7.01958233e-01, 8.55521792e-01, 9.61914112e-01,
                       1.00000000e+00, 9.61914112e-01, 8.55521792e-01, 7.01958233e-01,
                       5.29229800e-01, 3.64367322e-01, 2.26982400e-01, 1.26199203e-01,
                       6.13345000e-02, 2.52055665e-02, 8.24150804e-03, 1.84696229e-03,
                       3.62800000e-04 });

    run_tests(tests, WindowFunctionType::kNuttall);
}

TEST(TestWindowFunction, TypeNone)
{
    EXPECT_EQ(WindowFunction::Build(WindowFunctionType::kNone, 1), nullptr);
    EXPECT_EQ(WindowFunction::Build(WindowFunctionType::kNone, 10), nullptr);
}