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