#include "Globals.h" #include #include "Helpers.h" #include template void readInterleaved(absl::Span input, absl::Span outputLeft, absl::Span outputRight) noexcept { // The size of the output is not big enough for the input... ASSERT(outputLeft.size() >= input.size() / 2); ASSERT(outputRight.size() >= input.size() / 2); auto* in = input.begin(); auto* lOut = outputLeft.begin(); auto* rOut = outputRight.begin(); while (in < (input.end() - 1) && lOut < outputLeft.end() && rOut < outputRight.end()) { *lOut++ = *in++; *rOut++ = *in++; } } template void writeInterleaved(absl::Span inputLeft, absl::Span inputRight, absl::Span output) noexcept { ASSERT(inputLeft.size() <= output.size() / 2); ASSERT(inputRight.size() <= output.size() / 2); auto* lIn = inputLeft.begin(); auto* rIn = inputRight.begin(); auto* out = output.begin(); while (lIn < inputLeft.end() && rIn < inputRight.end() && out < (output.end() - 1)) { *out++ = *lIn++; *out++ = *rIn++; } } // Specializations template<> void writeInterleaved(absl::Span inputLeft, absl::Span inputRight, absl::Span output) noexcept; template<> void readInterleaved(absl::Span input, absl::Span outputLeft, absl::Span outputRight) noexcept; template void fill(absl::Span output, T value) noexcept { std::fill(output.begin(), output.end(), value); } template<> void fill(absl::Span output, float value) noexcept; template void exp(absl::Span input, absl::Span output) noexcept { ASSERT(output.size() >= input.size()); auto sentinel = std::min(input.size(), output.size()); for (decltype(sentinel) i = 0; i < sentinel; ++i) output[i] = std::exp(input[i]); } template<> void exp(absl::Span input, absl::Span output) noexcept; template void log(absl::Span input, absl::Span output) noexcept { ASSERT(output.size() >= input.size()); auto sentinel = std::min(input.size(), output.size()); for (decltype(sentinel) i = 0; i < sentinel; ++i) output[i] = std::log(input[i]); } template<> void log(absl::Span input, absl::Span output) noexcept; template void sin(absl::Span input, absl::Span output) noexcept { ASSERT(output.size() >= input.size()); auto sentinel = std::min(input.size(), output.size()); for (decltype(sentinel) i = 0; i < sentinel; ++i) output[i] = std::sin(input[i]); } template<> void sin(absl::Span input, absl::Span output) noexcept; template void cos(absl::Span input, absl::Span output) noexcept { ASSERT(output.size() >= input.size()); auto sentinel = std::min(input.size(), output.size()); for (decltype(sentinel) i = 0; i < sentinel; ++i) output[i] = std::cos(input[i]); } template<> void cos(absl::Span input, absl::Span output) noexcept; template void loopingSFZIndex(absl::Span jumps, absl::Span leftCoeffs, absl::Span rightCoeffs, absl::Span indices, T floatIndex, T loopEnd, T loopStart) noexcept { ASSERT(indices.size() >= jumps.size()); ASSERT(indices.size() == leftCoeffs.size()); ASSERT(indices.size() == rightCoeffs.size()); auto* index = indices.begin(); auto* leftCoeff = leftCoeffs.begin(); auto* rightCoeff = rightCoeffs.begin(); auto* jump = jumps.begin(); const auto size = min(jumps.size(), indices.size(), leftCoeffs.size(), rightCoeffs.size()); auto* sentinel = jumps.begin() + size; while (jump < sentinel) { floatIndex += *jump; if (floatIndex >= loopEnd) floatIndex -= loopEnd - loopStart; *index = static_cast(floatIndex); *rightCoeff = floatIndex - *index; *leftCoeff = 1.0f - *rightCoeff; index++; leftCoeff++; rightCoeff++; jump++; } } template<> void loopingSFZIndex(absl::Span jumps, absl::Span leftCoeff, absl::Span rightCoeff, absl::Span indices, float floatIndex, float loopEnd, float loopStart) noexcept; template void linearRamp(absl::Span output, T start, T end); template void exponentialRamp(absl::Span output, T start, T end); template void applyGain(T gain, absl::Span input, absl::Span output) noexcept { ASSERT(input.size() <= output.size()); auto* in = input.begin(); auto* out = output.begin(); auto* sentinel = out + std::min(output.size(), input.size()); while (out < sentinel) { *out++ = gain * (*in++); } } template void applyGain(absl::Span gain, absl::Span input, absl::Span output) noexcept { ASSERT(gain.size() == input.size()); ASSERT(input.size() <= output.size()); auto* in = input.begin(); auto* g = gain.begin(); auto* out = output.begin(); auto* sentinel = out + std::min(gain.size(), std::min(output.size(), input.size())); while (out < sentinel) { *out++ = (*g++) * (*in++); } } template void applyGain(T gain, absl::Span output) noexcept { applyGain(gain, output, output); } template void applyGain(absl::Span gain, absl::Span output) noexcept { applyGain(gain, output, output); } template<> void applyGain(float gain, absl::Span input, absl::Span output) noexcept; template<> void applyGain(absl::Span gain, absl::Span input, absl::Span output) noexcept;