From 4384c473f9c92ae81cbaedbc5ecd58ae9dd60b92 Mon Sep 17 00:00:00 2001 From: paulfd Date: Thu, 29 Aug 2019 19:15:06 +0200 Subject: [PATCH] Added iterators to the CCMap --- sources/CCMap.h | 7 ++-- sources/Range.h | 1 + sources/Region.cpp | 82 ++++++++++++++++++++++++++++++++++++++++++++-- sources/Region.h | 2 ++ sources/Synth.cpp | 5 +++ 5 files changed, 91 insertions(+), 6 deletions(-) diff --git a/sources/CCMap.h b/sources/CCMap.h index 58ec3138..093d83d3 100644 --- a/sources/CCMap.h +++ b/sources/CCMap.h @@ -18,7 +18,7 @@ public: const ValueType& getWithDefault(int index) const noexcept { auto it = container.find(index); - if (it == end(container)) { + if (it == container.end()) { return defaultValue; } else { return it->second; @@ -34,8 +34,9 @@ public: inline bool empty() const { return container.empty(); } const ValueType& at(int index) const { return container.at(index); } - bool contains(int index) const noexcept { return container.find(index) != end(container); } - + bool contains(int index) const noexcept { return container.find(index) != container.end(); } + typename std::map::iterator begin() { return container.begin(); } + typename std::map::iterator end() { return container.end(); } private: const ValueType defaultValue; std::map container; diff --git a/sources/Range.h b/sources/Range.h index 5f369d6d..d04922a8 100644 --- a/sources/Range.h +++ b/sources/Range.h @@ -35,6 +35,7 @@ public: std::pair getPair() const noexcept { return std::make_pair(_start, _end); } Range(const Range& range) = default; Range(Range&& range) = default; + constexpr Type length() { return _end - _start; } void setStart(Type start) noexcept { _start = start; diff --git a/sources/Region.cpp b/sources/Region.cpp index 161135d4..40260842 100644 --- a/sources/Region.cpp +++ b/sources/Region.cpp @@ -403,12 +403,12 @@ bool sfz::Region::parseOpcode(const Opcode& opcode) return true; } -bool sfz::Region::isSwitchedOn() const noexcept +bool sfz::Region::isSwitchedOn() const noexcept { return keySwitched && previousKeySwitched && sequenceSwitched && pitchSwitched && bpmSwitched && aftertouchSwitched && allCCSwitched; } -bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept +bool sfz::Region::registerNoteOn(int channel, int noteNumber, uint8_t velocity, float randValue) noexcept { const bool chanOk = channelRange.containsWithEnd(channel); if (!chanOk) @@ -558,7 +558,7 @@ float sfz::Region::getBasePitchVariation(int noteNumber, uint8_t velocity) noexc return centsFactor(pitchVariationInCents); } -float sfz::Region::getBaseGain() noexcept +float sfz::Region::getBaseGain() noexcept { float baseGaindB { volume }; baseGaindB += gainDistribution(Random::randomGenerator); @@ -591,4 +591,80 @@ bool sfz::Region::canUsePreloadedData() const noexcept bool sfz::Region::isStereo() const noexcept { return this->numChannels == 2; +} + +float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept +{ + float baseGain { 1.0f }; + + if (trigger == SfzTrigger::release_key) + baseGain *= velocityGain(lastNoteVelocities[noteNumber]); + else + baseGain *= velocityGain(velocity); + + if (noteNumber < crossfadeKeyInRange.getStart()) + baseGain = 0.0f; + else if (noteNumber < crossfadeKeyInRange.getEnd()) { + const auto crossfadePosition = static_cast(noteNumber - crossfadeKeyInRange.getStart()) / crossfadeKeyInRange.length(); + if (crossfadeKeyCurve == SfzCrossfadeCurve::power) + baseGain *= sqrt(crossfadePosition); + if (crossfadeKeyCurve == SfzCrossfadeCurve::gain) + baseGain *= crossfadePosition; + } + + if (noteNumber > crossfadeKeyOutRange.getEnd()) + baseGain = 0.0f; + else if (noteNumber > crossfadeKeyOutRange.getStart()) { + const auto crossfadePosition = static_cast(noteNumber - crossfadeKeyOutRange.getStart()) / crossfadeKeyOutRange.length(); + if (crossfadeKeyCurve == SfzCrossfadeCurve::power) + baseGain *= sqrt(1 - crossfadePosition); + if (crossfadeKeyCurve == SfzCrossfadeCurve::gain) + baseGain *= 1 - crossfadePosition; + } + + if (velocity < crossfadeVelInRange.getStart()) + baseGain = 0; + else if (velocity < crossfadeVelInRange.getEnd()) { + const auto crossfadePosition = static_cast(noteNumber - crossfadeVelInRange.getStart()) / crossfadeVelInRange.length(); + if (crossfadeVelCurve == SfzCrossfadeCurve::power) + baseGain *= sqrt(crossfadePosition); + if (crossfadeVelCurve == SfzCrossfadeCurve::gain) + baseGain *= crossfadePosition; + } + + if (velocity > crossfadeVelOutRange.getEnd()) + baseGain = 0; + else if (velocity > crossfadeVelOutRange.getStart()) { + const auto crossfadePosition = static_cast(noteNumber - crossfadeVelOutRange.getStart()) / crossfadeVelOutRange.length(); + if (crossfadeVelCurve == SfzCrossfadeCurve::power) + baseGain *= sqrt(1 - crossfadePosition); + if (crossfadeVelCurve == SfzCrossfadeCurve::gain) + baseGain *= 1 - crossfadePosition; + } + + return baseGain; +} + +float sfz::Region::velocityGain(uint8_t velocity) const noexcept +{ + float gaindB { 0.0 }; + if (velocityPoints.size() > 0) + { + auto after = std::find_if(velocityPoints.begin(), velocityPoints.end(), [velocity](auto& val) { return val.first >= velocity; }); + auto before = after == velocityPoints.begin() ? velocityPoints.begin() : after - 1; + // Linear interpolation + float relativePositionInSegment { static_cast(velocity - before->first) / (after->first - before->first) }; + float segmentEndpoints { after->second - before->second }; + gaindB = db2pow(relativePositionInSegment * segmentEndpoints); + } + else + { + float floatVelocity { static_cast(velocity)/127 }; + if (ampVeltrack > 0) + gaindB = 40 * std::log(floatVelocity) / std::log(10.0f); + else + gaindB = 40 * std::log(1-floatVelocity) / std::log(10.0f); + } + gaindB *= std::abs(ampVeltrack) / sfz::Default::ampVeltrackRange.getEnd(); + return db2pow(gaindB); } \ No newline at end of file diff --git a/sources/Region.h b/sources/Region.h index 97861944..82ed1d2b 100644 --- a/sources/Region.h +++ b/sources/Region.h @@ -31,7 +31,9 @@ struct Region { void registerTempo(float secondsPerQuarter) noexcept; bool isStereo() const noexcept; float getBasePitchVariation(int noteNumber, uint8_t velocity) noexcept; + float getNoteGain(int noteNumber, uint8_t velocity) noexcept; float getBaseGain() noexcept; + float velocityGain(uint8_t velocity) const noexcept; uint32_t getOffset() noexcept; uint32_t getDelay() noexcept; uint32_t trueSampleEnd() const noexcept; diff --git a/sources/Synth.cpp b/sources/Synth.cpp index 7b98aa76..666971a3 100644 --- a/sources/Synth.cpp +++ b/sources/Synth.cpp @@ -165,6 +165,11 @@ bool sfz::Synth::loadSfzFile(const std::filesystem::path& filename) region->registerNoteOn(region->channelRange.getStart(), *defaultSwitch, 127, 1.0); region->registerNoteOff(region->channelRange.getStart(), *defaultSwitch, 0, 1.0); } + + absl::c_sort(region->velocityPoints, [](const auto& lhs, const auto& rhs) { + return lhs.first < rhs.first; + }); + region->registerPitchWheel(region->channelRange.getStart(), 0); region->registerAftertouch(region->channelRange.getStart(), 0); region->registerTempo(2.0f);