summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/resonance-audio/resonance_audio/base/simd_utils.h
blob: 64fb9c6d1aaf188f2fc5a78e3eb4c77892fe51d5 (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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
Copyright 2018 Google Inc. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS-IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

#ifndef RESONANCE_AUDIO_BASE_SIMD_UTILS_H_
#define RESONANCE_AUDIO_BASE_SIMD_UTILS_H_

#include <cstddef>
#include <cstdint>

namespace vraudio {

// Checks if the pointer provided is correctly aligned for SIMD.
//
// @param pointer Pointer to check.
// @return True if the pointer is correctly aligned.
bool IsAligned(const float* pointer);
bool IsAligned(const int16_t* pointer);

// Rounds a number of frames up to the next aligned memory address
// based on |memory_alignment_bytes|. This allows for aligning offset pointers
// into a single chunk of allocated memory.
//
// @param length Number of samples before the desired offset pointer.
// @param type_size_bytes Size of the type of each entry in the array.
// @param memory_alignment_bytes Number of bytes to which an address is aligned.
// @return Number of samples into the memory chunk to ensure aligned memory.
size_t FindNextAlignedArrayIndex(size_t length, size_t type_size_bytes,
                                 size_t memory_alignment_bytes);

// Adds a float array |input_a| to another float array |input_b| and stores the
// result in |output|.
//
// @param length Number of floats.
// @param input_a Pointer to the first float in input_a array.
// @param input_b Pointer to the first float in input_b array.
// @param output Pointer to the first float in output array.
void AddPointwise(size_t length, const float* input_a, const float* input_b,
                  float* output);

// Subtracts a float array |input|, pointwise from another float array |output|.
//
// @param length Number of floats.
// @param input Pointer to the first float in input_a array.
// @param output Pointer to the first float in input_b array.
// @param output Pointer to the first float in output array.
void SubtractPointwise(size_t length, const float* input_a,
                       const float* input_b, float* output);

// Pointwise multiplies a float array |input_a| with another float array
// |input_b| and stores the result in |output|.
//
// @param length Number of floats.
// @param input Pointer to the first float in input_a array.
// @param input Pointer to the first float in input_b array.
// @param output Pointer to the first float in output array.
void MultiplyPointwise(size_t length, const float* input_a,
                       const float* input_b, float* output);

// Pointwise multiplies a float array |input_a| with another float array
// |input_b| and adds the result onto |accumulator|.
//
// @param length Number of floats.
// @param input_a Pointer to the first float in input_a array.
// @param input_b Pointer to the first float in input_b array.
// @param accumulator Pointer to the first float in accumulator array.
void MultiplyAndAccumulatePointwise(size_t length, const float* input_a,
                                    const float* input_b, float* accumulator);

// Multiplies a float array |input| by a scalar |gain| over |length| samples.
//
// @param length Number of floats.
// @param gain Scalar value with which to multiply the input.
// @param input Pointer to the first float in input array.
// @param output Pointer to the first float in output array.
void ScalarMultiply(size_t length, float gain, const float* input,
                    float* output);

// Multiplies a float array |input| by a scalar |gain| over |length| samples and
// adds the result onto |accumulator|.
//
// @param length Number of floats.
// @param gain Scalar value with which to multiply the input.
// @param input Pointer to the first float in input array.
// @param output Pointer to the first float in accumulator array.
void ScalarMultiplyAndAccumulate(size_t length, float gain, const float* input,
                                 float* accumulator);

// Calculates an approximmate reciprocal square root.
//
// @param length Number of floats.
// @param input Pointer to the first float in input array.
// @param output Pointer to the first float in output array.
void ReciprocalSqrt(size_t length, const float* input, float* output);

// Calculates an approximate square root.
//
// @param length Number of floats.
// @param input Pointer to the first float in input array.
// @param output Pointer to the first float in output array.
void Sqrt(size_t length, const float* input, float* output);

// Calculates the approximate magnitudes of interleaved complex numbers.
//
// @param length Number of complex numbers in the input array,
//     (i.e. half its length).
// @param input Pointer to the first float in input array. Length: 2 * |length|.
// @param output Pointer to the first float in output array, Length: |length|.
void ApproxComplexMagnitude(size_t length, const float* input, float* output);

// Calculates the complex values in interleaved format (real, imaginary), from a
// vector of magnitudes and of sines and cosines of phase.
//
// @param length Number of total entries (real & imaginary) in the input array.
// @param magnitude Pointer to the first float in the magnitude array, Length:
//     |length| /  2
// @param cos_phase Pointer to the first float in the cosine phase array,
//      Length: |length| /  2
// @param sin_phase Pointer to the first float in the sine phase array, Length:
//     |length| /  2
// @param complex_interleaved_format_output Pointer to the first float in the
//     output array. Length: |length|.
void ComplexInterleavedFormatFromMagnitudeAndSinCosPhase(
    size_t length, const float* magnitude, const float* cos_phase,
    const float* sin_phase, float* complex_interleaved_format_output);

// Generates an identical left and right pair of stereo channels from a mono
// input channel, where each channel is the mono channel times 1/sqrt(2).
//
// @param length Number of floats.
// @param mono Pointer to the first float in an input mono array.
// @param left Pointer to the first float in the left output array.
// @param right Pointer to the first float in the right output array.
void StereoFromMonoSimd(size_t length, const float* mono, float* left,
                        float* right);

// Generates a mono downmix from a pair of stereo channels, where the output is
// equal to the sum of the two inputs times 1/sqrt(2).
//
// @param length Number of floats.
// @param left Pointer to the first float in the left input array.
// @param right Pointer to the first float in the right input array.
// @param mono Pointer to the first float in an output mono array.
void MonoFromStereoSimd(size_t length, const float* left, const float* right,
                        float* mono);

// Converts an array of 32 bit float input to clamped 16 bit int output.
//
// @param length Number of floats in the input array and int16_ts in the output.
// @param input Float array.
// @param output Int array.
void Int16FromFloat(size_t length, const float* input, int16_t* output);

// Converts an array of 16 bit int input to 32 bit float output.
//
// @param length Number of int16_ts in the input array and floats in the output.
// @param input Int array.
// @param output Float array.
void FloatFromInt16(size_t length, const int16_t* input, float* output);

// Interleaves a pair of mono buffers of int_16 data into a stereo buffer.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be twice this size.
// @param channel_0 Input buffer of mono data for the first channel.
// @param channel_1 Input buffer of mono data for the second channel.
// @param interleaved_buffer Output buffer of stereo interleaved data.
void InterleaveStereo(size_t length, const int16_t* channel_0,
                      const int16_t* channel_1, int16_t* interleaved_buffer);

// Interleaves a pair of mono buffers of float data into a stereo buffer.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be twice this size.
// @param channel_0 Input buffer of mono data for the first channel.
// @param channel_1 Input buffer of mono data for the second channel.
// @param interleaved_buffer Output buffer of stereo interleaved data.
void InterleaveStereo(size_t length, const float* channel_0,
                      const float* channel_1, float* interleaved_buffer);

// Interleaves a pair of mono buffers of float data into a stereo buffer of
// int16_t data.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be twice this size.
// @param channel_0 Input buffer of mono data for the first channel (float).
// @param channel_1 Input buffer of mono data for the second channel (float).
// @param interleaved_buffer Output buffer of stereo interleaved data (int16_t).
void InterleaveStereo(size_t length, const float* channel_0,
                      const float* channel_1, int16_t* interleaved_buffer);

// Deinterleaves a stereo buffer of int16_t data into a pair of mono buffers.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be twice this size.
// @param interleaved_buffer Input buffer of stereo interleaved data.
// @param channel_0 Output buffer of mono data for the first channel.
// @param channel_1 Output buffer of mono data for the second channel.
void DeinterleaveStereo(size_t length, const int16_t* interleaved_buffer,
                        int16_t* channel_0, int16_t* channel_1);

// Deinterleaves a stereo buffer of float data into a pair of mono buffers.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be twice this size.
// @param interleaved_buffer Input buffer of stereo interleaved data.
// @param channel_0 Output buffer of mono data for the first channel.
// @param channel_1 Output buffer of mono data for the second channel.
void DeinterleaveStereo(size_t length, const float* interleaved_buffer,
                        float* channel_0, float* channel_1);

// Deinterleaves a stereo buffer of int16_t data into a pair of mono float
// buffers, performing the int16 to floating point conversion.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be twice this size.
// @param interleaved_buffer Input buffer of stereo interleaved data (int16_t).
// @param channel_0 Output buffer of mono data for the first channel (float).
// @param channel_1 Output buffer of mono data for the second channel (float).
void DeinterleaveStereo(size_t length, const int16_t* interleaved_buffer,
                        float* channel_0, float* channel_1);

// Interleaves four mono buffers of int16_t data into a quad buffer.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be four times this size and the workspace must be five times this size.
// @param channel_0 Input buffer of mono data for the first channel.
// @param channel_1 Input buffer of mono data for the second channel.
// @param channel_2 Input buffer of mono data for the third channel.
// @param channel_3 Input buffer of mono data for the fourth channel.
// @param workspace Aligned buffer of 5 * |length| samples in length.
// @param interleaved_buffer Output buffer of quad interleaved data.
void InterleaveQuad(size_t length, const int16_t* channel_0,
                    const int16_t* channel_1, const int16_t* channel_2,
                    const int16_t* channel_3, int16_t* workspace,
                    int16_t* interleaved_buffer);

// Interleaves four mono buffers of float data into a quad buffer.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be four times this size and the workspace must be five times this size.
// @param channel_0 Input buffer of mono data for the first channel.
// @param channel_1 Input buffer of mono data for the second channel.
// @param channel_2 Input buffer of mono data for the third channel.
// @param channel_3 Input buffer of mono data for the fourth channel.
// @param workspace Aligned buffer of 5 * |length| samples in length.
// @param interleaved_buffer Output buffer of quad interleaved data.
void InterleaveQuad(size_t length, const float* channel_0,
                    const float* channel_1, const float* channel_2,
                    const float* channel_3, float* workspace,
                    float* interleaved_buffer);

// Deinterleaves a quad buffer of int16_t data into four mono buffers.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be four times this size and the workspace must be five times this size.
// @param interleaved_buffer Input buffer of quad interleaved data.
// @param workspace Aligned buffer of 5 * |length| samples in length.
// @param channel_0 Output buffer of mono data for the first channel.
// @param channel_1 Output buffer of mono data for the second channel.
// @param channel_2 Output buffer of mono data for the third channel.
// @param channel_3 Output buffer of mono data for the fourth channel.
void DeinterleaveQuad(size_t length, const int16_t* interleaved_buffer,
                      int16_t* workspace, int16_t* channel_0,
                      int16_t* channel_1, int16_t* channel_2,
                      int16_t* channel_3);

// Deinterleaves a quad buffer of float data into four mono buffers.
//
// @param length Number of frames per mono channel. The interleaved buffer must
//     be four times this size and the workspace must be five times this size.
// @param interleaved_buffer Input buffer of quad interleaved data.
// @param workspace Aligned buffer of 5 * |length| samples in length.
// @param channel_0 Output buffer of mono data for the first channel.
// @param channel_1 Output buffer of mono data for the second channel.
// @param channel_2 Output buffer of mono data for the third channel.
// @param channel_3 Output buffer of mono data for the fourth channel.
void DeinterleaveQuad(size_t length, const float* interleaved_buffer,
                      float* workspace, float* channel_0, float* channel_1,
                      float* channel_2, float* channel_3);

}  // namespace vraudio

#endif  // RESONANCE_AUDIO_BASE_SIMD_UTILS_H_