summaryrefslogtreecommitdiff
path: root/shared/signal_processing.h
blob: 857d0b123291be26242607563214845b05ee41e5 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html       *
// * Copyright (C) 2008-2010 ZenJu (zhnmju123 AT gmx.de)                    *
// **************************************************************************
//
#include <algorithm>
#include <limits>
#include <numeric>


namespace util
{
template <class T>
T abs(T value);

int round(double d); //little rounding function

template <class T>
bool isNull(T number);

//----------------------------------------------------------------------------------
//       smoothen data ranges through a window around each data point              |
//----------------------------------------------------------------------------------
template <class InputIterator, class OutputIterator>
void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize); //default implementation: averaging

template <class InputIterator, class OutputIterator, class DataProcessor>
void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize, DataProcessor proc);
/*
DataProcessor is an abstraction for data evaluation. A valid implementation needs to support three properties:
- add data entry at window front:   operator+=(ValueType value)
- remove data entry at window back: operator-=(ValueType value)
- evaluate smoothed middle value:   ValueType operator()(size_t windowSize)
*/
//----------------------------------------------------------------------------------






















//################# inline implementation #########################
template <class T>
inline
T abs(T value)
{
    return value < 0 ? -value : value;
}


template <class T>
inline
bool isNull(T value)
{
    return abs(number) <= std::numeric_limits<T>::epsilon(); //epsilon == 0 for integer types, therefore less-equal(!)
}


inline
int round(double d)
{
    return static_cast<int>(d < 0 ? d - .5 : d + .5);
}


template <class InputIterator, class OutputIterator, class DataProcessor>
inline
void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize, DataProcessor proc)
{
    windowSize = std::min(windowSize, static_cast<size_t>(last - first)); //std::distance() not used to enforce random access iterator requirement

    if (windowSize <= 1)
    {
        std::copy(first, last, result);
        return;
    }

    const size_t firstHalf = windowSize / 2;
    const size_t secondHalf = windowSize - firstHalf;

    //preparation
    for (InputIterator i = first; i != first + secondHalf; ++i)
        proc += *i;

    //beginning
    for (InputIterator i = first; i != first + firstHalf; ++i)
    {
        *result++ = proc(i - first + secondHalf);
        proc += *(i + secondHalf);
    }

    //main
    for (InputIterator i = first + firstHalf; i != last - secondHalf; ++i)
    {
        *result++ = proc(windowSize);
        proc += *(i + secondHalf);
        proc -= *(i - firstHalf);
    }

    //ending
    for (InputIterator i = last - secondHalf; i != last; ++i)
    {
        *result++ = proc(windowSize - (i - last + secondHalf));
        proc -= *(i - firstHalf);
    }
}


template <class ValueType>
class ProcessorAverage
{
public:
    ProcessorAverage() : valueAcc() {}

    //add front data entry
    ProcessorAverage& operator+=(ValueType value)
    {
        valueAcc += value;
        return *this;
    }

    //remove rear data entry
    ProcessorAverage& operator-=(ValueType value)
    {
        valueAcc -= value;
        return *this;
    }

    //evaluate smoothed value
    ValueType operator()(size_t windowSize) const
    {
        return valueAcc / windowSize;
    }

private:
    ValueType valueAcc; //accumulated values
};



template <class InputIterator, class OutputIterator>
inline
void smoothen(InputIterator first, InputIterator last, OutputIterator result, size_t windowSize)
{
    typedef typename std::iterator_traits<InputIterator>::value_type ValueType;
    smoothen(first, last, result, windowSize, ProcessorAverage<ValueType>());
}

}
bgstack15