Cleaning up the gains and volumes and stuff a bit. Hopefully it right(er) now
This commit is contained in:
parent
9da6fc6f78
commit
29488f5d40
4 changed files with 74 additions and 32 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue