Resample one-coeff only

This commit is contained in:
Jean Pierre Cimalando 2020-05-15 17:58:28 +02:00
parent 420237e8dc
commit ff1cbb6c49
7 changed files with 43 additions and 55 deletions

View file

@ -22,8 +22,7 @@ public:
std::mt19937 gen { rd() }; std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 0, maxJump }; std::uniform_real_distribution<float> dist { 0, maxJump };
jumps = std::vector<int>(state.range(0)); jumps = std::vector<int>(state.range(0));
leftCoeffs = std::vector<float>(state.range(0)); coeffs = std::vector<float>(state.range(0));
rightCoeffs = std::vector<float>(state.range(0));
floatJumps = std::vector<float>(state.range(0)); floatJumps = std::vector<float>(state.range(0));
absl::c_generate(floatJumps, [&]() { return dist(gen); }); absl::c_generate(floatJumps, [&]() { return dist(gen); });
} }
@ -33,8 +32,7 @@ public:
} }
std::vector<int> jumps; std::vector<int> jumps;
std::vector<float> leftCoeffs; std::vector<float> coeffs;
std::vector<float> rightCoeffs;
std::vector<float> floatJumps; std::vector<float> floatJumps;
}; };
@ -42,28 +40,28 @@ public:
BENCHMARK_DEFINE_F(InterpolationCast, Scalar)(benchmark::State& state) { BENCHMARK_DEFINE_F(InterpolationCast, Scalar)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::sfzInterpolationCast<float, false>(floatJumps, absl::MakeSpan(jumps), absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs)); sfz::sfzInterpolationCast<float, false>(floatJumps, absl::MakeSpan(jumps), absl::MakeSpan(coeffs));
} }
} }
BENCHMARK_DEFINE_F(InterpolationCast, SIMD)(benchmark::State& state) { BENCHMARK_DEFINE_F(InterpolationCast, SIMD)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::sfzInterpolationCast<float, true>(floatJumps, absl::MakeSpan(jumps), absl::MakeSpan(leftCoeffs), absl::MakeSpan(rightCoeffs)); sfz::sfzInterpolationCast<float, true>(floatJumps, absl::MakeSpan(jumps), absl::MakeSpan(coeffs));
} }
} }
BENCHMARK_DEFINE_F(InterpolationCast, Scalar_Unaligned)(benchmark::State& state) { BENCHMARK_DEFINE_F(InterpolationCast, Scalar_Unaligned)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::sfzInterpolationCast<float, false>(absl::MakeSpan(floatJumps).subspan(1), absl::MakeSpan(jumps).subspan(3), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1)); sfz::sfzInterpolationCast<float, false>(absl::MakeSpan(floatJumps).subspan(1), absl::MakeSpan(jumps).subspan(3), absl::MakeSpan(coeffs).subspan(1));
} }
} }
BENCHMARK_DEFINE_F(InterpolationCast, SIMD_Unaligned)(benchmark::State& state) { BENCHMARK_DEFINE_F(InterpolationCast, SIMD_Unaligned)(benchmark::State& state) {
for (auto _ : state) for (auto _ : state)
{ {
sfz::sfzInterpolationCast<float, true>(absl::MakeSpan(floatJumps).subspan(1), absl::MakeSpan(jumps).subspan(3), absl::MakeSpan(leftCoeffs).subspan(2), absl::MakeSpan(rightCoeffs).subspan(1)); sfz::sfzInterpolationCast<float, true>(absl::MakeSpan(floatJumps).subspan(1), absl::MakeSpan(jumps).subspan(3), absl::MakeSpan(coeffs).subspan(1));
} }
} }

View file

@ -156,9 +156,9 @@ inline CXX14_CONSTEXPR void incrementAll(T& first, Args&... rest)
} }
template <class ValueType> template <class ValueType>
constexpr ValueType linearInterpolation(ValueType left, ValueType right, ValueType leftCoeff, ValueType rightCoeff) constexpr ValueType linearInterpolation(ValueType left, ValueType right, ValueType coeff)
{ {
return left * leftCoeff + right * rightCoeff; return left * (static_cast<ValueType>(1.0) - coeff) + right * coeff;
} }
template <class Type> template <class Type>

View file

@ -163,9 +163,9 @@ void sfz::cumsum<float, true>(absl::Span<const float> input, absl::Span<float> o
} }
template<> template<>
void sfz::sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept void sfz::sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> coeffs) noexcept
{ {
sfzInterpolationCast<float, false>(floatJumps, jumps, leftCoeffs, rightCoeffs); sfzInterpolationCast<float, false>(floatJumps, jumps, coeffs);
} }
template <> template <>

View file

@ -939,12 +939,11 @@ void cumsum<float, true>(absl::Span<const float> input, absl::Span<float> output
namespace _internals { namespace _internals {
template <class T> template <class T>
void snippetSFZInterpolationCast(const T*& floatJump, int*& jump, T*& leftCoeff, T*& rightCoeff) void snippetSFZInterpolationCast(const T*& floatJump, int*& jump, T*& coeff)
{ {
*jump = static_cast<int>(*floatJump); *jump = static_cast<int>(*floatJump);
*rightCoeff = *floatJump - static_cast<float>(*jump); *coeff = *floatJump - static_cast<float>(*jump);
*leftCoeff = static_cast<T>(1.0) - *rightCoeff; incrementAll(floatJump, coeff, jump);
incrementAll(floatJump, leftCoeff, rightCoeff, jump);
} }
} }
@ -960,24 +959,22 @@ namespace _internals {
* @param rightCoeffs the right interpolation coefficients * @param rightCoeffs the right interpolation coefficients
*/ */
template <class T, bool SIMD = SIMDConfig::sfzInterpolationCast> template <class T, bool SIMD = SIMDConfig::sfzInterpolationCast>
void sfzInterpolationCast(absl::Span<const T> floatJumps, absl::Span<int> jumps, absl::Span<T> leftCoeffs, absl::Span<T> rightCoeffs) noexcept void sfzInterpolationCast(absl::Span<const T> floatJumps, absl::Span<int> jumps, absl::Span<T> coeffs) noexcept
{ {
CHECK(jumps.size() >= floatJumps.size()); CHECK(jumps.size() >= floatJumps.size());
CHECK(jumps.size() == leftCoeffs.size()); CHECK(jumps.size() == coeffs.size());
CHECK(jumps.size() == rightCoeffs.size());
auto floatJump = floatJumps.data(); auto floatJump = floatJumps.data();
auto jump = jumps.data(); auto jump = jumps.data();
auto leftCoeff = leftCoeffs.data(); auto coeff = coeffs.data();
auto rightCoeff = rightCoeffs.data(); const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), coeffs.size());
const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), leftCoeffs.size(), rightCoeffs.size());
while (floatJump < sentinel) while (floatJump < sentinel)
_internals::snippetSFZInterpolationCast(floatJump, jump, leftCoeff, rightCoeff); _internals::snippetSFZInterpolationCast(floatJump, jump, coeff);
} }
template <> template <>
void sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept; void sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> coeffs) noexcept;
namespace _internals { namespace _internals {
template <class T> template <class T>

View file

@ -227,9 +227,9 @@ void sfz::cumsum<float, true>(absl::Span<const float> input, absl::Span<float> o
} }
template<> template<>
void sfz::sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept void sfz::sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> coeffs) noexcept
{ {
sfzInterpolationCast<float, false>(floatJumps, jumps, leftCoeffs, rightCoeffs); sfzInterpolationCast<float, false>(floatJumps, jumps, coeffs);
} }
template <> template <>

View file

@ -786,37 +786,33 @@ void sfz::cumsum<float, true>(absl::Span<const float> input, absl::Span<float> o
} }
template <> template <>
void sfz::sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> leftCoeffs, absl::Span<float> rightCoeffs) noexcept void sfz::sfzInterpolationCast<float, true>(absl::Span<const float> floatJumps, absl::Span<int> jumps, absl::Span<float> coeffs) noexcept
{ {
sfz::sfzInterpolationCast<float, false>(floatJumps, jumps, leftCoeffs, rightCoeffs); sfz::sfzInterpolationCast<float, false>(floatJumps, jumps, coeffs);
// CHECK(jumps.size() >= floatJumps.size()); // CHECK(jumps.size() >= floatJumps.size());
// CHECK(jumps.size() == leftCoeffs.size()); // CHECK(jumps.size() == coeffs.size());
// CHECK(jumps.size() == rightCoeffs.size());
// auto floatJump = floatJumps.data(); // auto floatJump = floatJumps.data();
// auto jump = jumps.data(); // auto jump = jumps.data();
// auto leftCoeff = leftCoeffs.data(); // auto coeff = coeffs.data();
// auto rightCoeff = rightCoeffs.data(); // const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), coeffs.size());
// const auto sentinel = floatJump + min(floatJumps.size(), jumps.size(), leftCoeffs.size(), rightCoeffs.size());
// const auto lastAligned = prevAligned(sentinel); // const auto lastAligned = prevAligned(sentinel);
// while (unaligned(floatJump, reinterpret_cast<float*>(jump), leftCoeff, rightCoeff) && floatJump < lastAligned) // while (unaligned(floatJump, reinterpret_cast<float*>(jump), coeff) && floatJump < lastAligned)
// _internals::snippetSFZInterpolationCast(floatJump, jump, leftCoeff, rightCoeff); // _internals::snippetSFZInterpolationCast(floatJump, jump, coeff);
// while (floatJump < lastAligned) { // while (floatJump < lastAligned) {
// auto mmFloatJumps = _mm_load_ps(floatJump); // auto mmFloatJumps = _mm_load_ps(floatJump);
// auto mmIndices = _mm_cvtps_epi32(_mm_sub_ps(mmFloatJumps, _mm_set_ps1(0.4999999552965164184570312f))); // auto mmIndices = _mm_cvtps_epi32(_mm_sub_ps(mmFloatJumps, _mm_set_ps1(0.4999999552965164184570312f)));
// _mm_store_si128(reinterpret_cast<__m128i*>(jump), mmIndices); // _mm_store_si128(reinterpret_cast<__m128i*>(jump), mmIndices);
// auto mmRight = _mm_sub_ps(mmFloatJumps, _mm_cvtepi32_ps(mmIndices)); // auto mmCoeff = _mm_sub_ps(mmFloatJumps, _mm_cvtepi32_ps(mmIndices));
// auto mmLeft = _mm_sub_ps(_mm_set_ps1(1.0f), mmRight); // _mm_store_ps(coeff, mmCoeff);
// _mm_store_ps(leftCoeff, mmLeft); // incrementAll<TypeAlignment>(floatJump, jump, coeff);
// _mm_store_ps(rightCoeff, mmRight);
// incrementAll<TypeAlignment>(floatJump, jump, leftCoeff, rightCoeff);
// } // }
// while(floatJump < sentinel) // while(floatJump < sentinel)
// _internals::snippetSFZInterpolationCast(floatJump, jump, leftCoeff, rightCoeff); // _internals::snippetSFZInterpolationCast(floatJump, jump, coeff);
} }
template <> template <>

View file

@ -443,10 +443,9 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
auto jumps = resources.bufferPool.getBuffer(numSamples); auto jumps = resources.bufferPool.getBuffer(numSamples);
auto bends = resources.bufferPool.getBuffer(numSamples); auto bends = resources.bufferPool.getBuffer(numSamples);
auto leftCoeffs = resources.bufferPool.getBuffer(numSamples); auto coeffs = resources.bufferPool.getBuffer(numSamples);
auto rightCoeffs = resources.bufferPool.getBuffer(numSamples);
auto indices = resources.bufferPool.getIndexBuffer(numSamples); auto indices = resources.bufferPool.getIndexBuffer(numSamples);
if (!jumps || !bends || !indices || !rightCoeffs || !leftCoeffs) if (!jumps || !bends || !indices || !coeffs)
return; return;
fill<float>(*jumps, pitchRatio * speedRatio); fill<float>(*jumps, pitchRatio * speedRatio);
@ -470,7 +469,7 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
jumps->front() += floatPositionOffset; jumps->front() += floatPositionOffset;
cumsum<float>(*jumps, *jumps); cumsum<float>(*jumps, *jumps);
sfzInterpolationCast<float>(*jumps, *indices, *leftCoeffs, *rightCoeffs); sfzInterpolationCast<float>(*jumps, *indices, *coeffs);
add<int>(sourcePosition, *indices); add<int>(sourcePosition, *indices);
if (region->shouldLoop() && region->loopEnd(currentPromise->oversamplingFactor) <= source.getNumFrames()) { if (region->shouldLoop() && region->loopEnd(currentPromise->oversamplingFactor) <= source.getNumFrames()) {
@ -500,35 +499,33 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
#endif #endif
egEnvelope.startRelease(i, true); egEnvelope.startRelease(i, true);
fill<int>(indices->subspan(i), sampleEnd); fill<int>(indices->subspan(i), sampleEnd);
fill<float>(leftCoeffs->subspan(i), 0.0f); fill<float>(coeffs->subspan(i), 1.0f);
fill<float>(rightCoeffs->subspan(i), 1.0f);
break; break;
} }
} }
} }
auto ind = indices->data(); auto ind = indices->data();
auto leftCoeff = leftCoeffs->data(); auto coeff = coeffs->data();
auto rightCoeff = rightCoeffs->data();
auto leftSource = source.getConstSpan(0); auto leftSource = source.getConstSpan(0);
auto left = buffer.getChannel(0); auto left = buffer.getChannel(0);
if (source.getNumChannels() == 1) { if (source.getNumChannels() == 1) {
while (ind < indices->end()) { while (ind < indices->end()) {
*left = linearInterpolation(leftSource[*ind], leftSource[*ind + 1], *leftCoeff, *rightCoeff); *left = linearInterpolation(leftSource[*ind], leftSource[*ind + 1], *coeff);
incrementAll(ind, left, leftCoeff, rightCoeff); incrementAll(ind, left, coeff);
} }
} else { } else {
auto right = buffer.getChannel(1); auto right = buffer.getChannel(1);
auto rightSource = source.getConstSpan(1); auto rightSource = source.getConstSpan(1);
while (ind < indices->end()) { while (ind < indices->end()) {
*left = linearInterpolation(leftSource[*ind], leftSource[*ind + 1], *leftCoeff, *rightCoeff); *left = linearInterpolation(leftSource[*ind], leftSource[*ind + 1], *coeff);
*right = linearInterpolation(rightSource[*ind], rightSource[*ind + 1], *leftCoeff, *rightCoeff); *right = linearInterpolation(rightSource[*ind], rightSource[*ind + 1], *coeff);
incrementAll(ind, left, right, leftCoeff, rightCoeff); incrementAll(ind, left, right, coeff);
} }
} }
sourcePosition = indices->back(); sourcePosition = indices->back();
floatPositionOffset = rightCoeffs->back(); floatPositionOffset = coeffs->back();
#if 0 #if 0
ASSERT(!hasNanInf(buffer.getConstSpan(0))); ASSERT(!hasNanInf(buffer.getConstSpan(0)));