#pragma once #include "Globals.h" #include "Helpers.h" #include #include #include template inline void snippetRead(const T*& input, T*& outputLeft, T*& outputRight) { *outputLeft++ = *input++; *outputRight++ = *input++; } 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()) snippetRead(in, lOut, rOut); } template inline void snippetWrite(T*& output, const T*& inputLeft, const T*& inputRight) { *output++ = *inputLeft++; *output++ = *inputRight++; } 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)) snippetWrite(out, lIn, 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 { absl::c_fill(output, 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 inline void snippetLoopingIndex(const T*& jump, T*& leftCoeff, T*& rightCoeff, int*& index, T& floatIndex, T loopEnd, T loopStart) { 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 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) snippetLoopingIndex(jump, leftCoeff, rightCoeff, index, floatIndex, loopEnd, loopStart); } template <> void loopingSFZIndex(absl::Span jumps, absl::Span leftCoeff, absl::Span rightCoeff, absl::Span indices, float floatIndex, float loopEnd, float loopStart) noexcept; template inline void snippetGain(T gain, const T*& input, T*& output) { *output++ = gain * (*input++); } 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) snippetGain(gain, in, out); } template inline void snippetGainSpan(const T*& gain, const T*& input, T*& output) { *output++ = (*gain++) * (*input++); } 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) snippetGainSpan(g, in, out); } 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; template inline void snippetRampLinear(T*& output, T& value, T step) { value += step; *output++ = value; } template T linearRamp(absl::Span output, T start, T step) noexcept { auto* out = output.begin(); while (out < output.end()) snippetRampLinear(out, start, step); return start; } template inline void snippetRampMultiplicative(T*& output, T& value, T step) { value *= step; *output++ = value; } template T multiplicativeRamp(absl::Span output, T start, T step) noexcept { auto* out = output.begin(); while (out < output.end()) snippetRampMultiplicative(out, start, step); return start; } template <> float linearRamp(absl::Span output, float start, float step) noexcept; template <> float multiplicativeRamp(absl::Span output, float start, float step) noexcept; template inline void snippetAdd(const T*& input, T*& output) { *output++ += *input++; } template void add(absl::Span input, absl::Span output) noexcept { ASSERT(output.size() >= input.size()); auto* in = input.begin(); auto* out = output.begin(); auto* sentinel = out + min(input.size(), output.size()); while (out < sentinel) snippetAdd(in, out); } template <> void add(absl::Span input, absl::Span output) noexcept;