Merge pull request #172 from paulfd/eg-issues
Solve some issues with DSmolken's drumkits
This commit is contained in:
commit
4c6febeca3
7 changed files with 96 additions and 8 deletions
|
|
@ -284,6 +284,7 @@ void Application::performSfzUpdate()
|
||||||
|
|
||||||
QString code;
|
QString code;
|
||||||
code += "<region>\n";
|
code += "<region>\n";
|
||||||
|
code += "key=69\n";
|
||||||
code += "sample="; code += QFileInfo(samplePath).fileName(); code += "\n";
|
code += "sample="; code += QFileInfo(samplePath).fileName(); code += "\n";
|
||||||
code += _ui->envelopeEdit->toPlainText();
|
code += _ui->envelopeEdit->toPlainText();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,9 @@ void ADSREnvelope<Type>::reset(const EGDescription& desc, const Region& region,
|
||||||
|
|
||||||
releaseDelay = 0;
|
releaseDelay = 0;
|
||||||
shouldRelease = false;
|
shouldRelease = false;
|
||||||
freeRunning = (
|
freeRunning = ((region.trigger == SfzTrigger::release)
|
||||||
(region.trigger == SfzTrigger::release)
|
|
||||||
|| (region.trigger == SfzTrigger::release_key)
|
|| (region.trigger == SfzTrigger::release_key)
|
||||||
|| region.loopMode == SfzLoopMode::one_shot
|
|| (region.loopMode == SfzLoopMode::one_shot && (region.isGenerator() || region.oscillator)));
|
||||||
);
|
|
||||||
currentValue = this->start;
|
currentValue = this->start;
|
||||||
currentState = State::Delay;
|
currentState = State::Delay;
|
||||||
}
|
}
|
||||||
|
|
@ -117,8 +115,7 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
|
||||||
// release takes effect this frame
|
// release takes effect this frame
|
||||||
currentState = State::Release;
|
currentState = State::Release;
|
||||||
releaseDelay = -1;
|
releaseDelay = -1;
|
||||||
}
|
} else if (shouldRelease && releaseDelay > 0) {
|
||||||
else if (shouldRelease && releaseDelay > 0) {
|
|
||||||
// prevent computing the segment further than release point
|
// prevent computing the segment further than release point
|
||||||
size = std::min<size_t>(size, releaseDelay);
|
size = std::min<size_t>(size, releaseDelay);
|
||||||
}
|
}
|
||||||
|
|
@ -188,6 +185,8 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
|
||||||
this->currentValue = currentValue;
|
this->currentValue = currentValue;
|
||||||
this->shouldRelease = shouldRelease;
|
this->shouldRelease = shouldRelease;
|
||||||
this->releaseDelay = releaseDelay;
|
this->releaseDelay = releaseDelay;
|
||||||
|
|
||||||
|
ASSERT(!hasNanInf(output));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Type>
|
template <class Type>
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Macros.h"
|
#include "Macros.h"
|
||||||
|
#include "absl/types/span.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <random>
|
#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));
|
(static_cast<I>(sgn) << (T::e_bits + T::m_bits));
|
||||||
return u.real;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -624,6 +624,11 @@ void sfz::Synth::renderBlock(AudioSpan<float> buffer) noexcept
|
||||||
|
|
||||||
// Reset the dispatch counter
|
// Reset the dispatch counter
|
||||||
dispatchDuration = Duration(0);
|
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
|
void sfz::Synth::noteOn(int delay, int noteNumber, uint8_t velocity) noexcept
|
||||||
|
|
|
||||||
|
|
@ -241,6 +241,12 @@ void sfz::Voice::renderBlock(AudioSpan<float> buffer) noexcept
|
||||||
|
|
||||||
powerHistory.push(buffer.meanSquared());
|
powerHistory.push(buffer.meanSquared());
|
||||||
this->triggerDelay = absl::nullopt;
|
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
|
void sfz::Voice::amplitudeEnvelope(absl::Span<float> modulationSpan) noexcept
|
||||||
|
|
@ -515,6 +521,13 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
|
||||||
|
|
||||||
sourcePosition = indices->back();
|
sourcePosition = indices->back();
|
||||||
floatPositionOffset = rightCoeffs->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
|
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
|
bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept
|
||||||
|
|
|
||||||
|
|
@ -253,8 +253,18 @@ WavetableMulti WavetableMulti::createForHarmonicProfile(
|
||||||
const WavetableMulti* WavetableMulti::getSilenceWavetable()
|
const WavetableMulti* WavetableMulti::getSilenceWavetable()
|
||||||
{
|
{
|
||||||
static WavetableMulti wm;
|
static WavetableMulti wm;
|
||||||
wm.allocateStorage(1);
|
static bool initialized { false };
|
||||||
wm.fillExtra();
|
|
||||||
|
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;
|
return &wm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
#include "catch2/catch.hpp"
|
#include "catch2/catch.hpp"
|
||||||
#include "sfizz/MathHelpers.h"
|
#include "sfizz/MathHelpers.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
TEST_CASE("[FloatMath] Fast ilog2 (float)")
|
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);
|
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));
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue