Added a new quantized envelope

This commit is contained in:
Paul Ferrand 2019-12-12 18:27:18 +01:00
parent 75cf7dee96
commit 055f233d88
4 changed files with 121 additions and 9 deletions

View file

@ -79,9 +79,9 @@ static void FillSIMD_unaligned(benchmark::State& state) {
}
}
BENCHMARK(Dummy)->Range((2<<6), (2<<16));
BENCHMARK(FillScalar)->Range((2<<6), (2<<16));
BENCHMARK(FillSIMD)->Range((2<<6), (2<<16));
BENCHMARK(FillScalar_unaligned)->Range((2<<6), (2<<16));
BENCHMARK(FillSIMD_unaligned)->Range((2<<6), (2<<16));
BENCHMARK(Dummy)->RangeMultiplier(4)->Range((1<<2), (1<<12));
BENCHMARK(FillScalar)->RangeMultiplier(4)->Range((1<<2), (1<<12));
BENCHMARK(FillSIMD)->RangeMultiplier(4)->Range((1<<2), (1<<12));
BENCHMARK(FillScalar_unaligned)->RangeMultiplier(4)->Range((1<<2), (1<<12));
BENCHMARK(FillSIMD_unaligned)->RangeMultiplier(4)->Range((1<<2), (1<<12));
BENCHMARK_MAIN();

View file

@ -133,6 +133,63 @@ static void MulSIMDUnaligned(benchmark::State& state) {
}
}
static void LogDomainScalar(benchmark::State& state) {
sfz::Buffer<float> output(state.range(0));
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 1, 2 };
for (auto _ : state)
{
auto value = dist(gen);
sfz::linearRamp<float, false>(absl::MakeSpan(output), 1.0f, value);
sfz::applyGain<float, false>(std::log(2.0f), absl::MakeSpan(output));
sfz::exp<float, false>(output, absl::MakeSpan(output));
}
}
static void LogDomainSIMD(benchmark::State& state) {
sfz::Buffer<float> output(state.range(0));
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 1, 2 };
for (auto _ : state)
{
auto value = dist(gen);
sfz::linearRamp<float, true>(absl::MakeSpan(output), 1.0f, value);
sfz::applyGain<float, true>(std::log(2.0f), absl::MakeSpan(output));
sfz::exp<float, true>(output, absl::MakeSpan(output));
}
}
static void LogDomainScalarUnaligned(benchmark::State& state) {
sfz::Buffer<float> output(state.range(0));
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 1, 2 };
for (auto _ : state)
{
auto value = dist(gen);
auto outputSpan = absl::MakeSpan(output).subspan(1);
sfz::linearRamp<float, false>(outputSpan, 1.0f, value);
sfz::applyGain<float, false>(std::log(2.0f), outputSpan);
sfz::exp<float, false>(outputSpan, outputSpan);
}
}
static void LogDomainSIMDUnaligned(benchmark::State& state) {
sfz::Buffer<float> output(state.range(0));
std::random_device rd { };
std::mt19937 gen { rd() };
std::uniform_real_distribution<float> dist { 1, 2 };
for (auto _ : state)
{
auto value = dist(gen);
auto outputSpan = absl::MakeSpan(output).subspan(1);
sfz::linearRamp<float, true>(outputSpan, 1.0f, value);
sfz::applyGain<float, true>(std::log(2.0f), outputSpan);
sfz::exp<float, true>(outputSpan, outputSpan);
}
}
// Register the function as a benchmark
BENCHMARK(Dummy)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(LinearScalar)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
@ -143,4 +200,8 @@ BENCHMARK(MulScalar)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(MulSIMD)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(MulScalarUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(MulSIMDUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(LogDomainScalar)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(LogDomainSIMD)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(LogDomainScalarUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK(LogDomainSIMDUnaligned)->RangeMultiplier(4)->Range((1 << 2), (1 << 12));
BENCHMARK_MAIN();

View file

@ -103,13 +103,16 @@ void LinearEnvelope<Type>::getBlock(absl::Span<Type> output)
template <class Type>
void LinearEnvelope<Type>::getQuantizedBlock(absl::Span<Type> output, Type quantizationStep)
{
ASSERT(quantizationStep != 0.0);
absl::c_sort(events, [](const auto& lhs, const auto& rhs) {
return lhs.first < rhs.first;
});
int index { 0 };
auto quantize = [quantizationStep](Type value) -> Type {
return static_cast<int>(value / quantizationStep) * quantizationStep;
const auto halfStep = quantizationStep / 2;
auto quantize = [quantizationStep, halfStep](Type value) -> Type {
return static_cast<int>((value + halfStep) / quantizationStep) * quantizationStep;
};
currentValue = quantize(currentValue);
@ -125,9 +128,9 @@ void LinearEnvelope<Type>::getQuantizedBlock(absl::Span<Type> output, Type quant
const int numSteps = abs(newValue - currentValue) / quantizationStep;
const auto stepLength = static_cast<int>(length / numSteps);
while (outputSize - index > stepLength) {
currentValue += currentValue <= newValue ? quantizationStep : -quantizationStep;
for (int i = 0; i < numSteps; ++i) {
fill<Type>(output.subspan(index, stepLength), currentValue);
currentValue += currentValue <= newValue ? quantizationStep : -quantizationStep;
index += stepLength;
}
}

View file

@ -156,4 +156,52 @@ TEST_CASE("[LinearEnvelope] 2 events, function")
std::array<float, 8> expected { 1, 2, 2.5, 3, 3.5, 4.0, 4.0, 4.0 };
envelope.getBlock(absl::MakeSpan(output));
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0);
envelope.registerEvent(6, 2.0);
std::array<float, 8> output;
std::array<float, 8> expected { 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0 };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with 2 steps")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0);
envelope.registerEvent(6, 3.0);
std::array<float, 8> output;
std::array<float, 8> expected { 0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0 };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized with unclean events")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.2);
envelope.registerEvent(6, 2.5);
std::array<float, 8> output;
std::array<float, 8> expected { 0.0, 0.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0 };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
}
TEST_CASE("[LinearEnvelope] Get quantized 3 events, one out of block")
{
sfz::LinearEnvelope<float> envelope;
envelope.registerEvent(2, 1.0);
envelope.registerEvent(6, 2.0);
envelope.registerEvent(10, 3.0);
std::array<float, 8> output;
std::array<float, 8> expected { 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0 };
std::array<float, 8> expected2 { 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0 };
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected);
envelope.getQuantizedBlock(absl::MakeSpan(output), 1.0f);
REQUIRE(output == expected2);
}