Skip to content

Commit

Permalink
Temp work in progress
Browse files Browse the repository at this point in the history
  • Loading branch information
paulfd committed Sep 20, 2020
1 parent 0765630 commit 228617e
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 71 deletions.
38 changes: 26 additions & 12 deletions src/sfizz/Panning.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cmath>

#if SFIZZ_HAVE_NEON
#include <iostream>
#include <arm_neon.h>
#include "simd/Common.h"
using Type = float;
Expand Down Expand Up @@ -44,19 +45,30 @@ void pan(const float* panEnvelope, float* leftBuffer, float* rightBuffer, unsign
const auto sentinel = panEnvelope + size;

#if SFIZZ_HAVE_NEON
if (willAlign<ByteAlignment>(panEnvelope, leftBuffer, rightBuffer)) {
const auto firstAligned = prevAligned<ByteAlignment>(panEnvelope + TypeAlignment - 1);

if (willAlign<ByteAlignment>(panEnvelope, leftBuffer, rightBuffer) && (firstAligned < sentinel)) {
std::cout << "Neon path" << '\n';
while (panEnvelope < firstAligned) {
auto p =(*panEnvelope + 1.0f) * 0.5f;
p = clamp(p, 0.0f, 1.0f);
*leftBuffer *= panLookup(p);
*rightBuffer *= panLookup(1 - p);
incrementAll(panEnvelope, leftBuffer, rightBuffer);
}

uint32_t indices[TypeAlignment];
float leftPan[TypeAlignment];
float rightPan[TypeAlignment];
const auto lastAligned = panEnvelope + size;
const auto lastAligned = prevAligned<ByteAlignment>(sentinel);
while (panEnvelope < lastAligned) {
float32x4_t mmPan = vld1q_f32(panEnvelope);
mmPan = vaddq_f32(mmPan, vdupq_n_f32(1.0f));
mmPan = vmulq_n_f32(mmPan, 0.5f * panSize);
mmPan = vaddq_f32(mmPan, vdupq_n_f32(0.5f));
mmPan = vminq_f32(mmPan, vdupq_n_f32(panSize));
mmPan = vmaxq_f32(mmPan, vdupq_n_f32(0.0f));
uint32x4_t mmIdx = vcvtq_u32_f32(mmPan);
mmIdx = vminq_u32(mmIdx, vdupq_n_u32(panSize - 1));
mmIdx = vmaxq_u32(mmIdx, vdupq_n_u32(0));
vst1q_u32(indices, mmIdx);

leftPan[0] = panData[indices[0]];
Expand All @@ -74,15 +86,15 @@ void pan(const float* panEnvelope, float* leftBuffer, float* rightBuffer, unsign
incrementAll<TypeAlignment>(panEnvelope, leftBuffer, rightBuffer);
}
}
#else
#endif

while (panEnvelope < sentinel) {
auto p =(*panEnvelope + 1.0f) * 0.5f;
p = clamp(p, 0.0f, 1.0f);
*leftBuffer *= panLookup(p);
*rightBuffer *= panLookup(1 - p);
incrementAll(panEnvelope, leftBuffer, rightBuffer);
}
#endif // SFIZZ_HAVE_NEON

}

Expand All @@ -91,19 +103,21 @@ void width(const float* widthEnvelope, float* leftBuffer, float* rightBuffer, un
const auto sentinel = widthEnvelope + size;

#if SFIZZ_HAVE_NEON
if (willAlign<ByteAlignment>(widthEnvelope, leftBuffer, rightBuffer)) {
const auto firstAligned = prevAligned<ByteAlignment>(widthEnvelope + TypeAlignment - 1);

if (willAlign<ByteAlignment>(widthEnvelope, leftBuffer, rightBuffer) && firstAligned < sentinel) {
uint32_t indices[TypeAlignment];
float coeff1[TypeAlignment];
float coeff2[TypeAlignment];
const auto lastAligned = widthEnvelope + size;
const auto lastAligned = prevAligned<ByteAlignment>(sentinel);
while (widthEnvelope < lastAligned) {
float32x4_t mmWidth = vld1q_f32(widthEnvelope);
mmWidth = vaddq_f32(mmWidth, vdupq_n_f32(1.0f));
mmWidth = vmulq_n_f32(mmWidth, 0.5f * panSize);
mmWidth = vaddq_f32(mmWidth, vdupq_n_f32(0.5f));
mmWidth = vminq_f32(mmWidth, vdupq_n_f32(panSize));
mmWidth = vmaxq_f32(mmWidth, vdupq_n_f32(0.0f));
uint32x4_t mmIdx = vcvtq_u32_f32(mmWidth);
mmIdx = vminq_u32(mmIdx, vdupq_n_u32(panSize - 1));
mmIdx = vmaxq_u32(mmIdx, vdupq_n_u32(0));
vst1q_u32(indices, mmIdx);

coeff1[0] = panData[indices[0]];
Expand All @@ -126,7 +140,8 @@ void width(const float* widthEnvelope, float* leftBuffer, float* rightBuffer, un
incrementAll<TypeAlignment>(widthEnvelope, leftBuffer, rightBuffer);
}
}
#else
#endif // SFIZZ_HAVE_NEON

while (widthEnvelope < sentinel) {
float w = (*widthEnvelope + 1.0f) * 0.5f;
w = clamp(w, 0.0f, 1.0f);
Expand All @@ -138,7 +153,6 @@ void width(const float* widthEnvelope, float* leftBuffer, float* rightBuffer, un
*rightBuffer = l * coeff1 + r * coeff2;
incrementAll(widthEnvelope, leftBuffer, rightBuffer);
}
#endif // SFIZZ_HAVE_NEON
}

}
7 changes: 6 additions & 1 deletion src/sfizz/simd/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ bool unaligned(const T* ptr1, Args... rest)
template<unsigned N, class T, class... Args>
bool willAlign(const T* ptr1, const T* ptr2)
{
return (reinterpret_cast<uintptr_t>(ptr1) & ByteAlignmentMask(N)) == (reinterpret_cast<uintptr_t>(ptr2) & ByteAlignmentMask(N));
const auto p1 = reinterpret_cast<uintptr_t>(ptr1);
const auto p2 = reinterpret_cast<uintptr_t>(ptr2);
return (
(p1 & ByteAlignmentMask(N)) == (p2 & ByteAlignmentMask(N))
&& ((p1 & ByteAlignmentMask(sizeof(T))) == 0)
);
}

template<unsigned N, class T, class... Args>
Expand Down
139 changes: 81 additions & 58 deletions tests/SIMDHelpersT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ inline bool approxEqual(absl::Span<const Type> lhs, absl::Span<const Type> rhs,
return true;
}

TEST_CASE("[Helpers] willAlign and unaligned tests")
TEST_CASE("[Helpers] willAlign, prevAligned and unaligned tests")
{
std::array<float, 16> array;
alignas(64) std::array<float, 16> array;
REQUIRE( !unaligned<16>(&array[0]) );
REQUIRE( !unaligned<16>(&array[4]) );
REQUIRE( !unaligned<32>(&array[8]) );
Expand All @@ -63,11 +63,25 @@ TEST_CASE("[Helpers] willAlign and unaligned tests")
REQUIRE( !unaligned<16>(&array[0], &array[4], &array[8]) );
REQUIRE( unaligned<16>(&array[0], &array[3], &array[8]) );

REQUIRE( prevAligned<16>(&array[0]) == &array[0] );
REQUIRE( prevAligned<16>(&array[1]) == &array[0] );
REQUIRE( prevAligned<16>(&array[2]) == &array[0] );
REQUIRE( prevAligned<16>(&array[3]) == &array[0] );
REQUIRE( prevAligned<16>(&array[4]) == &array[4] );
REQUIRE( prevAligned<16>(&array[5]) == &array[4] );
REQUIRE( prevAligned<32>(&array[7]) == &array[0] );
REQUIRE( prevAligned<32>(&array[8]) == &array[8] );
REQUIRE( prevAligned<32>(&array[9]) == &array[8] );

REQUIRE( willAlign<16>(&array[0], &array[4]) );
REQUIRE( willAlign<16>(&array[5], &array[1]) );
REQUIRE( !willAlign<16>(&array[2], &array[1]) );
REQUIRE( willAlign<32>(&array[9], &array[1]) );
REQUIRE( willAlign<32>(&array[8], &array[0]) );

float* meanPointer = (float*)((uint8_t*)&array[1] + 1);
REQUIRE( !willAlign<16>(&array[0], meanPointer) );
REQUIRE( !willAlign<16>(&array[4], &array[0], meanPointer) );
}

TEST_CASE("[Helpers] Interleaved read")
Expand Down Expand Up @@ -855,62 +869,71 @@ TEST_CASE("[Helpers] Diff (SIMD vs Scalar)")
REQUIRE(approxEqual<float>(outputScalar, outputSIMD));
}

TEST_CASE("[Helpers] Pan Scalar")
{
std::array<float, 1> leftValue { 1.0f };
std::array<float, 1> rightValue { 1.0f };
auto left = absl::MakeSpan(leftValue);
auto right = absl::MakeSpan(rightValue);
SECTION("Pan = 0")
{
std::array<float, 1> pan { 0.0f };
sfz::pan(pan, left, right);
REQUIRE(left[0] == Approx(0.70711f).margin(0.001f));
REQUIRE(right[0] == Approx(0.70711f).margin(0.001f));
}
SECTION("Pan = 1")
{
std::array<float, 1> pan { 1.0f };
sfz::pan(pan, left, right);
REQUIRE(left[0] == Approx(0.0f).margin(0.001f));
REQUIRE(right[0] == Approx(1.0f).margin(0.001f));
}
SECTION("Pan = -1")
{
std::array<float, 1> pan { -1.0f };
sfz::pan(pan, left, right);
REQUIRE(left[0] == Approx(1.0f).margin(0.001f));
REQUIRE(right[0] == Approx(0.0f).margin(0.001f));
}
}

TEST_CASE("[Helpers] Width Scalar")
{
std::array<float, 1> leftValue { 1.0f };
std::array<float, 1> rightValue { 1.0f };
auto left = absl::MakeSpan(leftValue);
auto right = absl::MakeSpan(rightValue);
SECTION("width = 1")
{
std::array<float, 1> width { 1.0f };
sfz::width(width, left, right);
REQUIRE(left[0] == Approx(1.0f).margin(0.001f));
REQUIRE(right[0] == Approx(1.0f).margin(0.001f));
}
SECTION("width = 0")
{
std::array<float, 1> width { 0.0f };
sfz::width(width, left, right);
REQUIRE(left[0] == Approx(1.414f).margin(0.001f));
REQUIRE(right[0] == Approx(1.414f).margin(0.001f));
}
SECTION("width = -1")
{
std::array<float, 1> width { -1.0f };
sfz::width(width, left, right);
REQUIRE(left[0] == Approx(1.0f).margin(0.001f));
REQUIRE(right[0] == Approx(1.0f).margin(0.001f));
}
template<unsigned N>
void panTest(float leftValue, float rightValue, float panValue, float expectedLeft, float expectedRight)
{
std::vector<float> leftChannel(N);
std::vector<float> rightChannel(N);
std::vector<float> pan(N);
std::vector<float> expectedLeftChannel(N);
std::vector<float> expectedRightChannel(N);
std::fill(leftChannel.begin(), leftChannel.end(), leftValue);
std::fill(expectedLeftChannel.begin(), expectedLeftChannel.end(), expectedLeft);
std::fill(rightChannel.begin(), rightChannel.end(), rightValue);
std::fill(expectedRightChannel.begin(), expectedRightChannel.end(), expectedRight);
std::fill(pan.begin(), pan.end(), panValue);
auto left = absl::MakeSpan(leftChannel);
auto right = absl::MakeSpan(rightChannel);
sfz::pan(pan, left, right);
REQUIRE_THAT( leftChannel, Catch::Approx(expectedLeftChannel).margin(0.001) );
REQUIRE_THAT( rightChannel, Catch::Approx(expectedRightChannel).margin(0.001) );
}

template<unsigned N>
void widthTest(float leftValue, float rightValue, float widthValue, float expectedLeft, float expectedRight)
{
std::vector<float> leftChannel(N);
std::vector<float> rightChannel(N);
std::vector<float> width(N);
std::vector<float> expectedLeftChannel(N);
std::vector<float> expectedRightChannel(N);
std::fill(leftChannel.begin(), leftChannel.end(), leftValue);
std::fill(expectedLeftChannel.begin(), expectedLeftChannel.end(), expectedLeft);
std::fill(rightChannel.begin(), rightChannel.end(), rightValue);
std::fill(expectedRightChannel.begin(), expectedRightChannel.end(), expectedRight);
std::fill(width.begin(), width.end(), widthValue);
auto left = absl::MakeSpan(leftChannel);
auto right = absl::MakeSpan(rightChannel);
sfz::width(width, left, right);
REQUIRE_THAT( leftChannel, Catch::Approx(expectedLeftChannel).margin(0.001) );
REQUIRE_THAT( rightChannel, Catch::Approx(expectedRightChannel).margin(0.001) );
}

TEST_CASE("[Helpers] Pan tests")
{
// Testing different sizes to check that SIMD and unrolling works as expected
panTest<1>(1.0f, 1.0f, 0.0f, 0.70711f, 0.70711f);
panTest<1>(1.0f, 1.0f, 1.0f, 0.0f, 1.0f);
panTest<1>(1.0f, 1.0f, -1.0f, 1.0f, 0.0f);
panTest<3>(1.0f, 1.0f, 0.0f, 0.70711f, 0.70711f);
panTest<3>(1.0f, 1.0f, 1.0f, 0.0f, 1.0f);
panTest<3>(1.0f, 1.0f, -1.0f, 1.0f, 0.0f);
panTest<10>(1.0f, 1.0f, 0.0f, 0.70711f, 0.70711f);
panTest<10>(1.0f, 1.0f, 1.0f, 0.0f, 1.0f);
panTest<10>(1.0f, 1.0f, -1.0f, 1.0f, 0.0f);
}

TEST_CASE("[Helpers] Width tests")
{
widthTest<1>(1.0f, 1.0f, 0.0f, 1.414f, 1.414f);
widthTest<1>(1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
widthTest<1>(1.0f, 1.0f, -1.0f, 1.0f, 1.0f);
widthTest<3>(1.0f, 1.0f, 0.0f, 1.414f, 1.414f);
widthTest<3>(1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
widthTest<3>(1.0f, 1.0f, -1.0f, 1.0f, 1.0f);
widthTest<10>(1.0f, 1.0f, 0.0f, 1.414f, 1.414f);
widthTest<10>(1.0f, 1.0f, 1.0f, 1.0f, 1.0f);
widthTest<10>(1.0f, 1.0f, -1.0f, 1.0f, 1.0f);
}

TEST_CASE("[Helpers] clampAll")
Expand Down

0 comments on commit 228617e

Please sign in to comment.