2019-12-26 14:45:42 -05:00
// Copyright Epic Games, Inc. All Rights Reserved.
2018-06-27 16:58:34 -04:00
# include "DSP/BufferVectorOperations.h"
# define AUDIO_USE_SIMD 1
namespace Audio
{
2020-02-09 18:57:53 -05:00
static void RestrictedPtrAliasCheck ( const float * RESTRICT Ptr1 , const float * RESTRICT Ptr2 , uint32 NumFloatsInArray )
{
2020-02-09 19:24:58 -05:00
checkf ( static_cast < uint32 > ( FMath : : Abs ( Ptr1 - Ptr2 ) ) > = NumFloatsInArray ,
2020-02-09 18:57:53 -05:00
TEXT ( " Using this function as an in-place operation will result in undefined behavior! " ) ) ;
}
2019-05-05 21:00:38 -04:00
/* Sets a values to zero if value is denormal. Denormal numbers significantly slow down floating point operations. */
2020-09-15 13:08:34 -04:00
void BufferUnderflowClampFast ( FAlignedFloatBuffer & InOutBuffer )
2019-05-05 21:00:38 -04:00
{
BufferUnderflowClampFast ( InOutBuffer . GetData ( ) , InOutBuffer . Num ( ) ) ;
}
/* Sets a values to zero if value is denormal. Denormal numbers significantly slow down floating point operations. */
void BufferUnderflowClampFast ( float * RESTRICT InOutBuffer , const int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < float * > ( InOutBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float VFMIN = MakeVectorRegister ( FLT_MIN , FLT_MIN , FLT_MIN , FLT_MIN ) ;
const VectorRegister4Float VNFMIN = MakeVectorRegister ( - FLT_MIN , - FLT_MIN , - FLT_MIN , - FLT_MIN ) ;
2019-05-05 21:00:38 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float VInOut = VectorLoadAligned ( & InOutBuffer [ i ] ) ;
2019-05-05 21:00:38 -04:00
// Create mask of denormal numbers.
2021-05-05 15:07:25 -04:00
VectorRegister4Float Mask = VectorBitwiseAnd ( VectorCompareGT ( VInOut , VNFMIN ) , VectorCompareLT ( VInOut , VFMIN ) ) ;
2019-05-05 21:00:38 -04:00
// Choose between zero or original number based upon mask.
VInOut = VectorSelect ( Mask , GlobalVectorConstants : : FloatZero , VInOut ) ;
VectorStoreAligned ( VInOut , & InOutBuffer [ i ] ) ;
}
}
2019-11-06 18:28:39 -05:00
/* Clamps values in the buffer to be between InMinValue and InMaxValue */
2021-05-04 16:05:46 -04:00
void BufferRangeClampFast ( FAlignedFloatBuffer & InOutBuffer , float InMinValue , float InMaxValue )
2019-11-06 18:28:39 -05:00
{
return BufferRangeClampFast ( InOutBuffer . GetData ( ) , InOutBuffer . Num ( ) , InMinValue , InMaxValue ) ;
}
/* Clamps values in the buffer to be between InMinValue and InMaxValue */
void BufferRangeClampFast ( float * RESTRICT InOutBuffer , const int32 InNum , float InMinValue , float InMaxValue )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < float * > ( InOutBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-11-06 18:28:39 -05:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float VMinVal = MakeVectorRegister ( InMinValue , InMinValue , InMinValue , InMinValue ) ;
const VectorRegister4Float VMaxVal = MakeVectorRegister ( InMaxValue , InMaxValue , InMaxValue , InMaxValue ) ;
2019-11-06 18:28:39 -05:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-11-06 18:28:39 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float VInOut = VectorLoadAligned ( & InOutBuffer [ i ] ) ;
2019-11-06 18:28:39 -05:00
// Create masks to flag elements outside of range.
2021-05-05 15:07:25 -04:00
VectorRegister4Float MinMask = VectorCompareLT ( VInOut , VMinVal ) ;
VectorRegister4Float MaxMask = VectorCompareGT ( VInOut , VMaxVal ) ;
2019-11-06 18:28:39 -05:00
// Choose between range extremes or original number based on masks.
VInOut = VectorSelect ( MinMask , VMinVal , VInOut ) ;
VInOut = VectorSelect ( MaxMask , VMaxVal , VInOut ) ;
VectorStoreAligned ( VInOut , & InOutBuffer [ i ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void BufferMultiplyByConstant ( const FAlignedFloatBuffer & InFloatBuffer , float InValue , FAlignedFloatBuffer & OutFloatBuffer )
2018-06-27 16:58:34 -04:00
{
// Prepare output buffer
OutFloatBuffer . Reset ( ) ;
OutFloatBuffer . AddUninitialized ( InFloatBuffer . Num ( ) ) ;
check ( InFloatBuffer . Num ( ) = = OutFloatBuffer . Num ( ) ) ;
const int32 NumSamples = InFloatBuffer . Num ( ) ;
// Get ptrs to audio buffers to avoid bounds check in non-shipping builds
const float * InBufferPtr = InFloatBuffer . GetData ( ) ;
float * OutBufferPtr = OutFloatBuffer . GetData ( ) ;
2019-05-05 21:00:38 -04:00
BufferMultiplyByConstant ( InBufferPtr , InValue , OutBufferPtr , NumSamples ) ;
}
void BufferMultiplyByConstant ( const float * RESTRICT InFloatBuffer , float InValue , float * RESTRICT OutFloatBuffer , const int32 InNumSamples )
{
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
2019-05-05 21:00:38 -04:00
for ( int32 i = 0 ; i < InNumSamples ; + + i )
2018-06-27 16:58:34 -04:00
{
2019-05-05 21:00:38 -04:00
OutFloatBuffer [ i ] = InValue * InFloatBuffer [ i ] ;
2018-06-27 16:58:34 -04:00
}
# else
2021-03-25 23:30:50 -04:00
RestrictedPtrAliasCheck ( InFloatBuffer , OutFloatBuffer , InNumSamples ) ;
2018-06-27 16:58:34 -04:00
// Can only SIMD on multiple of 4 buffers, we'll do normal multiples on last bit
2021-05-11 19:04:43 -04:00
const int32 NumSamplesRemaining = InNumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
const int32 NumSamplesToSimd = InNumSamples - NumSamplesRemaining ;
2018-06-27 16:58:34 -04:00
// Load the single value we want to multiply all values by into a vector register
2021-05-05 15:07:25 -04:00
const VectorRegister4Float MultiplyValue = VectorLoadFloat1 ( & InValue ) ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamplesToSimd ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
// Load the next 4 samples of the input buffer into a register
2021-05-05 15:07:25 -04:00
VectorRegister4Float InputBufferRegister = VectorLoadAligned ( & InFloatBuffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
// Perform the multiply
2021-05-05 15:07:25 -04:00
VectorRegister4Float Temp = VectorMultiply ( InputBufferRegister , MultiplyValue ) ;
2018-06-27 16:58:34 -04:00
// Store results into the output buffer
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Temp , & OutFloatBuffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
}
// Perform remaining non-simd values left over
for ( int32 i = 0 ; i < NumSamplesRemaining ; + + i )
{
2019-05-05 21:00:38 -04:00
OutFloatBuffer [ NumSamplesToSimd + i ] = InValue * InFloatBuffer [ NumSamplesToSimd + i ] ;
2018-06-27 16:58:34 -04:00
}
# endif
}
2021-05-04 16:05:46 -04:00
void MultiplyBufferByConstantInPlace ( FAlignedFloatBuffer & InBuffer , float InGain )
2019-01-08 11:38:48 -05:00
{
MultiplyBufferByConstantInPlace ( InBuffer . GetData ( ) , InBuffer . Num ( ) , InGain ) ;
}
2019-01-30 05:36:44 -05:00
void MultiplyBufferByConstantInPlace ( float * RESTRICT InBuffer , int32 NumSamples , float InGain )
2019-01-08 11:38:48 -05:00
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Gain = VectorLoadFloat1 ( & InGain ) ;
2019-01-08 11:38:48 -05:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-01-08 11:38:48 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorLoadAligned ( & InBuffer [ i ] ) ;
2019-01-08 11:38:48 -05:00
Output = VectorMultiply ( Output , Gain ) ;
VectorStoreAligned ( Output , & InBuffer [ i ] ) ;
}
}
2019-08-02 20:28:14 -04:00
// Adds a constant to a buffer (useful for DC offset removal)
2021-05-04 16:05:46 -04:00
void AddConstantToBufferInplace ( FAlignedFloatBuffer & InBuffer , float InConstant )
2019-08-02 20:28:14 -04:00
{
AddConstantToBufferInplace ( InBuffer . GetData ( ) , InBuffer . Num ( ) , InConstant ) ;
}
void AddConstantToBufferInplace ( float * RESTRICT InBuffer , int32 NumSamples , float InConstant )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Constant = VectorLoadFloat1 ( & InConstant ) ;
2019-08-02 20:28:14 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-08-02 20:28:14 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorLoadAligned ( & InBuffer [ i ] ) ;
2019-08-02 20:28:14 -04:00
Output = VectorAdd ( Output , Constant ) ;
VectorStoreAligned ( Output , & InBuffer [ i ] ) ;
}
}
2021-05-04 16:05:46 -04:00
void BufferSetToConstantInplace ( FAlignedFloatBuffer & InBuffer , float InConstant )
2020-04-06 17:13:33 -04:00
{
BufferSetToConstantInplace ( InBuffer . GetData ( ) , InBuffer . Num ( ) , InConstant ) ;
}
void BufferSetToConstantInplace ( float * RESTRICT InBuffer , int32 NumSamples , float InConstant )
{
2021-05-11 19:04:43 -04:00
checkf ( NumSamples > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2021-04-06 23:20:55 -04:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Constant = VectorLoadFloat1 ( & InConstant ) ;
2020-04-06 17:13:33 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2020-04-06 17:13:33 -04:00
{
VectorStoreAligned ( Constant , & InBuffer [ i ] ) ;
}
}
2019-05-05 21:00:38 -04:00
/* Performs an element-wise weighted sum OutputBuffer = (InBuffer1 x InGain1) + (InBuffer2 x InGain2) */
2020-09-15 13:08:34 -04:00
void BufferWeightedSumFast ( const FAlignedFloatBuffer & InBuffer1 , float InGain1 , const FAlignedFloatBuffer & InBuffer2 , float InGain2 , FAlignedFloatBuffer & OutBuffer )
2019-05-05 21:00:38 -04:00
{
checkf ( InBuffer1 . Num ( ) = = InBuffer2 . Num ( ) , TEXT ( " Buffers must be equal length " ) ) ;
OutBuffer . Reset ( ) ;
OutBuffer . AddUninitialized ( InBuffer1 . Num ( ) ) ;
BufferWeightedSumFast ( InBuffer1 . GetData ( ) , InGain1 , InBuffer2 . GetData ( ) , InGain2 , OutBuffer . GetData ( ) , InBuffer1 . Num ( ) ) ;
}
/* Performs an element-wise weighted sum OutputBuffer = (InBuffer1 x InGain1) + InBuffer2 */
2020-09-15 13:08:34 -04:00
void BufferWeightedSumFast ( const FAlignedFloatBuffer & InBuffer1 , float InGain1 , const FAlignedFloatBuffer & InBuffer2 , FAlignedFloatBuffer & OutBuffer )
2019-05-05 21:00:38 -04:00
{
checkf ( InBuffer1 . Num ( ) = = InBuffer2 . Num ( ) , TEXT ( " Buffers must be equal length " ) ) ;
OutBuffer . Reset ( ) ;
OutBuffer . AddUninitialized ( InBuffer1 . Num ( ) ) ;
BufferWeightedSumFast ( InBuffer1 . GetData ( ) , InGain1 , InBuffer2 . GetData ( ) , OutBuffer . GetData ( ) , InBuffer1 . Num ( ) ) ;
}
/* Performs an element-wise weighted sum OutputBuffer = (InBuffer1 x InGain1) + (InBuffer2 x InGain2) */
void BufferWeightedSumFast ( const float * RESTRICT InBuffer1 , float InGain1 , const float * RESTRICT InBuffer2 , float InGain2 , float * RESTRICT OutBuffer , int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InBuffer1 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InBuffer2 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InBuffer1 , OutBuffer , InNum ) ;
RestrictedPtrAliasCheck ( InBuffer2 , OutBuffer , InNum ) ;
2021-05-05 15:07:25 -04:00
VectorRegister4Float Gain1Vector = VectorLoadFloat1 ( & InGain1 ) ;
VectorRegister4Float Gain2Vector = VectorLoadFloat1 ( & InGain2 ) ;
2019-05-05 21:00:38 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
// InBuffer1 x InGain1
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InBuffer1 [ i ] ) ;
2019-05-05 21:00:38 -04:00
// InBuffer2 x InGain2
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input2 = VectorLoadAligned ( & InBuffer2 [ i ] ) ;
VectorRegister4Float Weighted2 = VectorMultiply ( Input2 , Gain2Vector ) ;
2019-05-05 21:00:38 -04:00
2021-08-03 11:56:47 -04:00
VectorRegister4Float Output = VectorMultiplyAdd ( Input1 , Gain1Vector , Weighted2 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Output , & OutBuffer [ i ] ) ;
}
}
/* Performs an element-wise weighted sum OutputBuffer = (InBuffer1 x InGain1) + InBuffer2 */
void BufferWeightedSumFast ( const float * RESTRICT InBuffer1 , float InGain1 , const float * RESTRICT InBuffer2 , float * RESTRICT OutBuffer , int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InBuffer1 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InBuffer2 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InBuffer1 , OutBuffer , InNum ) ;
RestrictedPtrAliasCheck ( InBuffer2 , OutBuffer , InNum ) ;
2021-05-05 15:07:25 -04:00
VectorRegister4Float Gain1Vector = VectorLoadFloat1 ( & InGain1 ) ;
2019-05-05 21:00:38 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
// InBuffer1 x InGain1
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InBuffer1 [ i ] ) ;
VectorRegister4Float Input2 = VectorLoadAligned ( & InBuffer2 [ i ] ) ;
2021-08-03 11:56:47 -04:00
VectorRegister4Float Output = VectorMultiplyAdd ( Input1 , Gain1Vector , Input2 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Output , & OutBuffer [ i ] ) ;
}
}
2021-05-04 16:05:46 -04:00
void FadeBufferFast ( FAlignedFloatBuffer & OutFloatBuffer , const float StartValue , const float EndValue )
2018-06-27 16:58:34 -04:00
{
FadeBufferFast ( OutFloatBuffer . GetData ( ) , OutFloatBuffer . Num ( ) , StartValue , EndValue ) ;
}
2019-01-30 05:36:44 -05:00
void FadeBufferFast ( float * RESTRICT OutFloatBuffer , int32 NumSamples , const float StartValue , const float EndValue )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < float * > ( OutFloatBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
float Gain = StartValue ;
if ( FMath : : IsNearlyEqual ( StartValue , EndValue ) )
{
// No need to do anything if start and end values are both 0.0
if ( StartValue = = 0.0f )
{
FMemory : : Memset ( OutFloatBuffer , 0 , sizeof ( float ) * NumSamples ) ;
}
else
{
// Only need to do a buffer multiply if start and end values are the same
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
OutFloatBuffer [ i ] = OutFloatBuffer [ i ] * Gain ;
}
}
}
else
{
// Do a fade from start to end
const float DeltaValue = ( ( EndValue - StartValue ) / NumSamples ) ;
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
OutFloatBuffer [ i ] = OutFloatBuffer [ i ] * Gain ;
Gain + = DeltaValue ;
}
}
# else
const int32 NumIterations = NumSamples / 4 ;
if ( FMath : : IsNearlyEqual ( StartValue , EndValue ) )
{
// No need to do anything if start and end values are both 0.0
if ( StartValue = = 0.0f )
{
FMemory : : Memset ( OutFloatBuffer , 0 , sizeof ( float ) * NumSamples ) ;
}
else
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Gain = VectorLoadFloat1 ( & StartValue ) ;
2018-06-27 16:58:34 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorLoadAligned ( & OutFloatBuffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
Output = VectorMultiply ( Output , Gain ) ;
VectorStoreAligned ( Output , & OutFloatBuffer [ i ] ) ;
}
}
}
else
{
const float DeltaValue = ( ( EndValue - StartValue ) / NumIterations ) ;
2021-05-05 15:07:25 -04:00
VectorRegister4Float Gain = VectorLoadFloat1 ( & StartValue ) ;
VectorRegister4Float Delta = VectorLoadFloat1 ( & DeltaValue ) ;
2018-06-27 16:58:34 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorLoadAligned ( & OutFloatBuffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
Output = VectorMultiply ( Output , Gain ) ;
Gain = VectorAdd ( Gain , Delta ) ;
VectorStoreAligned ( Output , & OutFloatBuffer [ i ] ) ;
}
}
# endif
}
2020-09-15 13:08:34 -04:00
void MixInBufferFast ( const FAlignedFloatBuffer & InFloatBuffer , FAlignedFloatBuffer & BufferToSumTo , const float Gain )
2018-06-27 16:58:34 -04:00
{
MixInBufferFast ( InFloatBuffer . GetData ( ) , BufferToSumTo . GetData ( ) , InFloatBuffer . Num ( ) , Gain ) ;
}
2019-01-30 05:36:44 -05:00
void MixInBufferFast ( const float * RESTRICT InFloatBuffer , float * RESTRICT BufferToSumTo , int32 NumSamples , const float Gain )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < const float * > ( InFloatBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( BufferToSumTo , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InFloatBuffer , BufferToSumTo , NumSamples ) ;
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
BufferToSumTo [ i ] + = InFloatBuffer [ i ] * Gain ;
}
# else
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector = VectorLoadFloat1 ( & Gain ) ;
2018-06-27 16:58:34 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorLoadAligned ( & BufferToSumTo [ i ] ) ;
VectorRegister4Float Input = VectorLoadAligned ( & InFloatBuffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
Output = VectorMultiplyAdd ( Input , GainVector , Output ) ;
VectorStoreAligned ( Output , & BufferToSumTo [ i ] ) ;
}
# endif
}
2020-09-15 13:08:34 -04:00
void MixInBufferFast ( const FAlignedFloatBuffer & InFloatBuffer , FAlignedFloatBuffer & BufferToSumTo )
2019-05-05 21:00:38 -04:00
{
checkf ( InFloatBuffer . Num ( ) = = BufferToSumTo . Num ( ) , TEXT ( " Buffers must be equal size " ) ) ;
MixInBufferFast ( InFloatBuffer . GetData ( ) , BufferToSumTo . GetData ( ) , InFloatBuffer . Num ( ) ) ;
}
2019-01-30 05:36:44 -05:00
void MixInBufferFast ( const float * RESTRICT InFloatBuffer , float * RESTRICT BufferToSumTo , int32 NumSamples )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < const float * > ( InFloatBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( BufferToSumTo , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InFloatBuffer , BufferToSumTo , NumSamples ) ;
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
BufferToSumTo [ i ] + = InFloatBuffer [ i ] ;
}
# else
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorLoadAligned ( & BufferToSumTo [ i ] ) ;
VectorRegister4Float Input = VectorLoadAligned ( & InFloatBuffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
Output = VectorAdd ( Input , Output ) ;
VectorStoreAligned ( Output , & BufferToSumTo [ i ] ) ;
}
# endif
}
2020-09-15 13:08:34 -04:00
void MixInBufferFast ( const FAlignedFloatBuffer & InFloatBuffer , FAlignedFloatBuffer & BufferToSumTo , const float StartGain , const float EndGain )
2019-11-01 15:17:07 -04:00
{
MixInBufferFast ( InFloatBuffer . GetData ( ) , BufferToSumTo . GetData ( ) , InFloatBuffer . Num ( ) , StartGain , EndGain ) ;
}
void MixInBufferFast ( const float * RESTRICT InFloatBuffer , float * RESTRICT BufferToSumTo , int32 NumSamples , const float StartGain , const float EndGain )
{
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < const float * > ( InFloatBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( BufferToSumTo , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2019-11-01 15:17:07 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InFloatBuffer , BufferToSumTo , NumSamples ) ;
2019-11-01 15:17:07 -04:00
const int32 NumIterations = NumSamples / 4 ;
if ( FMath : : IsNearlyEqual ( StartGain , EndGain ) )
{
// No need to do anything if start and end values are both 0.0
if ( StartGain = = 0.0f )
{
return ;
}
else
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Gain = VectorLoadFloat1 ( & StartGain ) ;
2019-11-01 15:17:07 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-11-01 15:17:07 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input = VectorLoadAligned ( & InFloatBuffer [ i ] ) ;
VectorRegister4Float Output = VectorLoadAligned ( & BufferToSumTo [ i ] ) ;
2019-11-01 15:17:07 -04:00
2021-08-03 11:56:47 -04:00
Output = VectorMultiplyAdd ( Input , Gain , Output ) ;
2019-11-01 15:17:07 -04:00
VectorStoreAligned ( Output , & BufferToSumTo [ i ] ) ;
}
}
}
else
{
const float DeltaValue = ( ( EndGain - StartGain ) / NumIterations ) ;
2021-05-05 15:07:25 -04:00
VectorRegister4Float Gain = VectorLoadFloat1 ( & StartGain ) ;
VectorRegister4Float Delta = VectorLoadFloat1 ( & DeltaValue ) ;
2019-11-01 15:17:07 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-11-01 15:17:07 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input = VectorLoadAligned ( & InFloatBuffer [ i ] ) ;
VectorRegister4Float Output = VectorLoadAligned ( & BufferToSumTo [ i ] ) ;
2021-08-03 11:56:47 -04:00
Output = VectorMultiplyAdd ( Input , Gain , Output ) ;
2021-12-17 03:41:59 -05:00
2019-11-01 15:17:07 -04:00
VectorStoreAligned ( Output , & BufferToSumTo [ i ] ) ;
Gain = VectorAdd ( Gain , Delta ) ;
}
}
}
2019-05-05 21:00:38 -04:00
/* Subtracts two buffers together element-wise. */
2020-09-15 13:08:34 -04:00
void BufferSubtractFast ( const FAlignedFloatBuffer & InMinuend , const FAlignedFloatBuffer & InSubtrahend , FAlignedFloatBuffer & OutputBuffer )
2019-05-05 21:00:38 -04:00
{
const int32 InNum = InMinuend . Num ( ) ;
OutputBuffer . Reset ( InNum ) ;
OutputBuffer . AddUninitialized ( InNum ) ;
2022-03-02 13:14:09 -05:00
checkf ( InMinuend . Num ( ) = = InSubtrahend . Num ( ) , TEXT ( " Input buffers must be equal length. InMinuend.Num()=%d, InSubtrahend.Num()=%d " ) , InMinuend . Num ( ) , InSubtrahend . Num ( ) ) ;
2019-05-05 21:00:38 -04:00
BufferSubtractFast ( InMinuend . GetData ( ) , InSubtrahend . GetData ( ) , OutputBuffer . GetData ( ) , OutputBuffer . Num ( ) ) ;
}
/* Subtracts two buffers together element-wise. */
void BufferSubtractFast ( const float * RESTRICT InMinuend , const float * RESTRICT InSubtrahend , float * RESTRICT OutBuffer , int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = 4 , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InMinuend , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InSubtrahend , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InMinuend , OutBuffer , InNum ) ;
RestrictedPtrAliasCheck ( InSubtrahend , OutBuffer , InNum ) ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InMinuend [ i ] ) ;
VectorRegister4Float Input2 = VectorLoadAligned ( & InSubtrahend [ i ] ) ;
VectorRegister4Float Output = VectorSubtract ( Input1 , Input2 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Output , & OutBuffer [ i ] ) ;
}
}
/* Performs element-wise in-place subtraction placing the result in the subtrahend. InOutSubtrahend = InMinuend - InOutSubtrahend */
2020-09-15 13:08:34 -04:00
void BufferSubtractInPlace1Fast ( const FAlignedFloatBuffer & InMinuend , FAlignedFloatBuffer & InOutSubtrahend )
2019-05-05 21:00:38 -04:00
{
checkf ( InMinuend . Num ( ) = = InOutSubtrahend . Num ( ) , TEXT ( " Input buffers must be equal length " ) ) ;
BufferSubtractInPlace1Fast ( InMinuend . GetData ( ) , InOutSubtrahend . GetData ( ) , InMinuend . Num ( ) ) ;
}
/* Performs element-wise in-place subtraction placing the result in the subtrahend. InOutSubtrahend = InMinuend - InOutSubtrahend */
void BufferSubtractInPlace1Fast ( const float * RESTRICT InMinuend , float * RESTRICT InOutSubtrahend , int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = 4 , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InMinuend , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InOutSubtrahend , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InMinuend , InOutSubtrahend , InNum ) ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InMinuend [ i ] ) ;
VectorRegister4Float Input2 = VectorLoadAligned ( & InOutSubtrahend [ i ] ) ;
2019-05-05 21:00:38 -04:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorSubtract ( Input1 , Input2 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Output , & InOutSubtrahend [ i ] ) ;
}
}
/* Performs element-wise in-place subtraction placing the result in the minuend. InOutMinuend = InOutMinuend - InSubtrahend */
2021-05-04 16:05:46 -04:00
void BufferSubtractInPlace2Fast ( FAlignedFloatBuffer & InOutMinuend , const FAlignedFloatBuffer & InSubtrahend )
2019-05-05 21:00:38 -04:00
{
checkf ( InOutMinuend . Num ( ) = = InSubtrahend . Num ( ) , TEXT ( " Input buffers must be equal length " ) ) ;
BufferSubtractInPlace2Fast ( InOutMinuend . GetData ( ) , InSubtrahend . GetData ( ) , InOutMinuend . Num ( ) ) ;
}
/* Performs element-wise in-place subtraction placing the result in the minuend. InOutMinuend = InOutMinuend - InSubtrahend */
void BufferSubtractInPlace2Fast ( float * RESTRICT InOutMinuend , const float * RESTRICT InSubtrahend , int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = 4 , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InOutMinuend , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InSubtrahend , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InOutMinuend , InSubtrahend , InNum ) ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InOutMinuend [ i ] ) ;
VectorRegister4Float Input2 = VectorLoadAligned ( & InSubtrahend [ i ] ) ;
2019-05-05 21:00:38 -04:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorSubtract ( Input1 , Input2 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Output , & InOutMinuend [ i ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void SumBuffers ( const FAlignedFloatBuffer & InFloatBuffer1 , const FAlignedFloatBuffer & InFloatBuffer2 , FAlignedFloatBuffer & OutputBuffer )
2018-06-27 16:58:34 -04:00
{
2019-05-05 21:00:38 -04:00
checkf ( InFloatBuffer1 . Num ( ) = = InFloatBuffer2 . Num ( ) , TEXT ( " Input buffers must be equal length " ) ) ;
const int32 InNum = InFloatBuffer1 . Num ( ) ;
OutputBuffer . Reset ( InNum ) ;
OutputBuffer . AddUninitialized ( InNum ) ;
SumBuffers ( InFloatBuffer1 . GetData ( ) , InFloatBuffer2 . GetData ( ) , OutputBuffer . GetData ( ) , InNum ) ;
2018-06-27 16:58:34 -04:00
}
2019-01-30 05:36:44 -05:00
void SumBuffers ( const float * RESTRICT InFloatBuffer1 , const float * RESTRICT InFloatBuffer2 , float * RESTRICT OutputBuffer , int32 NumSamples )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < const float * > ( InFloatBuffer1 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InFloatBuffer2 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutputBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InFloatBuffer1 , OutputBuffer , NumSamples ) ;
RestrictedPtrAliasCheck ( InFloatBuffer2 , OutputBuffer , NumSamples ) ;
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
OutputBuffer [ i ] = InFloatBuffer1 [ i ] + InFloatBuffer2 [ i ] ;
}
# else
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InFloatBuffer1 [ i ] ) ;
VectorRegister4Float Input2 = VectorLoadAligned ( & InFloatBuffer2 [ i ] ) ;
2018-06-27 16:58:34 -04:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Output = VectorAdd ( Input1 , Input2 ) ;
2018-06-27 16:58:34 -04:00
VectorStoreAligned ( Output , & OutputBuffer [ i ] ) ;
}
# endif
}
2020-09-15 13:08:34 -04:00
void MultiplyBuffersInPlace ( const FAlignedFloatBuffer & InFloatBuffer , FAlignedFloatBuffer & BufferToMultiply )
2018-11-14 19:05:13 -05:00
{
MultiplyBuffersInPlace ( InFloatBuffer . GetData ( ) , BufferToMultiply . GetData ( ) , BufferToMultiply . Num ( ) ) ;
}
2019-01-30 05:36:44 -05:00
void MultiplyBuffersInPlace ( const float * RESTRICT InFloatBuffer , float * RESTRICT BufferToMultiply , int32 NumSamples )
2018-11-14 19:05:13 -05:00
{
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < const float * > ( InFloatBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( BufferToMultiply , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-11-14 19:05:13 -05:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InFloatBuffer , BufferToMultiply , NumSamples ) ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-11-14 19:05:13 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input1 = VectorLoadAligned ( & InFloatBuffer [ i ] ) ;
VectorRegister4Float Output = VectorLoadAligned ( & BufferToMultiply [ i ] ) ;
2018-11-14 19:05:13 -05:00
Output = VectorMultiply ( Input1 , Output ) ;
VectorStoreAligned ( Output , & BufferToMultiply [ i ] ) ;
}
}
2020-09-15 13:08:34 -04:00
float GetMagnitude ( const FAlignedFloatBuffer & Buffer )
2018-06-27 16:58:34 -04:00
{
return GetMagnitude ( Buffer . GetData ( ) , Buffer . Num ( ) ) ;
}
2019-01-30 05:36:44 -05:00
float GetMagnitude ( const float * RESTRICT Buffer , int32 NumSamples )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
float Sum = 0.0f ;
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
Sum + = Buffer [ i ] * Buffer [ i ] ;
}
return FMath : : Sqrt ( Sum ) ;
# else
2021-05-05 15:07:25 -04:00
VectorRegister4Float Sum = VectorZero ( ) ;
2018-06-27 16:58:34 -04:00
const float Exponent = 2.0f ;
2021-05-05 15:07:25 -04:00
VectorRegister4Float ExponentVector = VectorLoadFloat1 ( & Exponent ) ;
2018-06-27 16:58:34 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input = VectorPow ( VectorLoadAligned ( & Buffer [ i ] ) , ExponentVector ) ;
2018-06-27 16:58:34 -04:00
Sum = VectorAdd ( Sum , Input ) ;
}
float PartionedSums [ 4 ] ;
VectorStoreAligned ( Sum , PartionedSums ) ;
return FMath : : Sqrt ( PartionedSums [ 0 ] + PartionedSums [ 1 ] + PartionedSums [ 2 ] + PartionedSums [ 3 ] ) ;
# endif
}
2021-01-25 17:26:35 -04:00
float BufferGetAverageValue ( const FAlignedFloatBuffer & Buffer )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( Buffer . Num ( ) % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
2021-01-25 17:26:35 -04:00
return BufferGetAverageValue ( Buffer . GetData ( ) , Buffer . Num ( ) ) ;
2018-06-27 16:58:34 -04:00
}
2021-01-25 17:26:35 -04:00
float BufferGetAverageValue ( const float * RESTRICT Buffer , int32 NumSamples )
2018-06-27 16:58:34 -04:00
{
2021-05-11 19:04:43 -04:00
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2018-06-27 16:58:34 -04:00
# if !AUDIO_USE_SIMD
float Sum = 0.0f ;
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
Sum + = Buffer [ i ] ;
}
return Sum / NumSamples ;
# else
2021-05-05 15:07:25 -04:00
VectorRegister4Float Sum = VectorZero ( ) ;
2018-06-27 16:58:34 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2018-06-27 16:58:34 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input = VectorLoadAligned ( & Buffer [ i ] ) ;
2018-06-27 16:58:34 -04:00
Sum = VectorAdd ( Sum , Input ) ;
}
float PartionedSums [ 4 ] ;
VectorStore ( Sum , PartionedSums ) ;
2021-01-25 17:26:35 -04:00
return ( PartionedSums [ 0 ] + PartionedSums [ 1 ] + PartionedSums [ 2 ] + PartionedSums [ 3 ] ) / NumSamples ;
# endif
}
float BufferGetAverageAbsValue ( const FAlignedFloatBuffer & Buffer )
{
2021-05-11 19:04:43 -04:00
checkf ( Buffer . Num ( ) % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2021-01-25 17:26:35 -04:00
return BufferGetAverageAbsValue ( Buffer . GetData ( ) , Buffer . Num ( ) ) ;
}
float BufferGetAverageAbsValue ( const float * RESTRICT Buffer , int32 NumSamples )
{
2021-05-11 19:04:43 -04:00
checkf ( NumSamples % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER = = 0 , TEXT ( " Please use a buffer size that is a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2021-01-25 17:26:35 -04:00
# if !AUDIO_USE_SIMD
float Sum = 0.0f ;
for ( int32 i = 0 ; i < NumSamples ; + + i )
{
Sum + = FMath : : Abs ( Buffer [ i ] ) ;
}
return Sum / NumSamples ;
# else
2021-05-05 15:07:25 -04:00
VectorRegister4Float Sum = VectorZero ( ) ;
2021-01-25 17:26:35 -04:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2021-01-25 17:26:35 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input = VectorAbs ( VectorLoadAligned ( & Buffer [ i ] ) ) ;
2021-01-25 17:26:35 -04:00
Sum = VectorAdd ( Sum , Input ) ;
}
float PartionedSums [ 4 ] ;
VectorStore ( Sum , PartionedSums ) ;
2018-06-27 16:58:34 -04:00
return ( PartionedSums [ 0 ] + PartionedSums [ 1 ] + PartionedSums [ 2 ] + PartionedSums [ 3 ] ) / NumSamples ;
# endif
}
2019-01-30 05:36:44 -05:00
/**
* CHANNEL MIXING OPERATIONS :
* To understand these functions , it ' s best that you have prior experience reading SIMD code .
* These functions are all variations on component - wise matrix multiplies .
* There are two types of functions below :
*
* Apply [ N ] ChannelGain :
* These are all in - place multiplies of an N - length gain vector and an N - length frame .
* There are two flavors of every variant of this function : The non - interpolating form ( which takes a single gain matrix )
* And the interpolating form ( which takes a start gain matrix and interpolates to the end gain matrix over the given number of frames ) .
* All non - interpolating forms of these functions use the following steps :
* 1. Create a const GainVector , or series of GainVectors , that maps to the multiplies required for each iteration .
* 2. In a loop :
* i . load a frame or number of frames into a vector register or series of vector registers ( these are named Result ) .
* ii . perform a vector multiply on result with the corresponding gain vector .
* iii . store the result vector in the same position in the buffer we loaded from .
*
* The interpolating forms of these functions use the following steps :
* 1. Initialize a non - const GainVector , or series of GainVectors , from StartGains , that maps to the multiplies required for each iteration .
* 2. Compute the amount we add to GainVector for each iteration to reach Destination Gains and store it in the const GainDeltasVector .
* 3. In a loop :
* i . load a frame or number of frames into a vector register or series of vector registers ( these are named Result ) .
* ii . perform a vector multiply on result with the corresponding gain vector .
* iii . store the result vector in the same position in the buffer we loaded from .
* iv . increment each GainVector by it ' s corresponding GainDeltasVector .
*
*
* MixMonoTo [ N ] ChannelsFast and Mix2ChannelsTo [ N ] ChannelsFast :
* These , like Apply [ N ] ChannelGain , all have non - interpolating and interpolating forms .
* All non - interpolating forms of these functions use the following steps :
* 1. Create a const GainVector , or series of GainVectors , that maps to the multiplies required for each input channel for each iteration .
* 2. In a loop :
* i . load a frame or number of frames into a const vector register or series of const vector registers ( these are named Input ) .
* ii . perform a vector multiply on input with the corresponding gain vector and store the result in a new vector or series of vectors named Result .
* iii . if there is a second input channel , store the results of the following MultiplyAdd operation to Results : ( Gain Vectors for second channel ) * ( Input vectors for second channel ) + ( Result vectors from step ii ) .
*
* Interpolating forms of these functions use the following steps :
* 1. Initialize a non - const GainVector , or series of GainVectors , from StartGains , that maps to the multiplies required for each input channel for each iteration .
* 2. Compute the amount we add to each GainVector for each iteration to reach the vector ' s corresponding DestinationGains and store it in a corresponding GainDeltaVector .
* 3. In a loop :
* i . load a frame or number of frames into a const vector register or series of const vector registers ( these are named Input ) .
* ii . perform a vector multiply on input with the corresponding gain vector and store the result in a new vector or series of vectors named Result .
* iii . if there is a second input channel , store the results of the following MultiplyAdd operation to Results : ( Gain Vectors for second channel ) * ( Input vectors for second channel ) + ( Result vectors from step ii ) .
* iv . increment each GainVector by it ' s corresponding GainDeltasVector .
*
* DETERMINING THE VECTOR LAYOUT FOR EACH FUNCTION :
* For every variant of Mix [ N ] ChannelsTo [ N ] ChannelsFast , we use the least common multiple of the number of output channels and the SIMD vector length ( 4 ) to calulate the length of our matrix .
2021-05-05 15:07:25 -04:00
* For example , MixMonoTo4ChannelsFast can use a single VectorRegister4Float for each variable . GainVector ' s values are [ g0 , g1 , g2 , g3 ] , input channels are mapped to [ i0 , i0 , i0 , i0 ] , and output channels are mapped to [ o0 , o1 , o2 , o3 ] .
* MixMonoTo8ChannelsFast has an LCM of 8 , so we use two VectorRegister4Float for each variable . This results in the following layout :
2019-01-30 05:36:44 -05:00
* GainVector1 : [ g0 , g1 , g2 , g3 ] GainVector2 : [ g4 , g5 , g6 , g7 ]
* InputVector1 : [ i0 , i0 , i0 , i0 ] InputVector2 : [ i0 , i0 , i0 , i0 ]
* ResultVector1 : [ o0 , o1 , o2 , o3 ] ResultVector2 : [ o4 , o5 , o6 , o7 ]
*
* The general naming convention for vector variables is [ Name ] Vector [ VectorIndex ] for MixMonoTo [ N ] ChannelsFast functions .
* For Mix2ChannelsTo [ N ] ChannelsFast functions , the naming convention for vector variables is [ Name ] Vector [ VectorIndex ] [ InputChannelIndex ] .
*
* For clarity , the layout of vectors for each function variant is given in a block comment above that function .
*/
2021-05-04 16:05:46 -04:00
void Apply2ChannelGain ( FAlignedFloatBuffer & StereoBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Apply2ChannelGain ( StereoBuffer . GetData ( ) , StereoBuffer . Num ( ) , Gains ) ;
}
void Apply2ChannelGain ( float * RESTRICT StereoBuffer , int32 NumSamples , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector = VectorLoadFloat2 ( Gains ) ;
2019-01-30 05:36:44 -05:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-01-30 05:36:44 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & StereoBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & StereoBuffer [ i ] ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply2ChannelGain ( FAlignedFloatBuffer & StereoBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Apply2ChannelGain ( StereoBuffer . GetData ( ) , StereoBuffer . Num ( ) , StartGains , EndGains ) ;
}
void Apply2ChannelGain ( float * RESTRICT StereoBuffer , int32 NumSamples , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
// Initialize GainVector at StartGains and compute GainDeltasVector:
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector = VectorLoadFloat2 ( StartGains ) ;
const VectorRegister4Float DestinationVector = VectorLoadFloat2 ( EndGains ) ;
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumSamples / 4.0f ) ;
const VectorRegister4Float GainDeltasVector = VectorDivide ( VectorSubtract ( DestinationVector , GainVector ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-01-30 05:36:44 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & StereoBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & StereoBuffer [ i ] ) ;
GainVector = VectorAdd ( GainVector , GainDeltasVector ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo2ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
MixMonoTo2ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 2 , Gains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain | g0 | g1 | g0 | g1 |
* | | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo2ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector = VectorLoadFloat2 ( Gains ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + = 2 )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorSet ( MonoBuffer [ i ] , MonoBuffer [ i ] , MonoBuffer [ i + 1 ] , MonoBuffer [ i + 1 ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 2 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo2ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
MixMonoTo2ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 2 , StartGains , EndGains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain | g0 | g1 | g0 | g1 |
* | | * | * | * | * |
2019-03-15 14:26:55 -04:00
* | Input | i0 | i0 | i1 | i1 |
2019-01-30 05:36:44 -05:00
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo2ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
// Initialize GainVector at StartGains and compute GainDeltasVector:
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector = VectorLoadFloat2 ( StartGains ) ;
const VectorRegister4Float DestinationVector = VectorLoadFloat2 ( EndGains ) ;
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumFrames / 2.0f ) ;
const VectorRegister4Float GainDeltasVector = VectorDivide ( VectorSubtract ( DestinationVector , GainVector ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
// To help with stair stepping, we initialize the second frame in GainVector to be half a GainDeltas vector higher than the first frame.
2021-05-05 15:07:25 -04:00
const VectorRegister4Float VectorOfHalf = VectorSet ( 0.5f , 0.5f , 1.0f , 1.0f ) ;
2021-08-03 11:56:47 -04:00
GainVector = VectorMultiplyAdd ( GainDeltasVector , VectorOfHalf , GainVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + = 2 )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorSet ( MonoBuffer [ i ] , MonoBuffer [ i ] , MonoBuffer [ i + 1 ] , MonoBuffer [ i + 1 ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 2 ] ) ;
GainVector = VectorAdd ( GainVector , GainDeltasVector ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo2ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer )
2019-05-05 21:00:38 -04:00
{
MixMonoTo2ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , MonoBuffer . Num ( ) ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Input | i0 | i0 | i1 | i1 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo2ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 InNumFrames )
{
2021-05-11 19:04:43 -04:00
checkf ( InNumFrames > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNumFrames % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( MonoBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( DestinationBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
int32 OutPos = 0 ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNumFrames ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Input = VectorLoadAligned ( & MonoBuffer [ i ] ) ;
VectorRegister4Float Output = VectorSwizzle ( Input , 0 , 0 , 1 , 1 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Output , & DestinationBuffer [ OutPos ] ) ;
2021-05-11 19:04:43 -04:00
OutPos + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
Output = VectorSwizzle ( Input , 2 , 2 , 3 , 3 ) ;
VectorStoreAligned ( Output , & DestinationBuffer [ OutPos ] ) ;
2021-05-11 19:04:43 -04:00
OutPos + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo2ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Mix2ChannelsTo2ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 2 , Gains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain1 | g0 | g1 | g0 | g1 |
* | | * | * | * | * |
* | Input1 | i0 | i0 | i2 | i2 |
* | | + | + | + | + |
* | Gain2 | g2 | g3 | g2 | g3 |
* | | * | * | * | * |
* | Input2 | i1 | i1 | i3 | i3 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void Mix2ChannelsTo2ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector1 = VectorLoadFloat2 ( Gains ) ;
const VectorRegister4Float GainVector2 = VectorLoadFloat2 ( Gains + 2 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + = 2 )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorSet ( SourceBuffer [ i * 2 ] , SourceBuffer [ i * 2 ] , SourceBuffer [ i * 2 + 2 ] , SourceBuffer [ i * 2 + 2 ] ) ;
const VectorRegister4Float Input2 = VectorSet ( SourceBuffer [ i * 2 + 1 ] , SourceBuffer [ i * 2 + 1 ] , SourceBuffer [ i * 2 + 3 ] , SourceBuffer [ i * 2 + 3 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector2 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 2 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo2ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Mix2ChannelsTo2ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 2 , StartGains , EndGains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain1 | g0 | g1 | g0 | g1 |
* | | * | * | * | * |
* | Input1 | i0 | i0 | i2 | i2 |
* | | + | + | + | + |
* | Gain2 | g2 | g3 | g2 | g3 |
* | | * | * | * | * |
* | Input2 | i1 | i1 | i3 | i3 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void Mix2ChannelsTo2ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumFrames / 2.0f ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector1 = VectorLoadFloat2 ( StartGains ) ;
const VectorRegister4Float DestinationVector1 = VectorLoadFloat2 ( EndGains ) ;
const VectorRegister4Float GainDeltasVector1 = VectorDivide ( VectorSubtract ( DestinationVector1 , GainVector1 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
// To help with stair stepping, we initialize the second frame in GainVector to be half a GainDeltas vector higher than the first frame.
2021-05-05 15:07:25 -04:00
const VectorRegister4Float VectorOfHalf = VectorSet ( 0.5f , 0.5f , 1.0f , 1.0f ) ;
2019-01-30 05:36:44 -05:00
2021-08-03 11:56:47 -04:00
GainVector1 = VectorMultiplyAdd ( GainDeltasVector1 , VectorOfHalf , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector2 = VectorLoadFloat2 ( StartGains + 2 ) ;
const VectorRegister4Float DestinationVector2 = VectorLoadFloat2 ( EndGains + 2 ) ;
const VectorRegister4Float GainDeltasVector2 = VectorDivide ( VectorSubtract ( DestinationVector2 , GainVector2 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-08-03 11:56:47 -04:00
GainVector2 = VectorMultiplyAdd ( GainDeltasVector2 , VectorOfHalf , GainVector2 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + = 2 )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorSet ( SourceBuffer [ i * 2 ] , SourceBuffer [ i * 2 ] , SourceBuffer [ i * 2 + 2 ] , SourceBuffer [ i * 2 + 2 ] ) ;
const VectorRegister4Float Input2 = VectorSet ( SourceBuffer [ i * 2 + 1 ] , SourceBuffer [ i * 2 + 1 ] , SourceBuffer [ i * 2 + 3 ] , SourceBuffer [ i * 2 + 3 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector2 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 2 ] ) ;
GainVector1 = VectorAdd ( GainVector1 , GainDeltasVector1 ) ;
GainVector2 = VectorAdd ( GainVector2 , GainDeltasVector2 ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply4ChannelGain ( FAlignedFloatBuffer & InterleavedBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Apply4ChannelGain ( InterleavedBuffer . GetData ( ) , InterleavedBuffer . Num ( ) , Gains ) ;
}
void Apply4ChannelGain ( float * RESTRICT InterleavedBuffer , int32 NumSamples , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector = VectorLoadAligned ( Gains ) ;
2019-01-30 05:36:44 -05:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-01-30 05:36:44 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & InterleavedBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i ] ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply4ChannelGain ( FAlignedFloatBuffer & InterleavedBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Apply4ChannelGain ( InterleavedBuffer . GetData ( ) , InterleavedBuffer . Num ( ) , StartGains , EndGains ) ;
}
void Apply4ChannelGain ( float * RESTRICT InterleavedBuffer , int32 NumSamples , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
// Initialize GainVector at StartGains and compute GainDeltasVector:
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector = VectorLoadAligned ( EndGains ) ;
2021-05-11 19:04:43 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumSamples / ( float ) AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainDeltasVector = VectorDivide ( VectorSubtract ( DestinationVector , GainVector ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < NumSamples ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-01-30 05:36:44 -05:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & InterleavedBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i ] ) ;
GainVector = VectorAdd ( GainVector , GainDeltasVector ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo4ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
2021-05-11 19:04:43 -04:00
MixMonoTo4ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , Gains ) ;
2019-01-30 05:36:44 -05:00
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frame per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain | g0 | g1 | g2 | g3 |
* | | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo4ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector = VectorLoadAligned ( Gains ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 4 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo4ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
2021-05-11 19:04:43 -04:00
MixMonoTo4ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , StartGains , EndGains ) ;
2019-01-30 05:36:44 -05:00
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frame per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain | g0 | g1 | g2 | g3 |
* | | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo4ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( ( float ) NumFrames ) ;
const VectorRegister4Float GainDeltasVector = VectorDivide ( VectorSubtract ( DestinationVector , GainVector ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 4 ] ) ;
GainVector = VectorAdd ( GainVector , GainDeltasVector ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo4ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
2021-05-11 19:04:43 -04:00
Mix2ChannelsTo4ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , Gains ) ;
2019-01-30 05:36:44 -05:00
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frame per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain1 | g0 | g1 | g2 | g3 |
* | | * | * | * | * |
* | Input1 | i0 | i0 | i0 | i0 |
* | | + | + | + | + |
* | Gain2 | g4 | g5 | g6 | g7 |
* | | * | * | * | * |
* | Input2 | i1 | i1 | i1 | i1 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void Mix2ChannelsTo4ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector1 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector2 = VectorLoadAligned ( Gains + 4 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 ] ) ;
const VectorRegister4Float Input2 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 + 1 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector2 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 4 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo4ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
2021-05-11 19:04:43 -04:00
Mix2ChannelsTo4ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , StartGains , EndGains ) ;
2019-01-30 05:36:44 -05:00
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frame per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | Gain1 | g0 | g1 | g2 | g3 |
* | | * | * | * | * |
* | Input1 | i0 | i0 | i0 | i0 |
* | | + | + | + | + |
* | Gain2 | g4 | g5 | g6 | g7 |
* | | * | * | * | * |
* | Input2 | i1 | i1 | i1 | i1 |
* | | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 |
* + - - - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void Mix2ChannelsTo4ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( ( float ) NumFrames ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector1 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector1 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector1 = VectorDivide ( VectorSubtract ( DestinationVector1 , GainVector1 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector2 = VectorLoadAligned ( StartGains + 4 ) ;
const VectorRegister4Float DestinationVector2 = VectorLoadAligned ( EndGains + 4 ) ;
const VectorRegister4Float GainDeltasVector2 = VectorDivide ( VectorSubtract ( DestinationVector2 , GainVector2 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 ] ) ;
const VectorRegister4Float Input2 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 + 1 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector2 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 4 ] ) ;
GainVector1 = VectorAdd ( GainVector1 , GainDeltasVector1 ) ;
GainVector2 = VectorAdd ( GainVector2 , GainDeltasVector2 ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply6ChannelGain ( FAlignedFloatBuffer & InterleavedBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Apply6ChannelGain ( InterleavedBuffer . GetData ( ) , InterleavedBuffer . Num ( ) , Gains ) ;
}
void Apply6ChannelGain ( float * RESTRICT InterleavedBuffer , int32 NumSamples , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector1 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector2 = VectorSet ( Gains [ 4 ] , Gains [ 5 ] , Gains [ 0 ] , Gains [ 1 ] ) ;
const VectorRegister4Float GainVector3 = VectorLoad ( & Gains [ 2 ] ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumSamples ; i + = 12 )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & InterleavedBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector1 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i ] ) ;
Result = VectorLoadAligned ( & InterleavedBuffer [ i + 4 ] ) ;
Result = VectorMultiply ( Result , GainVector2 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i + 4 ] ) ;
Result = VectorLoadAligned ( & InterleavedBuffer [ i + 8 ] ) ;
Result = VectorMultiply ( Result , GainVector3 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i + 8 ] ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply6ChannelGain ( FAlignedFloatBuffer & InterleavedBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Apply6ChannelGain ( InterleavedBuffer . GetData ( ) , InterleavedBuffer . Num ( ) , StartGains , EndGains ) ;
}
void Apply6ChannelGain ( float * RESTRICT InterleavedBuffer , int32 NumSamples , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumSamples / 12.0f ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector1 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector1 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector1 = VectorDivide ( VectorSubtract ( DestinationVector1 , GainVector1 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector2 = VectorSet ( StartGains [ 4 ] , StartGains [ 5 ] , StartGains [ 0 ] , StartGains [ 1 ] ) ;
const VectorRegister4Float DestinationVector2 = VectorSet ( EndGains [ 4 ] , EndGains [ 5 ] , EndGains [ 0 ] , EndGains [ 1 ] ) ;
const VectorRegister4Float GainDeltasVector2 = VectorDivide ( VectorSubtract ( DestinationVector2 , GainVector2 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector3 = VectorLoad ( & StartGains [ 2 ] ) ;
const VectorRegister4Float DestinationVector3 = VectorLoad ( & EndGains [ 2 ] ) ;
const VectorRegister4Float GainDeltasVector3 = VectorDivide ( VectorSubtract ( DestinationVector3 , GainVector3 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumSamples ; i + = 12 )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & InterleavedBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector1 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i ] ) ;
GainVector1 = VectorAdd ( GainVector1 , GainDeltasVector1 ) ;
Result = VectorLoadAligned ( & InterleavedBuffer [ i + 4 ] ) ;
Result = VectorMultiply ( Result , GainVector2 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i + 4 ] ) ;
GainVector2 = VectorAdd ( GainVector2 , GainDeltasVector2 ) ;
Result = VectorLoadAligned ( & InterleavedBuffer [ i + 8 ] ) ;
Result = VectorMultiply ( Result , GainVector3 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i + 8 ] ) ;
GainVector3 = VectorAdd ( GainVector3 , GainDeltasVector3 ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo6ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
MixMonoTo6ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 6 , Gains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | | Vector 3 | | | |
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 | Index 8 | Index 9 | Index 10 | Index 11 |
* | Gain | g0 | g1 | g2 | g3 | g4 | g5 | g0 | g1 | g2 | g3 | g4 | g5 |
* | | * | * | * | * | * | * | * | * | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 | i0 | i0 | i1 | i1 | i1 | i1 | i1 | i1 |
* | | = | = | = | = | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 | o8 | o9 | o10 | o11 |
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
*/
void MixMonoTo6ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector1 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector2 = VectorSet ( Gains [ 4 ] , Gains [ 5 ] , Gains [ 0 ] , Gains [ 1 ] ) ;
const VectorRegister4Float GainVector3 = VectorLoad ( & Gains [ 2 ] ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + = 2 )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
const VectorRegister4Float Input2 = VectorSet ( MonoBuffer [ i ] , MonoBuffer [ i ] , MonoBuffer [ i + 1 ] , MonoBuffer [ i + 1 ] ) ;
const VectorRegister4Float Input3 = VectorLoadFloat1 ( & MonoBuffer [ i + 1 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
VectorStoreAligned ( Result , & DestinationBuffer [ i * 6 ] ) ;
Result = VectorMultiply ( Input2 , GainVector2 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 6 + 4 ] ) ;
Result = VectorMultiply ( Input3 , GainVector3 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 6 + 8 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo6ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
MixMonoTo6ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 6 , StartGains , EndGains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | | Vector 3 | | | |
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 | Index 8 | Index 9 | Index 10 | Index 11 |
* | Gain | g0 | g1 | g2 | g3 | g4 | g5 | g0 | g1 | g2 | g3 | g4 | g5 |
* | | * | * | * | * | * | * | * | * | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 | i0 | i0 | i1 | i1 | i1 | i1 | i1 | i1 |
* | | = | = | = | = | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 | o8 | o9 | o10 | o11 |
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
*/
void MixMonoTo6ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumFrames / 2.0f ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector1 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector1 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector1 = VectorDivide ( VectorSubtract ( DestinationVector1 , GainVector1 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector2 = VectorSet ( StartGains [ 4 ] , StartGains [ 5 ] , StartGains [ 0 ] , StartGains [ 1 ] ) ;
const VectorRegister4Float DestinationVector2 = VectorSet ( EndGains [ 4 ] , EndGains [ 5 ] , EndGains [ 0 ] , EndGains [ 1 ] ) ;
const VectorRegister4Float GainDeltasVector2 = VectorDivide ( VectorSubtract ( DestinationVector2 , GainVector2 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector3 = VectorLoad ( & StartGains [ 2 ] ) ;
const VectorRegister4Float DestinationVector3 = VectorLoad ( & EndGains [ 2 ] ) ;
const VectorRegister4Float GainDeltasVector3 = VectorDivide ( VectorSubtract ( DestinationVector3 , GainVector3 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + = 2 )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
const VectorRegister4Float Input2 = VectorSet ( MonoBuffer [ i ] , MonoBuffer [ i ] , MonoBuffer [ i + 1 ] , MonoBuffer [ i + 1 ] ) ;
const VectorRegister4Float Input3 = VectorLoadFloat1 ( & MonoBuffer [ i + 1 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
VectorStoreAligned ( Result , & DestinationBuffer [ i * 6 ] ) ;
GainVector1 = VectorAdd ( GainVector1 , GainDeltasVector1 ) ;
Result = VectorMultiply ( Input2 , GainVector2 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 6 + 4 ] ) ;
GainVector2 = VectorAdd ( GainVector2 , GainDeltasVector2 ) ;
Result = VectorMultiply ( Input3 , GainVector3 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 6 + 8 ] ) ;
GainVector3 = VectorAdd ( GainVector3 , GainDeltasVector3 ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo6ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Mix2ChannelsTo6ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 6 , Gains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | | Vector 3 | | | |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 | Index 8 | Index 9 | Index 10 | Index 11 |
* | Gain1 | g0 | g1 | g2 | g3 | g4 | g5 | g0 | g1 | g2 | g3 | g4 | g5 |
* | | * | * | * | * | * | * | * | * | * | * | * | * |
* | Input1 | i0 | i0 | i0 | i0 | i0 | i0 | i2 | i2 | i2 | i2 | i2 | i2 |
* | | + | + | + | + | + | + | + | + | + | + | + | + |
* | Gain2 | g6 | g7 | g8 | g9 | g10 | g11 | g6 | g7 | g8 | g9 | g10 | g11 |
* | | * | * | * | * | * | * | * | * | * | * | * | * |
* | Input2 | i1 | i1 | i1 | i1 | i1 | i1 | i1 | i3 | i3 | i3 | i3 | i3 |
* | | = | = | = | = | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 | o8 | o9 | o10 | o11 |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
*/
void Mix2ChannelsTo6ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector11 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector21 = VectorSet ( Gains [ 4 ] , Gains [ 5 ] , Gains [ 0 ] , Gains [ 1 ] ) ;
const VectorRegister4Float GainVector31 = VectorLoad ( & Gains [ 2 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector12 = VectorLoad ( Gains + 6 ) ;
const VectorRegister4Float GainVector22 = VectorSet ( Gains [ 10 ] , Gains [ 11 ] , Gains [ 6 ] , Gains [ 7 ] ) ;
const VectorRegister4Float GainVector32 = VectorLoadAligned ( & Gains [ 8 ] ) ;
2019-01-30 05:36:44 -05:00
for ( int32 FrameIndex = 0 ; FrameIndex < NumFrames ; FrameIndex + = 2 )
{
const int32 InputIndex = FrameIndex * 2 ;
const int32 OutputIndex = FrameIndex * 6 ;
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input11 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex ] ) ;
const VectorRegister4Float Input21 = VectorSet ( SourceBuffer [ InputIndex ] , SourceBuffer [ InputIndex ] , SourceBuffer [ InputIndex + 2 ] , SourceBuffer [ InputIndex + 2 ] ) ;
const VectorRegister4Float Input31 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex + 2 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input12 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex + 1 ] ) ;
const VectorRegister4Float Input22 = VectorSet ( SourceBuffer [ InputIndex + 1 ] , SourceBuffer [ InputIndex + 1 ] , SourceBuffer [ InputIndex + 3 ] , SourceBuffer [ InputIndex + 3 ] ) ;
const VectorRegister4Float Input32 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex + 3 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input11 , GainVector11 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input12 , GainVector12 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ OutputIndex ] ) ;
Result = VectorMultiply ( Input21 , GainVector21 ) ;
Result = VectorMultiplyAdd ( Input22 , GainVector22 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ OutputIndex + 4 ] ) ;
Result = VectorMultiply ( Input31 , GainVector31 ) ;
2020-08-11 01:36:57 -04:00
Result = VectorMultiplyAdd ( Input32 , GainVector32 , Result ) ;
2019-01-30 05:36:44 -05:00
VectorStoreAligned ( Result , & DestinationBuffer [ OutputIndex + 8 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo6ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Mix2ChannelsTo6ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 6 , StartGains , EndGains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 2 frames per iteration :
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | | Vector 3 | | | |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
* | | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 | Index 8 | Index 9 | Index 10 | Index 11 |
* | Gain1 | g0 | g1 | g2 | g3 | g4 | g5 | g0 | g1 | g2 | g3 | g4 | g5 |
* | | * | * | * | * | * | * | * | * | * | * | * | * |
* | Input1 | i0 | i0 | i0 | i0 | i0 | i0 | i2 | i2 | i2 | i2 | i2 | i2 |
* | | + | + | + | + | + | + | + | + | + | + | + | + |
* | Gain2 | g6 | g7 | g8 | g9 | g10 | g11 | g6 | g7 | g8 | g9 | g10 | g11 |
* | | * | * | * | * | * | * | * | * | * | * | * | * |
2019-02-02 10:12:28 -05:00
* | Input2 | i1 | i1 | i1 | i1 | i1 | i1 | i3 | i3 | i3 | i3 | i3 | i3 |
2019-01-30 05:36:44 -05:00
* | | = | = | = | = | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 | o8 | o9 | o10 | o11 |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - - +
*/
void Mix2ChannelsTo6ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumFrames / 2.0f ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector11 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector11 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector11 = VectorDivide ( VectorSubtract ( DestinationVector11 , GainVector11 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector21 = VectorSet ( StartGains [ 4 ] , StartGains [ 5 ] , StartGains [ 0 ] , StartGains [ 1 ] ) ;
const VectorRegister4Float DestinationVector21 = VectorSet ( EndGains [ 4 ] , EndGains [ 5 ] , EndGains [ 0 ] , EndGains [ 1 ] ) ;
const VectorRegister4Float GainDeltasVector21 = VectorDivide ( VectorSubtract ( DestinationVector21 , GainVector21 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
// In order to ease stair stepping, we ensure that the second frame is initialized to half the GainDelta more than the first frame.
// This gives us a consistent increment across every frame.
2021-05-05 15:07:25 -04:00
const VectorRegister4Float DeltaHalf21 = VectorSet ( 0.0f , 0.0f , 0.5f , 0.5f ) ;
2021-08-03 11:56:47 -04:00
GainVector21 = VectorMultiplyAdd ( GainDeltasVector21 , DeltaHalf21 , GainVector21 ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector31 = VectorLoad ( & StartGains [ 2 ] ) ;
const VectorRegister4Float DestinationVector31 = VectorLoad ( & EndGains [ 2 ] ) ;
const VectorRegister4Float GainDeltasVector31 = VectorDivide ( VectorSubtract ( DestinationVector31 , GainVector31 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float DeltaHalf31 = VectorSetFloat1 ( 0.5f ) ;
2021-08-03 11:56:47 -04:00
GainVector31 = VectorMultiplyAdd ( GainDeltasVector31 , DeltaHalf31 , GainVector31 ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector12 = VectorLoad ( StartGains + 6 ) ;
const VectorRegister4Float DestinationVector12 = VectorLoad ( EndGains + 6 ) ;
const VectorRegister4Float GainDeltasVector12 = VectorDivide ( VectorSubtract ( DestinationVector12 , GainVector12 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector22 = VectorSet ( StartGains [ 10 ] , StartGains [ 11 ] , StartGains [ 6 ] , StartGains [ 7 ] ) ;
const VectorRegister4Float DestinationVector22 = VectorSet ( EndGains [ 10 ] , EndGains [ 11 ] , EndGains [ 6 ] , EndGains [ 7 ] ) ;
const VectorRegister4Float GainDeltasVector22 = VectorDivide ( VectorSubtract ( DestinationVector22 , GainVector22 ) , NumFramesVector ) ;
2021-08-03 11:56:47 -04:00
GainVector22 = VectorMultiplyAdd ( GainDeltasVector22 , DeltaHalf21 , GainVector22 ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector32 = VectorLoadAligned ( StartGains + 8 ) ;
const VectorRegister4Float DestinationVector32 = VectorLoadAligned ( EndGains + 8 ) ;
const VectorRegister4Float GainDeltasVector32 = VectorDivide ( VectorSubtract ( DestinationVector32 , GainVector32 ) , NumFramesVector ) ;
2021-08-03 11:56:47 -04:00
GainVector32 = VectorMultiplyAdd ( GainDeltasVector32 , DeltaHalf31 , GainVector32 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 FrameIndex = 0 ; FrameIndex < NumFrames ; FrameIndex + = 2 )
{
const int32 InputIndex = FrameIndex * 2 ;
const int32 OutputIndex = FrameIndex * 6 ;
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input11 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex ] ) ;
const VectorRegister4Float Input21 = VectorSet ( SourceBuffer [ InputIndex ] , SourceBuffer [ InputIndex ] , SourceBuffer [ InputIndex + 2 ] , SourceBuffer [ InputIndex + 2 ] ) ;
const VectorRegister4Float Input31 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex + 2 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input12 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex + 1 ] ) ;
const VectorRegister4Float Input22 = VectorSet ( SourceBuffer [ InputIndex + 1 ] , SourceBuffer [ InputIndex + 1 ] , SourceBuffer [ InputIndex + 3 ] , SourceBuffer [ InputIndex + 3 ] ) ;
const VectorRegister4Float Input32 = VectorLoadFloat1 ( & SourceBuffer [ InputIndex + 3 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input11 , GainVector11 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input12 , GainVector12 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ OutputIndex ] ) ;
GainVector11 = VectorAdd ( GainVector11 , GainDeltasVector11 ) ;
GainVector12 = VectorAdd ( GainVector12 , GainDeltasVector12 ) ;
Result = VectorMultiply ( Input21 , GainVector21 ) ;
Result = VectorMultiplyAdd ( Input22 , GainVector22 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ OutputIndex + 4 ] ) ;
GainVector21 = VectorAdd ( GainVector21 , GainDeltasVector21 ) ;
GainVector22 = VectorAdd ( GainVector22 , GainDeltasVector22 ) ;
Result = VectorMultiply ( Input31 , GainVector31 ) ;
Result = VectorMultiplyAdd ( Input32 , GainVector31 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ OutputIndex + 8 ] ) ;
GainVector31 = VectorAdd ( GainVector31 , GainDeltasVector31 ) ;
GainVector32 = VectorAdd ( GainVector32 , GainDeltasVector32 ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply8ChannelGain ( FAlignedFloatBuffer & InterleavedBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Apply8ChannelGain ( InterleavedBuffer . GetData ( ) , InterleavedBuffer . Num ( ) , Gains ) ;
}
void Apply8ChannelGain ( float * RESTRICT InterleavedBuffer , int32 NumSamples , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector1 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector2 = VectorLoadAligned ( Gains + 4 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumSamples ; i + = 8 )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & InterleavedBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector1 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i ] ) ;
Result = VectorLoadAligned ( & InterleavedBuffer [ i + 4 ] ) ;
Result = VectorMultiply ( Result , GainVector2 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i + 4 ] ) ;
}
}
2021-05-04 16:05:46 -04:00
void Apply8ChannelGain ( FAlignedFloatBuffer & InterleavedBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Apply8ChannelGain ( InterleavedBuffer . GetData ( ) , InterleavedBuffer . Num ( ) , StartGains , EndGains ) ;
}
void Apply8ChannelGain ( float * RESTRICT InterleavedBuffer , int32 NumSamples , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( NumSamples / 8.0f ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector1 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector1 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector1 = VectorDivide ( VectorSubtract ( DestinationVector1 , GainVector1 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector2 = VectorLoadAligned ( StartGains + 4 ) ;
const VectorRegister4Float DestinationVector2 = VectorLoadAligned ( EndGains + 4 ) ;
const VectorRegister4Float GainDeltasVector2 = VectorDivide ( VectorSubtract ( DestinationVector2 , GainVector2 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumSamples ; i + = 8 )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadAligned ( & InterleavedBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector1 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i ] ) ;
GainVector1 = VectorAdd ( GainVector1 , GainDeltasVector1 ) ;
Result = VectorLoadAligned ( & InterleavedBuffer [ i + 4 ] ) ;
Result = VectorMultiply ( Result , GainVector2 ) ;
VectorStoreAligned ( Result , & InterleavedBuffer [ i + 4 ] ) ;
GainVector2 = VectorAdd ( GainVector2 , GainDeltasVector2 ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo8ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
MixMonoTo8ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 8 , Gains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | |
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 |
* | Gain | g0 | g1 | g2 | g3 | g4 | g5 | g6 | g7 |
* | | * | * | * | * | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 | i0 | i0 | i0 | i0 |
* | | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 |
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo8ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector1 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector2 = VectorLoadAligned ( Gains + 4 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiply ( Result , GainVector1 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 ] ) ;
Result = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
Result = VectorMultiply ( Result , GainVector2 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 + 4 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void MixMonoTo8ChannelsFast ( const FAlignedFloatBuffer & MonoBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
MixMonoTo8ChannelsFast ( MonoBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 8 , StartGains , EndGains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frames per iteration :
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | |
* | VectorName | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 |
* | Gain | g0 | g1 | g2 | g3 | g4 | g5 | g6 | g7 |
* | | * | * | * | * | * | * | * | * |
* | Input | i0 | i0 | i0 | i0 | i0 | i0 | i0 | i0 |
* | | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 |
* + - - - - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void MixMonoTo8ChannelsFast ( const float * RESTRICT MonoBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( ( float ) NumFrames ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector1 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector1 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector1 = VectorDivide ( VectorSubtract ( DestinationVector1 , GainVector1 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector2 = VectorLoadAligned ( StartGains + 4 ) ;
const VectorRegister4Float DestinationVector2 = VectorLoadAligned ( EndGains + 4 ) ;
const VectorRegister4Float GainDeltasVector2 = VectorDivide ( VectorSubtract ( DestinationVector2 , GainVector2 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input = VectorLoadFloat1 ( & MonoBuffer [ i ] ) ;
VectorRegister4Float Result = VectorMultiply ( Input , GainVector1 ) ;
2019-01-30 05:36:44 -05:00
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 ] ) ;
GainVector1 = VectorAdd ( GainVector1 , GainDeltasVector1 ) ;
Result = VectorMultiply ( Input , GainVector2 ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 + 4 ] ) ;
GainVector2 = VectorAdd ( GainVector2 , GainDeltasVector2 ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo8ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
Mix2ChannelsTo8ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 8 , Gains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frames per iteration :
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 |
* | Gain1 | g0 | g1 | g2 | g3 | g4 | g5 | g6 | g7 |
* | | * | * | * | * | * | * | * | * |
* | Input1 | i0 | i0 | i0 | i0 | i0 | i0 | i0 | i0 |
* | | + | + | + | + | + | + | + | + |
* | Gain2 | g8 | g9 | g10 | g11 | g12 | g13 | g14 | g5 |
* | | * | * | * | * | * | * | * | * |
* | Input2 | i1 | i1 | i1 | i1 | i1 | i1 | i1 | i1 |
* | | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void Mix2ChannelsTo8ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float GainVector11 = VectorLoadAligned ( Gains ) ;
const VectorRegister4Float GainVector21 = VectorLoadAligned ( Gains + 4 ) ;
const VectorRegister4Float GainVector12 = VectorLoadAligned ( Gains + 8 ) ;
const VectorRegister4Float GainVector22 = VectorLoadAligned ( Gains + 12 ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 ] ) ;
const VectorRegister4Float Input2 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 + 1 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector11 ) ;
2019-02-19 17:50:25 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector12 , Result ) ;
2019-01-30 05:36:44 -05:00
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 ] ) ;
2019-02-19 17:50:25 -05:00
Result = VectorMultiply ( Input1 , GainVector21 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector22 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 + 4 ] ) ;
}
}
2020-09-15 13:08:34 -04:00
void Mix2ChannelsTo8ChannelsFast ( const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
Mix2ChannelsTo8ChannelsFast ( SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , DestinationBuffer . Num ( ) / 8 , StartGains , EndGains ) ;
}
/**
* See CHANNEL MIXING OPERATIONS above for more info .
* 1 frames per iteration :
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | | Vector 1 | | | | Vector 2 | | | |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
* | | Index 0 | Index 1 | Index 2 | Index 3 | Index 4 | Index 5 | Index 6 | Index 7 |
* | Gain1 | g0 | g1 | g2 | g3 | g4 | g5 | g6 | g7 |
* | | * | * | * | * | * | * | * | * |
* | Input1 | i0 | i0 | i0 | i0 | i0 | i0 | i0 | i0 |
* | | + | + | + | + | + | + | + | + |
2019-02-19 17:50:25 -05:00
* | Gain2 | g8 | g9 | g10 | g11 | g12 | g13 | g14 | g15 |
2019-01-30 05:36:44 -05:00
* | | * | * | * | * | * | * | * | * |
* | Input2 | i1 | i1 | i1 | i1 | i1 | i1 | i1 | i1 |
* | | = | = | = | = | = | = | = | = |
* | Output | o0 | o1 | o2 | o3 | o4 | o5 | o6 | o7 |
* + - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - - + - - - - - - - - - + - - - - - - - - - + - - - - - - - - - +
*/
void Mix2ChannelsTo8ChannelsFast ( const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float NumFramesVector = VectorSetFloat1 ( ( float ) NumFrames ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector11 = VectorLoadAligned ( StartGains ) ;
const VectorRegister4Float DestinationVector11 = VectorLoadAligned ( EndGains ) ;
const VectorRegister4Float GainDeltasVector11 = VectorDivide ( VectorSubtract ( DestinationVector11 , GainVector11 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector21 = VectorLoadAligned ( StartGains + 4 ) ;
const VectorRegister4Float DestinationVector21 = VectorLoadAligned ( EndGains + 4 ) ;
const VectorRegister4Float GainDeltasVector21 = VectorDivide ( VectorSubtract ( DestinationVector21 , GainVector21 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector12 = VectorLoadAligned ( StartGains + 8 ) ;
const VectorRegister4Float DestinationVector12 = VectorLoadAligned ( EndGains + 8 ) ;
const VectorRegister4Float GainDeltasVector12 = VectorDivide ( VectorSubtract ( DestinationVector12 , GainVector12 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float GainVector22 = VectorLoadAligned ( StartGains + 12 ) ;
const VectorRegister4Float DestinationVector22 = VectorLoadAligned ( EndGains + 12 ) ;
const VectorRegister4Float GainDeltasVector22 = VectorDivide ( VectorSubtract ( DestinationVector22 , GainVector22 ) , NumFramesVector ) ;
2019-01-30 05:36:44 -05:00
for ( int32 i = 0 ; i < NumFrames ; i + + )
{
2021-05-05 15:07:25 -04:00
const VectorRegister4Float Input1 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 ] ) ;
const VectorRegister4Float Input2 = VectorLoadFloat1 ( & SourceBuffer [ i * 2 + 1 ] ) ;
2019-01-30 05:36:44 -05:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float Result = VectorMultiply ( Input1 , GainVector11 ) ;
2019-02-19 17:50:25 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector12 , Result ) ;
2019-01-30 05:36:44 -05:00
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 ] ) ;
GainVector11 = VectorAdd ( GainVector11 , GainDeltasVector11 ) ;
2019-02-19 17:50:25 -05:00
GainVector12 = VectorAdd ( GainVector12 , GainDeltasVector12 ) ;
2019-01-30 05:36:44 -05:00
2019-02-19 17:50:25 -05:00
Result = VectorMultiply ( Input1 , GainVector21 ) ;
2019-01-30 05:36:44 -05:00
Result = VectorMultiplyAdd ( Input2 , GainVector22 , Result ) ;
VectorStoreAligned ( Result , & DestinationBuffer [ i * 8 + 4 ] ) ;
2019-02-19 17:50:25 -05:00
GainVector21 = VectorAdd ( GainVector21 , GainDeltasVector21 ) ;
2019-01-30 05:36:44 -05:00
GainVector22 = VectorAdd ( GainVector22 , GainDeltasVector22 ) ;
}
}
/**
* These functions are non - vectorized versions of the Mix [ N ] ChannelsTo [ N ] Channels functions above :
*/
2020-09-15 13:08:34 -04:00
void DownmixBuffer ( int32 NumSourceChannels , int32 NumDestinationChannels , const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , const float * RESTRICT Gains )
2019-01-30 05:36:44 -05:00
{
DownmixBuffer ( NumSourceChannels , NumDestinationChannels , SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , SourceBuffer . Num ( ) / NumSourceChannels , Gains ) ;
}
void DownmixBuffer ( int32 NumSourceChannels , int32 NumDestinationChannels , const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , const float * RESTRICT Gains )
{
for ( int32 FrameIndex = 0 ; FrameIndex < NumFrames ; FrameIndex + + )
{
float * RESTRICT OutputFrame = & DestinationBuffer [ FrameIndex * NumDestinationChannels ] ;
const float * RESTRICT InputFrame = & SourceBuffer [ FrameIndex * NumSourceChannels ] ;
for ( int32 OutputChannelIndex = 0 ; OutputChannelIndex < NumDestinationChannels ; OutputChannelIndex + + )
{
2021-10-12 21:21:22 -04:00
float Value = 0.f ;
2019-01-30 05:36:44 -05:00
for ( int32 InputChannelIndex = 0 ; InputChannelIndex < NumSourceChannels ; InputChannelIndex + + )
{
2021-10-12 21:21:22 -04:00
Value + = InputFrame [ InputChannelIndex ] * Gains [ InputChannelIndex * NumDestinationChannels + OutputChannelIndex ] ;
2019-01-30 05:36:44 -05:00
}
2021-10-12 21:21:22 -04:00
OutputFrame [ OutputChannelIndex ] = Value ;
2019-01-30 05:36:44 -05:00
}
}
}
2020-09-15 13:08:34 -04:00
void DownmixBuffer ( int32 NumSourceChannels , int32 NumDestinationChannels , const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & DestinationBuffer , float * RESTRICT StartGains , const float * RESTRICT EndGains )
2019-01-30 05:36:44 -05:00
{
DownmixBuffer ( NumSourceChannels , NumDestinationChannels , SourceBuffer . GetData ( ) , DestinationBuffer . GetData ( ) , SourceBuffer . Num ( ) / NumSourceChannels , StartGains , EndGains ) ;
}
void DownmixBuffer ( int32 NumSourceChannels , int32 NumDestinationChannels , const float * RESTRICT SourceBuffer , float * RESTRICT DestinationBuffer , int32 NumFrames , float * RESTRICT StartGains , const float * RESTRICT EndGains )
{
// First, build a map of the per-frame delta that we will use to increment StartGains every frame:
2019-08-26 18:35:22 -04:00
check ( NumSourceChannels < = 8 & & NumDestinationChannels < = 8 ) ;
alignas ( 16 ) float GainDeltas [ 8 * 8 ] ;
2021-10-12 21:21:22 -04:00
2019-01-30 05:36:44 -05:00
for ( int32 OutputChannelIndex = 0 ; OutputChannelIndex < NumDestinationChannels ; OutputChannelIndex + + )
{
for ( int32 InputChannelIndex = 0 ; InputChannelIndex < NumSourceChannels ; InputChannelIndex + + )
{
2019-03-15 14:26:55 -04:00
const int32 GainMatrixIndex = InputChannelIndex * NumDestinationChannels + OutputChannelIndex ;
2019-01-30 05:36:44 -05:00
GainDeltas [ GainMatrixIndex ] = ( EndGains [ GainMatrixIndex ] - StartGains [ GainMatrixIndex ] ) / NumFrames ;
}
}
for ( int32 FrameIndex = 0 ; FrameIndex < NumFrames ; FrameIndex + + )
{
float * RESTRICT OutputFrame = & DestinationBuffer [ FrameIndex * NumDestinationChannels ] ;
const float * RESTRICT InputFrame = & SourceBuffer [ FrameIndex * NumSourceChannels ] ;
for ( int32 OutputChannelIndex = 0 ; OutputChannelIndex < NumDestinationChannels ; OutputChannelIndex + + )
{
2021-10-12 21:21:22 -04:00
float Value = 0.f ;
2019-01-30 05:36:44 -05:00
for ( int32 InputChannelIndex = 0 ; InputChannelIndex < NumSourceChannels ; InputChannelIndex + + )
{
const int32 GainMatrixIndex = InputChannelIndex * NumDestinationChannels + OutputChannelIndex ;
2021-10-12 21:21:22 -04:00
Value + = InputFrame [ InputChannelIndex ] * StartGains [ GainMatrixIndex ] ;
2019-01-30 05:36:44 -05:00
StartGains [ GainMatrixIndex ] + = GainDeltas [ GainMatrixIndex ] ;
}
2021-10-12 21:21:22 -04:00
OutputFrame [ OutputChannelIndex ] = Value ;
2019-01-30 05:36:44 -05:00
}
}
}
2019-05-05 21:00:38 -04:00
2020-09-15 13:08:34 -04:00
SIGNALPROCESSING_API void DownmixAndSumIntoBuffer ( int32 NumSourceChannels , int32 NumDestinationChannels , const FAlignedFloatBuffer & SourceBuffer , FAlignedFloatBuffer & BufferToSumTo , const float * RESTRICT Gains )
2020-02-09 18:57:53 -05:00
{
DownmixAndSumIntoBuffer ( NumSourceChannels , NumDestinationChannels , SourceBuffer . GetData ( ) , BufferToSumTo . GetData ( ) , SourceBuffer . Num ( ) / NumSourceChannels , Gains ) ;
}
SIGNALPROCESSING_API void DownmixAndSumIntoBuffer ( int32 NumSourceChannels , int32 NumDestinationChannels , const float * RESTRICT SourceBuffer , float * RESTRICT BufferToSumTo , int32 NumFrames , const float * RESTRICT Gains )
{
for ( int32 FrameIndex = 0 ; FrameIndex < NumFrames ; FrameIndex + + )
{
float * RESTRICT OutputFrame = & BufferToSumTo [ FrameIndex * NumDestinationChannels ] ;
const float * RESTRICT InputFrame = & SourceBuffer [ FrameIndex * NumSourceChannels ] ;
for ( int32 OutputChannelIndex = 0 ; OutputChannelIndex < NumDestinationChannels ; OutputChannelIndex + + )
{
2021-10-12 21:21:22 -04:00
float Value = 0.f ;
2020-02-09 18:57:53 -05:00
for ( int32 InputChannelIndex = 0 ; InputChannelIndex < NumSourceChannels ; InputChannelIndex + + )
{
2021-10-12 21:21:22 -04:00
Value + = InputFrame [ InputChannelIndex ] * Gains [ InputChannelIndex * NumDestinationChannels + OutputChannelIndex ] ;
2020-02-09 18:57:53 -05:00
}
2021-10-12 21:21:22 -04:00
OutputFrame [ OutputChannelIndex ] + = Value ;
2020-02-09 18:57:53 -05:00
}
}
}
2019-05-05 21:00:38 -04:00
/** Interleaves samples from two input buffers */
2020-09-15 13:08:34 -04:00
void BufferInterleave2ChannelFast ( const FAlignedFloatBuffer & InBuffer1 , const FAlignedFloatBuffer & InBuffer2 , FAlignedFloatBuffer & OutBuffer )
2019-05-05 21:00:38 -04:00
{
checkf ( InBuffer1 . Num ( ) = = InBuffer2 . Num ( ) , TEXT ( " InBuffer1 Num not equal to InBuffer2 Num " ) ) ;
const int32 InNum = InBuffer1 . Num ( ) ;
OutBuffer . Reset ( 2 * InNum ) ;
OutBuffer . AddUninitialized ( 2 * InNum ) ;
BufferInterleave2ChannelFast ( InBuffer1 . GetData ( ) , InBuffer2 . GetData ( ) , OutBuffer . GetData ( ) , InNum ) ;
}
/** Interleaves samples from two input buffers */
void BufferInterleave2ChannelFast ( const float * RESTRICT InBuffer1 , const float * RESTRICT InBuffer2 , float * RESTRICT OutBuffer , const int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = 4 , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InBuffer1 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InBuffer2 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
const int32 OutNum = 2 * InNum ;
int32 OutPos = 0 ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-05-05 21:00:38 -04:00
{
// Vector1[L0, L1, L2, L3]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Vector1 = VectorLoadAligned ( & InBuffer1 [ i ] ) ;
2019-05-05 21:00:38 -04:00
// Vector2[R0, R1, R2, R3]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Vector2 = VectorLoadAligned ( & InBuffer2 [ i ] ) ;
2019-05-05 21:00:38 -04:00
// HalfInterleaved[L0, L1, R0, R1]
2021-05-05 15:07:25 -04:00
VectorRegister4Float HalfInterleaved = VectorShuffle ( Vector1 , Vector2 , 0 , 1 , 0 , 1 ) ;
2019-05-05 21:00:38 -04:00
// Interleaved[L0, R0, L1, R1]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Interleaved = VectorSwizzle ( HalfInterleaved , 0 , 2 , 1 , 3 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Interleaved , & OutBuffer [ OutPos ] ) ;
2021-05-11 19:04:43 -04:00
OutPos + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
// HalfInterleaved[L2, L3, R2, R3]
HalfInterleaved = VectorShuffle ( Vector1 , Vector2 , 2 , 3 , 2 , 3 ) ;
// Interleaved[L2, R2, L3, R3]
Interleaved = VectorSwizzle ( HalfInterleaved , 0 , 2 , 1 , 3 ) ;
VectorStoreAligned ( Interleaved , & OutBuffer [ OutPos ] ) ;
2021-05-11 19:04:43 -04:00
OutPos + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
}
}
/** Deinterleaves samples from a 2 channel input buffer */
2020-09-15 13:08:34 -04:00
void BufferDeinterleave2ChannelFast ( const FAlignedFloatBuffer & InBuffer , FAlignedFloatBuffer & OutBuffer1 , FAlignedFloatBuffer & OutBuffer2 )
2019-05-05 21:00:38 -04:00
{
const int32 InNum = InBuffer . Num ( ) ;
const int32 InNumFrames = InNum / 2 ;
const int32 OutNum = InNumFrames ;
OutBuffer1 . Reset ( OutNum ) ;
OutBuffer2 . Reset ( OutNum ) ;
OutBuffer1 . AddUninitialized ( OutNum ) ;
OutBuffer2 . AddUninitialized ( OutNum ) ;
BufferDeinterleave2ChannelFast ( InBuffer . GetData ( ) , OutBuffer1 . GetData ( ) , OutBuffer2 . GetData ( ) , InNumFrames ) ;
}
/** Deinterleaves samples from a 2 channel input buffer */
void BufferDeinterleave2ChannelFast ( const float * RESTRICT InBuffer , float * RESTRICT OutBuffer1 , float * RESTRICT OutBuffer2 , const int32 InNumFrames )
{
2021-05-11 19:04:43 -04:00
checkf ( InNumFrames > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNumFrames % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InBuffer , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( OutBuffer1 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutBuffer2 , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
int32 InNum = InNumFrames * 2 ;
int32 OutPos = 0 ;
for ( int32 InPos = 0 ; InPos < InNum ; InPos + = 8 )
{
// load 4 frames (2 frames per vector)
2021-05-05 15:07:25 -04:00
VectorRegister4Float InVector1 = VectorLoadAligned ( & InBuffer [ InPos ] ) ;
VectorRegister4Float InVector2 = VectorLoadAligned ( & InBuffer [ InPos + 4 ] ) ;
2019-05-05 21:00:38 -04:00
// Write channel 0
2021-05-05 15:07:25 -04:00
VectorRegister4Float OutVector = VectorShuffle ( InVector1 , InVector2 , 0 , 2 , 0 , 2 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( OutVector , & OutBuffer1 [ OutPos ] ) ;
// Write channel 1
OutVector = VectorShuffle ( InVector1 , InVector2 , 1 , 3 , 1 , 3 ) ;
VectorStoreAligned ( OutVector , & OutBuffer2 [ OutPos ] ) ;
2021-05-11 19:04:43 -04:00
OutPos + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
}
}
/** Sums 2 channel interleaved input samples. OutSamples[n] = InSamples[2n] + InSamples[2n + 1] */
2020-09-15 13:08:34 -04:00
void BufferSum2ChannelToMonoFast ( const FAlignedFloatBuffer & InSamples , FAlignedFloatBuffer & OutSamples )
2019-05-05 21:00:38 -04:00
{
const int32 InNum = InSamples . Num ( ) ;
const int32 Frames = InNum / 2 ;
OutSamples . Reset ( Frames ) ;
OutSamples . AddUninitialized ( Frames ) ;
BufferSum2ChannelToMonoFast ( InSamples . GetData ( ) , OutSamples . GetData ( ) , Frames ) ;
}
/** Sums 2 channel interleaved input samples. OutSamples[n] = InSamples[2n] + InSamples[2n + 1] */
void BufferSum2ChannelToMonoFast ( const float * RESTRICT InSamples , float * RESTRICT OutSamples , const int32 InNumFrames )
{
2021-05-11 19:04:43 -04:00
checkf ( InNumFrames > = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNumFrames % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( IsAligned < const float * > ( InSamples , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutSamples , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-05-05 21:00:38 -04:00
const int32 InNum = InNumFrames * 2 ;
int32 OutPos = 0 ;
for ( int32 i = 0 ; i < InNum ; i + = 8 )
{
// Load 4 frames (2 frames per vector)
// Buffer1[L0, R0, L1, R1]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Buffer1 = VectorLoadAligned ( & InSamples [ i ] ) ;
2019-05-05 21:00:38 -04:00
// Buffer2[L2, R2, L3, R3]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Buffer2 = VectorLoadAligned ( & InSamples [ i + 4 ] ) ;
2019-05-05 21:00:38 -04:00
// Shuffle samples into order
// Channel0[L0, L1, L2, L3]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Channel0 = VectorShuffle ( Buffer1 , Buffer2 , 0 , 2 , 0 , 2 ) ;
2019-05-05 21:00:38 -04:00
// Channel1[R0, R1, R2, R3]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Channel1 = VectorShuffle ( Buffer1 , Buffer2 , 1 , 3 , 1 , 3 ) ;
2019-05-05 21:00:38 -04:00
// Sum left and right.
// Out[L0 + R0, L1 + R1, L2 + R2, L3 + R3]
2021-05-05 15:07:25 -04:00
VectorRegister4Float Out = VectorAdd ( Channel0 , Channel1 ) ;
2019-05-05 21:00:38 -04:00
VectorStoreAligned ( Out , & OutSamples [ OutPos ] ) ;
2021-05-11 19:04:43 -04:00
OutPos + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ;
2019-05-05 21:00:38 -04:00
}
}
2019-09-12 13:49:12 -04:00
2020-09-15 13:08:34 -04:00
void BufferComplexToPowerFast ( const FAlignedFloatBuffer & InRealSamples , const FAlignedFloatBuffer & InImaginarySamples , FAlignedFloatBuffer & OutPowerSamples )
2019-09-12 13:49:12 -04:00
{
checkf ( InRealSamples . Num ( ) = = InImaginarySamples . Num ( ) , TEXT ( " Input buffers must have equal number of elements " ) ) ;
const int32 Num = InRealSamples . Num ( ) ;
OutPowerSamples . Reset ( Num ) ;
OutPowerSamples . AddUninitialized ( Num ) ;
BufferComplexToPowerFast ( InRealSamples . GetData ( ) , InImaginarySamples . GetData ( ) , OutPowerSamples . GetData ( ) , Num ) ;
}
void BufferComplexToPowerFast ( const float * RESTRICT InRealSamples , const float * RESTRICT InImaginarySamples , float * RESTRICT OutPowerSamples , const int32 InNum )
{
2021-05-11 19:04:43 -04:00
checkf ( InNum > = 4 , TEXT ( " Buffer must have at least %i elements. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
checkf ( 0 = = ( InNum % AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) , TEXT ( " Buffer length be a multiple of %i. " ) , AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER ) ;
2019-09-12 13:49:12 -04:00
2021-05-11 19:04:43 -04:00
checkf ( IsAligned < const float * > ( InRealSamples , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < const float * > ( InImaginarySamples , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
checkf ( IsAligned < float * > ( OutPowerSamples , AUDIO_SIMD_BYTE_ALIGNMENT ) , TEXT ( " Memory must be aligned to use vector operations. " ) ) ;
2019-09-12 13:49:12 -04:00
2020-02-09 18:57:53 -05:00
RestrictedPtrAliasCheck ( InRealSamples , OutPowerSamples , InNum ) ;
RestrictedPtrAliasCheck ( InImaginarySamples , OutPowerSamples , InNum ) ;
2021-05-11 19:04:43 -04:00
for ( int32 i = 0 ; i < InNum ; i + = AUDIO_NUM_FLOATS_PER_VECTOR_REGISTER )
2019-09-12 13:49:12 -04:00
{
2021-05-05 15:07:25 -04:00
VectorRegister4Float VInReal = VectorLoadAligned ( & InRealSamples [ i ] ) ;
VectorRegister4Float VInRealSquared = VectorMultiply ( VInReal , VInReal ) ;
2019-09-12 13:49:12 -04:00
2021-05-05 15:07:25 -04:00
VectorRegister4Float VInImag = VectorLoadAligned ( & InImaginarySamples [ i ] ) ;
2021-08-03 11:56:47 -04:00
VectorRegister4Float VOut = VectorMultiplyAdd ( VInImag , VInImag , VInRealSquared ) ;
2019-09-12 13:49:12 -04:00
VectorStoreAligned ( VOut , & OutPowerSamples [ i ] ) ;
}
}
2020-02-09 18:57:53 -05:00
// class FBufferLinearEase implementation
FBufferLinearEase : : FBufferLinearEase ( ) { }
2020-09-15 13:08:34 -04:00
FBufferLinearEase : : FBufferLinearEase ( const FAlignedFloatBuffer & InSourceValues , const FAlignedFloatBuffer & InTargetValues , int32 InLerpLength )
2020-02-09 18:57:53 -05:00
{
Init ( InSourceValues , InTargetValues , InLerpLength ) ;
}
FBufferLinearEase : : ~ FBufferLinearEase ( ) { }
2020-09-15 13:08:34 -04:00
void FBufferLinearEase : : Init ( const FAlignedFloatBuffer & InSourceValues , const FAlignedFloatBuffer & InTargetValues , int32 InLerpLength )
2020-02-09 18:57:53 -05:00
{
check ( InSourceValues . Num ( ) ) ;
check ( InTargetValues . Num ( ) ) ;
check ( InLerpLength > 0 ) ;
BufferLength = InSourceValues . Num ( ) ;
check ( InTargetValues . Num ( ) = = BufferLength ) ;
LerpLength = InLerpLength ;
CurrentLerpStep = 0 ;
// init deltas
DeltaBuffer . Reset ( ) ;
DeltaBuffer . AddZeroed ( BufferLength ) ;
const float OneOverLerpLength = 1.0f / static_cast < float > ( LerpLength ) ;
BufferSubtractFast ( InTargetValues . GetData ( ) , InSourceValues . GetData ( ) , DeltaBuffer . GetData ( ) , BufferLength ) ;
MultiplyBufferByConstantInPlace ( DeltaBuffer , OneOverLerpLength ) ;
}
2021-05-04 16:05:46 -04:00
bool FBufferLinearEase : : Update ( FAlignedFloatBuffer & InSourceValues )
2020-02-09 18:57:53 -05:00
{
check ( InSourceValues . Num ( ) = = BufferLength ) ;
check ( CurrentLerpStep ! = LerpLength ) ;
MixInBufferFast ( DeltaBuffer . GetData ( ) , InSourceValues . GetData ( ) , BufferLength ) ;
if ( + + CurrentLerpStep = = LerpLength )
{
return true ;
}
return false ;
}
2020-09-15 13:08:34 -04:00
bool FBufferLinearEase : : Update ( uint32 StepsToJumpForward , FAlignedFloatBuffer & InSourceValues )
2020-02-09 18:57:53 -05:00
{
check ( InSourceValues . Num ( ) = = BufferLength ) ;
check ( CurrentLerpStep ! = LerpLength ) ;
check ( StepsToJumpForward ) ;
bool bIsComplete = false ;
if ( ( CurrentLerpStep + = StepsToJumpForward ) > = LerpLength )
{
StepsToJumpForward - = ( CurrentLerpStep - LerpLength ) ;
CurrentLerpStep = LerpLength ;
bIsComplete = true ;
}
MixInBufferFast ( DeltaBuffer . GetData ( ) , InSourceValues . GetData ( ) , BufferLength , static_cast < float > ( StepsToJumpForward ) ) ;
return bIsComplete ;
}
2020-09-15 13:08:34 -04:00
const FAlignedFloatBuffer & FBufferLinearEase : : GetDeltaBuffer ( )
2020-02-09 18:57:53 -05:00
{
return DeltaBuffer ;
}
2018-06-27 16:58:34 -04:00
}