Merge pull request #172 from paulfd/eg-issues

Solve some issues with DSmolken's drumkits
This commit is contained in:
JP Cimalando 2020-04-14 14:46:49 +02:00 committed by GitHub
commit 4c6febeca3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 96 additions and 8 deletions

View file

@ -284,6 +284,7 @@ void Application::performSfzUpdate()
QString code;
code += "<region>\n";
code += "key=69\n";
code += "sample="; code += QFileInfo(samplePath).fileName(); code += "\n";
code += _ui->envelopeEdit->toPlainText();

View file

@ -40,11 +40,9 @@ void ADSREnvelope<Type>::reset(const EGDescription& desc, const Region& region,
releaseDelay = 0;
shouldRelease = false;
freeRunning = (
(region.trigger == SfzTrigger::release)
freeRunning = ((region.trigger == SfzTrigger::release)
|| (region.trigger == SfzTrigger::release_key)
|| region.loopMode == SfzLoopMode::one_shot
);
|| (region.loopMode == SfzLoopMode::one_shot && (region.isGenerator() || region.oscillator)));
currentValue = this->start;
currentState = State::Delay;
}
@ -117,8 +115,7 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
// release takes effect this frame
currentState = State::Release;
releaseDelay = -1;
}
else if (shouldRelease && releaseDelay > 0) {
} else if (shouldRelease && releaseDelay > 0) {
// prevent computing the segment further than release point
size = std::min<size_t>(size, releaseDelay);
}
@ -188,6 +185,8 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
this->currentValue = currentValue;
this->shouldRelease = shouldRelease;
this->releaseDelay = releaseDelay;
ASSERT(!hasNanInf(output));
}
template <class Type>

View file

@ -11,6 +11,7 @@
#pragma once
#include "Config.h"
#include "Macros.h"
#include "absl/types/span.h"
#include <algorithm>
#include <cmath>
#include <random>
@ -292,3 +293,38 @@ inline F fp_from_parts(bool sgn, int ex, uint64_t mant)
(static_cast<I>(sgn) << (T::e_bits + T::m_bits));
return u.real;
}
template <class F>
inline bool fp_naninf(F x)
{
typedef FP_traits<F> T;
typedef typename T::same_size_int I;
union {
F real;
I integer;
} u;
u.real = x;
const auto all_ones = ((1u << T::e_bits) - 1);
const auto ex = (u.integer >> T::m_bits) & all_ones;
return ex == all_ones;
}
template <class Type>
bool hasNanInf(absl::Span<Type> span)
{
for (const auto& x : span)
if (fp_naninf(x))
return true;
return false;
}
template <class Type>
bool isValidAudio(absl::Span<Type> span)
{
for (const auto& x : span)
if (x < -1.0f || x > 1.0f)
return false;
return true;
}

View file

@ -624,6 +624,11 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
// Reset the dispatch counter
dispatchDuration = Duration(0);
ASSERT(!hasNanInf(buffer.getConstSpan(0)));
ASSERT(!hasNanInf(buffer.getConstSpan(1)));
ASSERT(isValidAudio(buffer.getConstSpan(0)));
ASSERT(isValidAudio(buffer.getConstSpan(1)));
}
void sfz::Synth::noteOn(int delay, int noteNumber, uint8_t velocity) noexcept

View file

@ -241,6 +241,12 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
powerHistory.push(buffer.meanSquared());
this->triggerDelay = absl::nullopt;
#if 0
ASSERT(!hasNanInf(buffer.getConstSpan(0)));
ASSERT(!hasNanInf(buffer.getConstSpan(1)));
ASSERT(isValidAudio(buffer.getConstSpan(0)));
ASSERT(isValidAudio(buffer.getConstSpan(1)));
#endif
}
void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
@ -515,6 +521,13 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
sourcePosition = indices->back();
floatPositionOffset = rightCoeffs->back();
#if 0
ASSERT(!hasNanInf(buffer.getConstSpan(0)));
ASSERT(!hasNanInf(buffer.getConstSpan(1)));
ASSERT(isValidAudio(buffer.getConstSpan(0)));
ASSERT(isValidAudio(buffer.getConstSpan(1)));
#endif
}
void sfz::Voice::fillWithGenerator(AudioSpan<float> buffer) noexcept
@ -573,6 +586,13 @@ void sfz::Voice::fillWithGenerator(AudioSpan<float> buffer) noexcept
}
}
}
#if 0
ASSERT(!hasNanInf(buffer.getConstSpan(0)));
ASSERT(!hasNanInf(buffer.getConstSpan(1)));
ASSERT(isValidAudio(buffer.getConstSpan(0)));
ASSERT(isValidAudio(buffer.getConstSpan(1)));
#endif
}
bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept

View file

@ -253,8 +253,18 @@ WavetableMulti WavetableMulti::createForHarmonicProfile(
const WavetableMulti* WavetableMulti::getSilenceWavetable()
{
static WavetableMulti wm;
wm.allocateStorage(1);
wm.fillExtra();
static bool initialized { false };
if (!initialized) {
constexpr unsigned numTables = WavetableMulti::numTables();
wm.allocateStorage(1);
for (unsigned m = 0; m < numTables; ++m) {
float* ptr = const_cast<float*>(wm.getTablePointer(m));
*ptr = 0;
}
wm.fillExtra();
initialized = true;
}
return &wm;
}

View file

@ -7,6 +7,7 @@
#include "catch2/catch.hpp"
#include "sfizz/MathHelpers.h"
#include <cmath>
#include <limits>
TEST_CASE("[FloatMath] Fast ilog2 (float)")
{
@ -51,3 +52,19 @@ TEST_CASE("[FloatMath] Break apart and reconstruct (double)")
REQUIRE(fp_from_parts<double>(sgn, ex, mant.num) == f);
}
}
TEST_CASE("[FloatMath] Nan/Inf checker")
{
REQUIRE(fp_naninf(std::numeric_limits<double>::quiet_NaN()));
REQUIRE(fp_naninf(std::numeric_limits<float>::quiet_NaN()));
REQUIRE(fp_naninf(std::numeric_limits<double>::infinity()));
REQUIRE(fp_naninf(std::numeric_limits<float>::infinity()));
REQUIRE(fp_naninf(-std::numeric_limits<double>::infinity()));
REQUIRE(fp_naninf(-std::numeric_limits<float>::infinity()));
REQUIRE(!fp_naninf(0.0f));
REQUIRE(!fp_naninf(0.0));
REQUIRE(!fp_naninf(1.0f));
REQUIRE(!fp_naninf(1.0));
REQUIRE(!fp_naninf(-1.0f));
REQUIRE(!fp_naninf(-1.0));
}