Cleaning up the gains and volumes and stuff a bit. Hopefully it right(er) now

This commit is contained in:
paulfd 2019-09-09 17:44:53 +02:00
parent 9da6fc6f78
commit 29488f5d40
4 changed files with 74 additions and 32 deletions

View file

@ -284,7 +284,7 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
break;
case hash("amp_random"):
setValueFromOpcode(opcode, ampRandom, Default::ampRandomRange);
gainDistribution.param(std::uniform_real_distribution<float>::param_type(-ampRandom, ampRandom));
volumeDistribution.param(std::uniform_real_distribution<float>::param_type(-ampRandom, ampRandom));
break;
case hash("amp_velcurve_"):
if (opcode.parameter && Default::ccRange.containsWithEnd(*opcode.parameter)) {
@ -620,11 +620,14 @@ float sfz::Region::getBasePitchVariation(int noteNumber, uint8_t velocity) noexc
return centsFactor(pitchVariationInCents);
}
float sfz::Region::getBaseVolumedB() noexcept
{
return volume + volumeDistribution(Random::randomGenerator);
}
float sfz::Region::getBaseGain() noexcept
{
float baseGaindB { volume };
baseGaindB += gainDistribution(Random::randomGenerator);
return db2mag(baseGaindB);
return amplitude;
}
uint32_t sfz::Region::getOffset() noexcept
@ -692,20 +695,22 @@ float crossfadeOut(const Range<T>& crossfadeRange, U value, SfzCrossfadeCurve cu
float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
{
float baseGain { 1.0f };
float baseGain { 1.0 };
// Amplitude key tracking
baseGain *= db2mag(ampKeytrack * static_cast<float>(noteNumber - ampKeycenter));
// Crossfades related to the note number
baseGain *= crossfadeIn(crossfadeKeyInRange, noteNumber, crossfadeKeyCurve);
baseGain *= crossfadeOut(crossfadeKeyOutRange, noteNumber, crossfadeKeyCurve);
// Amplitude velocity tracking
if (trigger == SfzTrigger::release_key)
baseGain *= velocityGain(lastNoteVelocities[noteNumber]);
baseGain *= velocityCurve(lastNoteVelocities[noteNumber]);
else
baseGain *= velocityGain(velocity);
baseGain *= velocityCurve(velocity);
// Amplitude key tracking
baseGain *= db2pow(ampKeytrack * static_cast<float>(noteNumber - pitchKeycenter));
// Crossfades related to key and velocity
baseGain *= crossfadeIn(crossfadeKeyInRange, noteNumber, crossfadeKeyCurve);
baseGain *= crossfadeOut(crossfadeKeyOutRange, noteNumber, crossfadeKeyCurve);
// Crossfades related to velocity
baseGain *= crossfadeIn(crossfadeVelInRange, velocity, crossfadeVelCurve);
baseGain *= crossfadeOut(crossfadeVelOutRange, velocity, crossfadeVelCurve);
@ -732,9 +737,9 @@ float sfz::Region::getCrossfadeGain(const sfz::CCValueArray& ccState) noexcept
return gain;
}
float sfz::Region::velocityGain(uint8_t velocity) const noexcept
float sfz::Region::velocityCurve(uint8_t velocity) const noexcept
{
float gaindB { 0.0 };
float gain { 1.0 };
if (velocityPoints.size() > 0) { // Custom velocity curve
auto after = std::find_if(velocityPoints.begin(), velocityPoints.end(), [velocity](auto& val) { return val.first >= velocity; });
@ -742,17 +747,17 @@ float sfz::Region::velocityGain(uint8_t velocity) const noexcept
// Linear interpolation
float relativePositionInSegment { static_cast<float>(velocity - before->first) / (after->first - before->first) };
float segmentEndpoints { after->second - before->second };
gaindB = db2pow(relativePositionInSegment * segmentEndpoints);
gain *= relativePositionInSegment * segmentEndpoints;
} else { // Standard velocity curve
float floatVelocity { static_cast<float>(velocity) / 127 };
if (ampVeltrack > 0)
gaindB = 40 * std::log(floatVelocity) / std::log(10.0f);
const float floatVelocity { static_cast<float>(velocity) / 127 };
const float gaindB = [&]() {
if (ampVeltrack > 0)
return 40 * std::log(floatVelocity) / std::log(10.0f);
else
gaindB = 40 * std::log(1 - floatVelocity) / std::log(10.0f);
return 40 * std::log(1 - floatVelocity) / std::log(10.0f);
}();
gain *= db2mag( gaindB * std::abs(ampVeltrack) / sfz::Default::ampVeltrackRange.getEnd());
}
// Velocity tracking
gaindB *= std::abs(ampVeltrack) / sfz::Default::ampVeltrackRange.getEnd();
return db2pow(gaindB);
return gain;
}

View file

@ -57,8 +57,9 @@ struct Region {
float getBasePitchVariation(int noteNumber, uint8_t velocity) noexcept;
float getNoteGain(int noteNumber, uint8_t velocity) noexcept;
float getCrossfadeGain(const CCValueArray& ccState) noexcept;
float getBaseVolumedB() noexcept;
float getBaseGain() noexcept;
float velocityGain(uint8_t velocity) const noexcept;
float velocityCurve(uint8_t velocity) const noexcept;
uint32_t getOffset() noexcept;
uint32_t getDelay() noexcept;
uint32_t trueSampleEnd() const noexcept;
@ -161,7 +162,7 @@ private:
int activeNotesInRange { -1 };
int sequenceCounter { 0 };
std::uniform_real_distribution<float> gainDistribution { -sfz::Default::ampRandom, sfz::Default::ampRandom };
std::uniform_real_distribution<float> volumeDistribution { -sfz::Default::ampRandom, sfz::Default::ampRandom };
std::uniform_real_distribution<float> delayDistribution { 0, sfz::Default::delayRandom };
std::uniform_int_distribution<uint32_t> offsetDistribution { 0, sfz::Default::offsetRandom };
std::uniform_int_distribution<int> pitchDistribution { -sfz::Default::pitchRandom, sfz::Default::pitchRandom };

View file

@ -24,6 +24,7 @@
#include "Voice.h"
#include "AudioSpan.h"
#include "Defaults.h"
#include "MathHelpers.h"
#include "SIMDHelpers.h"
#include "SfzHelpers.h"
#include "absl/algorithm/container.h"
@ -52,13 +53,21 @@ void sfz::Voice::startVoice(Region* region, int delay, int channel, int number,
speedRatio = static_cast<float>(region->sampleRate / this->sampleRate);
pitchRatio = region->getBasePitchVariation(number, value);
baseVolumedB = region->getBaseVolumedB();
auto volumedB { baseVolumedB };
if (region->volumeCC)
volumedB += normalizeCC(ccState[region->volumeCC->first]) * region->volumeCC->second;
volumeEnvelope.reset(db2mag(volumedB));
baseGain = region->getBaseGain();
baseGain *= region->getCrossfadeGain(ccState);
if (triggerType != TriggerType::CC)
baseGain *= region->getNoteGain(number, value);
baseGain *= region->getCrossfadeGain(ccState);
float gain { baseGain };
if (region->amplitudeCC)
baseGain *= normalizeCC(ccState[region->amplitudeCC->first]) * normalizePercents(region->amplitudeCC->second);
amplitudeEnvelope.reset(baseGain);
gain *= normalizeCC(ccState[region->amplitudeCC->first]) * normalizePercents(region->amplitudeCC->second);
amplitudeEnvelope.reset(gain);
basePan = normalizeNegativePercents(region->pan);
auto pan = basePan;
@ -152,14 +161,29 @@ void sfz::Voice::registerCC(int delay, int channel [[maybe_unused]], int ccNumbe
release(delay);
if (region->amplitudeCC && ccNumber == region->amplitudeCC->first) {
const float newGain { normalizeCC(ccValue) * normalizePercents(region->amplitudeCC->second) * baseGain };
const float newGain { baseGain * normalizeCC(ccValue) * normalizePercents(region->amplitudeCC->second) };
amplitudeEnvelope.registerEvent(delay, newGain);
}
if (region->volumeCC && ccNumber == region->volumeCC->first) {
const float newVolumedB { baseVolumedB + normalizeCC(ccValue) * region->volumeCC->second };
amplitudeEnvelope.registerEvent(delay, db2mag(newVolumedB));
}
if (region->panCC && ccNumber == region->panCC->first) {
const float newPan { basePan + normalizeCC(ccValue) * normalizeNegativePercents(region->panCC->second)};
panEnvelope.registerEvent(delay, newPan);
}
if (region->positionCC && ccNumber == region->positionCC->first) {
const float newPosition { basePosition + normalizeCC(ccValue) * normalizeNegativePercents(region->positionCC->second)};
positionEnvelope.registerEvent(delay, newPosition);
}
if (region->widthCC && ccNumber == region->widthCC->first) {
const float newWidth { baseWidth + normalizeCC(ccValue) * normalizeNegativePercents(region->widthCC->second)};
widthEnvelope.registerEvent(delay, newWidth);
}
}
void sfz::Voice::registerPitchWheel(int delay [[maybe_unused]], int channel [[maybe_unused]], int pitch [[maybe_unused]]) noexcept
@ -233,7 +257,11 @@ void sfz::Voice::processMono(AudioSpan<float> buffer) noexcept
// AmpEG envelope
egEnvelope.getBlock(span1);
::applyGain<float>(span1, leftBuffer);
// Volume envelope
volumeEnvelope.getBlock(span1);
::applyGain<float>(span1, leftBuffer);
// Prepare for stereo output
::copy<float>(leftBuffer, rightBuffer);
@ -258,12 +286,18 @@ void sfz::Voice::processStereo(AudioSpan<float> buffer) noexcept
auto leftBuffer = buffer.getSpan(0);
auto rightBuffer = buffer.getSpan(1);
// Amplitude envelope
amplitudeEnvelope.getBlock(span1);
buffer.applyGain(span1);
// AmpEG envelope
egEnvelope.getBlock(span1);
buffer.applyGain(span1);
// Volume envelope
volumeEnvelope.getBlock(span1);
buffer.applyGain(span1);
// Create mid/side from left/right in the output buffer
::copy<float>(rightBuffer, span1);
::add<float>(leftBuffer, rightBuffer);

View file

@ -90,6 +90,7 @@ private:
float speedRatio { 1.0 };
float pitchRatio { 1.0 };
float baseVolumedB{ 0.0 };
float baseGain { 1.0 };
float basePan { 0.0 };
float basePosition { 0.0 };
@ -119,7 +120,8 @@ private:
const CCValueArray& ccState;
ADSREnvelope<float> egEnvelope;
LinearEnvelope<float> amplitudeEnvelope;
LinearEnvelope<float> volumeEnvelope; // dB events but the envelope output is linear gain
LinearEnvelope<float> amplitudeEnvelope; // linear events
LinearEnvelope<float> panEnvelope;
LinearEnvelope<float> positionEnvelope;
LinearEnvelope<float> widthEnvelope;