Source code

Revision control

Copy as Markdown

/*
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
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_