| 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 | |