1 | /* |
2 | Copyright 2018 Google Inc. All Rights Reserved. |
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 RESONANCE_AUDIO_BASE_SIMD_UTILS_H_ |
18 | #define RESONANCE_AUDIO_BASE_SIMD_UTILS_H_ |
19 | |
20 | #include <cstddef> |
21 | #include <cstdint> |
22 | |
23 | namespace vraudio { |
24 | |
25 | // Checks if the pointer provided is correctly aligned for SIMD. |
26 | // |
27 | // @param pointer Pointer to check. |
28 | // @return True if the pointer is correctly aligned. |
29 | bool IsAligned(const float* pointer); |
30 | bool IsAligned(const int16_t* pointer); |
31 | |
32 | // Rounds a number of frames up to the next aligned memory address |
33 | // based on |memory_alignment_bytes|. This allows for aligning offset pointers |
34 | // into a single chunk of allocated memory. |
35 | // |
36 | // @param length Number of samples before the desired offset pointer. |
37 | // @param type_size_bytes Size of the type of each entry in the array. |
38 | // @param memory_alignment_bytes Number of bytes to which an address is aligned. |
39 | // @return Number of samples into the memory chunk to ensure aligned memory. |
40 | size_t FindNextAlignedArrayIndex(size_t length, size_t type_size_bytes, |
41 | size_t memory_alignment_bytes); |
42 | |
43 | // Adds a float array |input_a| to another float array |input_b| and stores the |
44 | // result in |output|. |
45 | // |
46 | // @param length Number of floats. |
47 | // @param input_a Pointer to the first float in input_a array. |
48 | // @param input_b Pointer to the first float in input_b array. |
49 | // @param output Pointer to the first float in output array. |
50 | void AddPointwise(size_t length, const float* input_a, const float* input_b, |
51 | float* output); |
52 | |
53 | // Subtracts a float array |input|, pointwise from another float array |output|. |
54 | // |
55 | // @param length Number of floats. |
56 | // @param input Pointer to the first float in input_a array. |
57 | // @param output Pointer to the first float in input_b array. |
58 | // @param output Pointer to the first float in output array. |
59 | void SubtractPointwise(size_t length, const float* input_a, |
60 | const float* input_b, float* output); |
61 | |
62 | // Pointwise multiplies a float array |input_a| with another float array |
63 | // |input_b| and stores the result in |output|. |
64 | // |
65 | // @param length Number of floats. |
66 | // @param input Pointer to the first float in input_a array. |
67 | // @param input Pointer to the first float in input_b array. |
68 | // @param output Pointer to the first float in output array. |
69 | void MultiplyPointwise(size_t length, const float* input_a, |
70 | const float* input_b, float* output); |
71 | |
72 | // Pointwise multiplies a float array |input_a| with another float array |
73 | // |input_b| and adds the result onto |accumulator|. |
74 | // |
75 | // @param length Number of floats. |
76 | // @param input_a Pointer to the first float in input_a array. |
77 | // @param input_b Pointer to the first float in input_b array. |
78 | // @param accumulator Pointer to the first float in accumulator array. |
79 | void MultiplyAndAccumulatePointwise(size_t length, const float* input_a, |
80 | const float* input_b, float* accumulator); |
81 | |
82 | // Multiplies a float array |input| by a scalar |gain| over |length| samples. |
83 | // |
84 | // @param length Number of floats. |
85 | // @param gain Scalar value with which to multiply the input. |
86 | // @param input Pointer to the first float in input array. |
87 | // @param output Pointer to the first float in output array. |
88 | void ScalarMultiply(size_t length, float gain, const float* input, |
89 | float* output); |
90 | |
91 | // Multiplies a float array |input| by a scalar |gain| over |length| samples and |
92 | // adds the result onto |accumulator|. |
93 | // |
94 | // @param length Number of floats. |
95 | // @param gain Scalar value with which to multiply the input. |
96 | // @param input Pointer to the first float in input array. |
97 | // @param output Pointer to the first float in accumulator array. |
98 | void ScalarMultiplyAndAccumulate(size_t length, float gain, const float* input, |
99 | float* accumulator); |
100 | |
101 | // Calculates an approximmate reciprocal square root. |
102 | // |
103 | // @param length Number of floats. |
104 | // @param input Pointer to the first float in input array. |
105 | // @param output Pointer to the first float in output array. |
106 | void ReciprocalSqrt(size_t length, const float* input, float* output); |
107 | |
108 | // Calculates an approximate square root. |
109 | // |
110 | // @param length Number of floats. |
111 | // @param input Pointer to the first float in input array. |
112 | // @param output Pointer to the first float in output array. |
113 | void Sqrt(size_t length, const float* input, float* output); |
114 | |
115 | // Calculates the approximate magnitudes of interleaved complex numbers. |
116 | // |
117 | // @param length Number of complex numbers in the input array, |
118 | // (i.e. half its length). |
119 | // @param input Pointer to the first float in input array. Length: 2 * |length|. |
120 | // @param output Pointer to the first float in output array, Length: |length|. |
121 | void ApproxComplexMagnitude(size_t length, const float* input, float* output); |
122 | |
123 | // Calculates the complex values in interleaved format (real, imaginary), from a |
124 | // vector of magnitudes and of sines and cosines of phase. |
125 | // |
126 | // @param length Number of total entries (real & imaginary) in the input array. |
127 | // @param magnitude Pointer to the first float in the magnitude array, Length: |
128 | // |length| / 2 |
129 | // @param cos_phase Pointer to the first float in the cosine phase array, |
130 | // Length: |length| / 2 |
131 | // @param sin_phase Pointer to the first float in the sine phase array, Length: |
132 | // |length| / 2 |
133 | // @param complex_interleaved_format_output Pointer to the first float in the |
134 | // output array. Length: |length|. |
135 | void ComplexInterleavedFormatFromMagnitudeAndSinCosPhase( |
136 | size_t length, const float* magnitude, const float* cos_phase, |
137 | const float* sin_phase, float* complex_interleaved_format_output); |
138 | |
139 | // Generates an identical left and right pair of stereo channels from a mono |
140 | // input channel, where each channel is the mono channel times 1/sqrt(2). |
141 | // |
142 | // @param length Number of floats. |
143 | // @param mono Pointer to the first float in an input mono array. |
144 | // @param left Pointer to the first float in the left output array. |
145 | // @param right Pointer to the first float in the right output array. |
146 | void StereoFromMonoSimd(size_t length, const float* mono, float* left, |
147 | float* right); |
148 | |
149 | // Generates a mono downmix from a pair of stereo channels, where the output is |
150 | // equal to the sum of the two inputs times 1/sqrt(2). |
151 | // |
152 | // @param length Number of floats. |
153 | // @param left Pointer to the first float in the left input array. |
154 | // @param right Pointer to the first float in the right input array. |
155 | // @param mono Pointer to the first float in an output mono array. |
156 | void MonoFromStereoSimd(size_t length, const float* left, const float* right, |
157 | float* mono); |
158 | |
159 | // Converts an array of 32 bit float input to clamped 16 bit int output. |
160 | // |
161 | // @param length Number of floats in the input array and int16_ts in the output. |
162 | // @param input Float array. |
163 | // @param output Int array. |
164 | void Int16FromFloat(size_t length, const float* input, int16_t* output); |
165 | |
166 | // Converts an array of 16 bit int input to 32 bit float output. |
167 | // |
168 | // @param length Number of int16_ts in the input array and floats in the output. |
169 | // @param input Int array. |
170 | // @param output Float array. |
171 | void FloatFromInt16(size_t length, const int16_t* input, float* output); |
172 | |
173 | // Interleaves a pair of mono buffers of int_16 data into a stereo buffer. |
174 | // |
175 | // @param length Number of frames per mono channel. The interleaved buffer must |
176 | // be twice this size. |
177 | // @param channel_0 Input buffer of mono data for the first channel. |
178 | // @param channel_1 Input buffer of mono data for the second channel. |
179 | // @param interleaved_buffer Output buffer of stereo interleaved data. |
180 | void InterleaveStereo(size_t length, const int16_t* channel_0, |
181 | const int16_t* channel_1, int16_t* interleaved_buffer); |
182 | |
183 | // Interleaves a pair of mono buffers of float data into a stereo buffer. |
184 | // |
185 | // @param length Number of frames per mono channel. The interleaved buffer must |
186 | // be twice this size. |
187 | // @param channel_0 Input buffer of mono data for the first channel. |
188 | // @param channel_1 Input buffer of mono data for the second channel. |
189 | // @param interleaved_buffer Output buffer of stereo interleaved data. |
190 | void InterleaveStereo(size_t length, const float* channel_0, |
191 | const float* channel_1, float* interleaved_buffer); |
192 | |
193 | // Interleaves a pair of mono buffers of float data into a stereo buffer of |
194 | // int16_t data. |
195 | // |
196 | // @param length Number of frames per mono channel. The interleaved buffer must |
197 | // be twice this size. |
198 | // @param channel_0 Input buffer of mono data for the first channel (float). |
199 | // @param channel_1 Input buffer of mono data for the second channel (float). |
200 | // @param interleaved_buffer Output buffer of stereo interleaved data (int16_t). |
201 | void InterleaveStereo(size_t length, const float* channel_0, |
202 | const float* channel_1, int16_t* interleaved_buffer); |
203 | |
204 | // Deinterleaves a stereo buffer of int16_t data into a pair of mono buffers. |
205 | // |
206 | // @param length Number of frames per mono channel. The interleaved buffer must |
207 | // be twice this size. |
208 | // @param interleaved_buffer Input buffer of stereo interleaved data. |
209 | // @param channel_0 Output buffer of mono data for the first channel. |
210 | // @param channel_1 Output buffer of mono data for the second channel. |
211 | void DeinterleaveStereo(size_t length, const int16_t* interleaved_buffer, |
212 | int16_t* channel_0, int16_t* channel_1); |
213 | |
214 | // Deinterleaves a stereo buffer of float data into a pair of mono buffers. |
215 | // |
216 | // @param length Number of frames per mono channel. The interleaved buffer must |
217 | // be twice this size. |
218 | // @param interleaved_buffer Input buffer of stereo interleaved data. |
219 | // @param channel_0 Output buffer of mono data for the first channel. |
220 | // @param channel_1 Output buffer of mono data for the second channel. |
221 | void DeinterleaveStereo(size_t length, const float* interleaved_buffer, |
222 | float* channel_0, float* channel_1); |
223 | |
224 | // Deinterleaves a stereo buffer of int16_t data into a pair of mono float |
225 | // buffers, performing the int16 to floating point conversion. |
226 | // |
227 | // @param length Number of frames per mono channel. The interleaved buffer must |
228 | // be twice this size. |
229 | // @param interleaved_buffer Input buffer of stereo interleaved data (int16_t). |
230 | // @param channel_0 Output buffer of mono data for the first channel (float). |
231 | // @param channel_1 Output buffer of mono data for the second channel (float). |
232 | void DeinterleaveStereo(size_t length, const int16_t* interleaved_buffer, |
233 | float* channel_0, float* channel_1); |
234 | |
235 | // Interleaves four mono buffers of int16_t data into a quad buffer. |
236 | // |
237 | // @param length Number of frames per mono channel. The interleaved buffer must |
238 | // be four times this size and the workspace must be five times this size. |
239 | // @param channel_0 Input buffer of mono data for the first channel. |
240 | // @param channel_1 Input buffer of mono data for the second channel. |
241 | // @param channel_2 Input buffer of mono data for the third channel. |
242 | // @param channel_3 Input buffer of mono data for the fourth channel. |
243 | // @param workspace Aligned buffer of 5 * |length| samples in length. |
244 | // @param interleaved_buffer Output buffer of quad interleaved data. |
245 | void InterleaveQuad(size_t length, const int16_t* channel_0, |
246 | const int16_t* channel_1, const int16_t* channel_2, |
247 | const int16_t* channel_3, int16_t* workspace, |
248 | int16_t* interleaved_buffer); |
249 | |
250 | // Interleaves four mono buffers of float data into a quad buffer. |
251 | // |
252 | // @param length Number of frames per mono channel. The interleaved buffer must |
253 | // be four times this size and the workspace must be five times this size. |
254 | // @param channel_0 Input buffer of mono data for the first channel. |
255 | // @param channel_1 Input buffer of mono data for the second channel. |
256 | // @param channel_2 Input buffer of mono data for the third channel. |
257 | // @param channel_3 Input buffer of mono data for the fourth channel. |
258 | // @param workspace Aligned buffer of 5 * |length| samples in length. |
259 | // @param interleaved_buffer Output buffer of quad interleaved data. |
260 | void InterleaveQuad(size_t length, const float* channel_0, |
261 | const float* channel_1, const float* channel_2, |
262 | const float* channel_3, float* workspace, |
263 | float* interleaved_buffer); |
264 | |
265 | // Deinterleaves a quad buffer of int16_t data into four mono buffers. |
266 | // |
267 | // @param length Number of frames per mono channel. The interleaved buffer must |
268 | // be four times this size and the workspace must be five times this size. |
269 | // @param interleaved_buffer Input buffer of quad interleaved data. |
270 | // @param workspace Aligned buffer of 5 * |length| samples in length. |
271 | // @param channel_0 Output buffer of mono data for the first channel. |
272 | // @param channel_1 Output buffer of mono data for the second channel. |
273 | // @param channel_2 Output buffer of mono data for the third channel. |
274 | // @param channel_3 Output buffer of mono data for the fourth channel. |
275 | void DeinterleaveQuad(size_t length, const int16_t* interleaved_buffer, |
276 | int16_t* workspace, int16_t* channel_0, |
277 | int16_t* channel_1, int16_t* channel_2, |
278 | int16_t* channel_3); |
279 | |
280 | // Deinterleaves a quad buffer of float data into four mono buffers. |
281 | // |
282 | // @param length Number of frames per mono channel. The interleaved buffer must |
283 | // be four times this size and the workspace must be five times this size. |
284 | // @param interleaved_buffer Input buffer of quad interleaved data. |
285 | // @param workspace Aligned buffer of 5 * |length| samples in length. |
286 | // @param channel_0 Output buffer of mono data for the first channel. |
287 | // @param channel_1 Output buffer of mono data for the second channel. |
288 | // @param channel_2 Output buffer of mono data for the third channel. |
289 | // @param channel_3 Output buffer of mono data for the fourth channel. |
290 | void DeinterleaveQuad(size_t length, const float* interleaved_buffer, |
291 | float* workspace, float* channel_0, float* channel_1, |
292 | float* channel_2, float* channel_3); |
293 | |
294 | } // namespace vraudio |
295 | |
296 | #endif // RESONANCE_AUDIO_BASE_SIMD_UTILS_H_ |
297 | |