1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef RDSP_H
18 #define RDSP_H
19 
20 #include <complex>
21 #include <log/log.h>
22 #include <vector>
23 #include <map>
24 using FloatVec = std::vector<float>;
25 using IntVec = std::vector<int>;
26 using ComplexVec  = std::vector<std::complex<float>>;
27 
28 // =======
29 // Helper Functions
30 // =======
31 template <class T>
dBtoLinear(T valueDb)32 static T dBtoLinear(T valueDb) {
33     return pow (10, valueDb / 20.0);
34 }
35 
36 template <class T>
linearToDb(T value)37 static T linearToDb(T value) {
38     return 20 * log10(value);
39 }
40 
41 // =======
42 // DSP window creation
43 // =======
44 
45 #define TWOPI (M_PI * 2)
46 
47 enum rdsp_window_type {
48     RDSP_WINDOW_RECTANGULAR,
49     RDSP_WINDOW_TRIANGULAR,
50     RDSP_WINDOW_TRIANGULAR_FLAT_TOP,
51     RDSP_WINDOW_HAMMING,
52     RDSP_WINDOW_HAMMING_FLAT_TOP,
53     RDSP_WINDOW_HANNING,
54     RDSP_WINDOW_HANNING_FLAT_TOP,
55 };
56 
57 template <typename T>
fillRectangular(T & v)58 static void fillRectangular(T &v) {
59     const size_t size = v.size();
60     for (size_t i = 0; i < size; i++) {
61         v[i] = 1.0;
62     }
63 } //rectangular
64 
65 template <typename T>
fillTriangular(T & v,size_t overlap)66 static void fillTriangular(T &v, size_t overlap) {
67     const size_t size = v.size();
68     //ramp up
69     size_t i = 0;
70     if (overlap > 0) {
71         for (; i < overlap; i++) {
72             v[i] = (2.0 * i + 1) / (2 * overlap);
73         }
74     }
75 
76     //flat top
77     for (; i < size - overlap; i++) {
78         v[i] = 1.0;
79     }
80 
81     //ramp down
82     if (overlap > 0) {
83         for (; i < size; i++) {
84             v[i] = (2.0 * (size - i) - 1) / (2 * overlap);
85         }
86     }
87 } //triangular
88 
89 template <typename T>
fillHamming(T & v,size_t overlap)90 static void fillHamming(T &v, size_t overlap) {
91     const size_t size = v.size();
92     const size_t twoOverlap = 2 * overlap;
93     size_t i = 0;
94     if (overlap > 0) {
95         for (; i < overlap; i++) {
96             v[i] = 0.54 - 0.46 * cos(TWOPI * i /(twoOverlap - 1));
97         }
98     }
99 
100     //flat top
101     for (; i < size - overlap; i++) {
102         v[i] = 1.0;
103     }
104 
105     //ramp down
106     if (overlap > 0) {
107         for (; i < size; i++) {
108             int k = i - ((int)size - 2 * overlap);
109             v[i] = 0.54 - 0.46 * cos(TWOPI * k / (twoOverlap - 1));
110         }
111     }
112 } //hamming
113 
114 template <typename T>
fillHanning(T & v,size_t overlap)115 static void fillHanning(T &v, size_t overlap) {
116     const size_t size = v.size();
117     const size_t twoOverlap = 2 * overlap;
118     //ramp up
119     size_t i = 0;
120     if (overlap > 0) {
121         for (; i < overlap; i++) {
122             v[i] = 0.5 * (1.0 - cos(TWOPI * i / (twoOverlap - 1)));
123         }
124     }
125 
126     //flat top
127     for (; i < size - overlap; i++) {
128         v[i] = 1.0;
129     }
130 
131     //ramp down
132     if (overlap > 0) {
133         for (; i < size; i++) {
134             int k = i - ((int)size - 2 * overlap);
135             v[i] = 0.5 * (1.0 - cos(TWOPI * k / (twoOverlap - 1)));
136         }
137     }
138 }
139 
140 template <typename T>
fill_window(T & v,int type,size_t size,size_t overlap)141 static void fill_window(T &v, int type, size_t size, size_t overlap) {
142     if (overlap > size / 2) {
143         overlap = size / 2;
144     }
145     v.resize(size);
146 
147     switch (type) {
148     case RDSP_WINDOW_RECTANGULAR:
149         fillRectangular(v);
150         break;
151     case RDSP_WINDOW_TRIANGULAR:
152         fillTriangular(v, size / 2);
153         break;
154     case RDSP_WINDOW_TRIANGULAR_FLAT_TOP:
155         fillTriangular(v, overlap);
156         break;
157     case RDSP_WINDOW_HAMMING:
158         fillHamming(v, size / 2);
159         break;
160     case RDSP_WINDOW_HAMMING_FLAT_TOP:
161         fillHamming(v, overlap);
162         break;
163     case RDSP_WINDOW_HANNING:
164         fillHanning(v, size / 2);
165         break;
166     case RDSP_WINDOW_HANNING_FLAT_TOP:
167         fillHanning(v, overlap);
168         break;
169     default:
170         ALOGE("Error: unknown window type %d", type);
171     }
172 }
173 
174 //};
175 #endif //RDSP_H
176