1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11 Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12
13 End User License Agreement: www.juce.com/juce-6-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24 */
25
26 namespace juce
27 {
28 namespace dsp
29 {
30
31 template <typename FloatType>
ncos(size_t order,size_t i,size_t size)32 static FloatType ncos (size_t order, size_t i, size_t size) noexcept
33 {
34 return std::cos (static_cast<FloatType> (order * i)
35 * MathConstants<FloatType>::pi / static_cast<FloatType> (size - 1));
36 }
37
38 template <typename FloatType>
WindowingFunction(size_t size,WindowingMethod type,bool normalise,FloatType beta)39 WindowingFunction<FloatType>::WindowingFunction (size_t size, WindowingMethod type, bool normalise, FloatType beta)
40 {
41 fillWindowingTables (size, type, normalise, beta);
42 }
43
44 template <typename FloatType>
fillWindowingTables(size_t size,WindowingMethod type,bool normalise,FloatType beta)45 void WindowingFunction<FloatType>::fillWindowingTables (size_t size, WindowingMethod type,
46 bool normalise, FloatType beta) noexcept
47 {
48 windowTable.resize (static_cast<int> (size));
49 fillWindowingTables (windowTable.getRawDataPointer(), size, type, normalise, beta);
50 }
51
52 template <typename FloatType>
fillWindowingTables(FloatType * samples,size_t size,WindowingMethod type,bool normalise,FloatType beta)53 void WindowingFunction<FloatType>::fillWindowingTables (FloatType* samples, size_t size,
54 WindowingMethod type, bool normalise,
55 FloatType beta) noexcept
56 {
57 switch (type)
58 {
59 case rectangular:
60 {
61 for (size_t i = 0; i < size; ++i)
62 samples[i] = static_cast<FloatType> (1);
63 }
64 break;
65
66 case triangular:
67 {
68 auto halfSlots = static_cast<FloatType> (0.5) * static_cast<FloatType> (size - 1);
69
70 for (size_t i = 0; i < size; ++i)
71 samples[i] = static_cast<FloatType> (1.0) - std::abs ((static_cast<FloatType> (i) - halfSlots) / halfSlots);
72 }
73 break;
74
75 case hann:
76 {
77 for (size_t i = 0; i < size; ++i)
78 {
79 auto cos2 = ncos<FloatType> (2, i, size);
80 samples[i] = static_cast<FloatType> (0.5 - 0.5 * cos2);
81 }
82 }
83 break;
84
85 case hamming:
86 {
87 for (size_t i = 0; i < size; ++i)
88 {
89 auto cos2 = ncos<FloatType> (2, i, size);
90 samples[i] = static_cast<FloatType> (0.54 - 0.46 * cos2);
91 }
92 }
93 break;
94
95 case blackman:
96 {
97 constexpr FloatType alpha = 0.16f;
98
99 for (size_t i = 0; i < size; ++i)
100 {
101 auto cos2 = ncos<FloatType> (2, i, size);
102 auto cos4 = ncos<FloatType> (4, i, size);
103
104 samples[i] = static_cast<FloatType> (0.5 * (1 - alpha) - 0.5 * cos2 + 0.5 * alpha * cos4);
105 }
106 }
107 break;
108
109 case blackmanHarris:
110 {
111 for (size_t i = 0; i < size; ++i)
112 {
113 auto cos2 = ncos<FloatType> (2, i, size);
114 auto cos4 = ncos<FloatType> (4, i, size);
115 auto cos6 = ncos<FloatType> (6, i, size);
116
117 samples[i] = static_cast<FloatType> (0.35875 - 0.48829 * cos2 + 0.14128 * cos4 - 0.01168 * cos6);
118 }
119 }
120 break;
121
122 case flatTop:
123 {
124 for (size_t i = 0; i < size; ++i)
125 {
126 auto cos2 = ncos<FloatType> (2, i, size);
127 auto cos4 = ncos<FloatType> (4, i, size);
128 auto cos6 = ncos<FloatType> (6, i, size);
129 auto cos8 = ncos<FloatType> (8, i, size);
130
131 samples[i] = static_cast<FloatType> (1.0 - 1.93 * cos2 + 1.29 * cos4 - 0.388 * cos6 + 0.028 * cos8);
132 }
133 }
134 break;
135
136 case kaiser:
137 {
138 const double factor = 1.0 / SpecialFunctions::besselI0 (beta);
139 const auto doubleSize = (double) size;
140
141 for (size_t i = 0; i < size; ++i)
142 samples[i] = static_cast<FloatType> (SpecialFunctions::besselI0 (beta * std::sqrt (1.0 - std::pow (((double) i - 0.5 * (doubleSize - 1.0))
143 / ( 0.5 * (doubleSize - 1.0)), 2.0)))
144 * factor);
145 }
146 break;
147
148 case numWindowingMethods:
149 default:
150 jassertfalse;
151 break;
152 }
153
154 // DC frequency amplitude must be one
155 if (normalise)
156 {
157 FloatType sum (0);
158
159 for (size_t i = 0; i < size; ++i)
160 sum += samples[i];
161
162 auto factor = static_cast<FloatType> (size) / sum;
163
164 FloatVectorOperations::multiply (samples, factor, static_cast<int> (size));
165 }
166 }
167
168 template <typename FloatType>
multiplyWithWindowingTable(FloatType * samples,size_t size)169 void WindowingFunction<FloatType>::multiplyWithWindowingTable (FloatType* samples, size_t size) noexcept
170 {
171 FloatVectorOperations::multiply (samples, windowTable.getRawDataPointer(), jmin (static_cast<int> (size), windowTable.size()));
172 }
173
174 template <typename FloatType>
getWindowingMethodName(WindowingMethod type)175 const char* WindowingFunction<FloatType>::getWindowingMethodName (WindowingMethod type) noexcept
176 {
177 switch (type)
178 {
179 case rectangular: return "Rectangular";
180 case triangular: return "Triangular";
181 case hann: return "Hann";
182 case hamming: return "Hamming";
183 case blackman: return "Blackman";
184 case blackmanHarris: return "Blackman-Harris";
185 case flatTop: return "Flat Top";
186 case kaiser: return "Kaiser";
187 case numWindowingMethods:
188 default: jassertfalse; return "";
189 }
190 }
191
192 template class WindowingFunction<float>;
193 template class WindowingFunction<double>;
194
195 } // namespace dsp
196 } // namespace juce
197