Add amp and pitch veltrack oncc

This commit is contained in:
Paul Fd 2021-07-05 09:22:07 +02:00
parent f84cacebf6
commit 3658de4497
6 changed files with 54 additions and 31 deletions

View file

@ -1724,19 +1724,6 @@ bool sfz::Region::processGenericCc(const Opcode& opcode, OpcodeSpec<float> spec,
return true; return true;
} }
float sfz::Region::getBasePitchVariation(float noteNumber, float velocity) const noexcept
{
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
fast_real_distribution<float> pitchDistribution { 0.0f, pitchRandom };
float pitchVariationInCents = pitchKeytrack * (noteNumber - float(pitchKeycenter)); // note difference with pitch center
pitchVariationInCents += pitch; // sample tuning
pitchVariationInCents += config::centPerSemitone * transpose; // sample transpose
pitchVariationInCents += velocity * pitchVeltrack; // track velocity
pitchVariationInCents += pitchDistribution(Random::randomGenerator); // random pitch changes
return centsFactor(pitchVariationInCents);
}
float sfz::Region::getBaseGain() const noexcept float sfz::Region::getBaseGain() const noexcept
{ {
float baseGain = amplitude; float baseGain = amplitude;

View file

@ -99,15 +99,6 @@ struct Region {
*/ */
bool shouldLoop() const noexcept { return (loopMode == LoopMode::loop_continuous || loopMode == LoopMode::loop_sustain); } bool shouldLoop() const noexcept { return (loopMode == LoopMode::loop_continuous || loopMode == LoopMode::loop_sustain); }
/**
* @brief Get the base pitch of the region depending on which note has been
* pressed and at which velocity.
*
* @param noteNumber
* @param velocity
* @return float
*/
float getBasePitchVariation(float noteNumber, float velocity) const noexcept;
/** /**
* @brief Get the base gain of the region. * @brief Get the base gain of the region.
* *

View file

@ -125,10 +125,40 @@ float velocityCurve(const Region& region, float velocity, const MidiState& midiS
else else
gain = velocity * velocity; gain = velocity * velocity;
gain = std::fabs(region.ampVeltrack) * (1.0f - gain); float veltrack = region.ampVeltrack;
gain = (region.ampVeltrack < 0) ? gain : (1.0f - gain);
for (const auto& mod : region.ampVeltrackCC) {
const auto& curve = curveSet.getCurve(mod.data.curve);
const float value = midiState.getCCValue(mod.cc);
veltrack += curve.evalNormalized(value) * mod.data.modifier;
}
gain = std::fabs(veltrack) * (1.0f - gain);
gain = (veltrack < 0) ? gain : (1.0f - gain);
return gain; return gain;
} }
float basePitchVariation(const Region& region, float noteNumber, float velocity, const MidiState& midiState, const CurveSet& curveSet) noexcept
{
ASSERT(velocity >= 0.0f && velocity <= 1.0f);
fast_real_distribution<float> pitchDistribution { 0.0f, region.pitchRandom };
float pitchVariationInCents = region.pitchKeytrack * (noteNumber - float(region.pitchKeycenter)); // note difference with pitch center
pitchVariationInCents += region.pitch; // sample tuning
pitchVariationInCents += config::centPerSemitone * region.transpose; // sample transpose
float veltrack = region.pitchVeltrack;
for (const auto& mod : region.pitchVeltrackCC) {
const auto& curve = curveSet.getCurve(mod.data.curve);
const float value = midiState.getCCValue(mod.cc);
veltrack += curve.evalNormalized(value) * mod.data.modifier;
}
pitchVariationInCents += velocity * veltrack; // track velocity
pitchVariationInCents += pitchDistribution(Random::randomGenerator); // random pitch changes
return centsFactor(pitchVariationInCents);
}
} }

View file

@ -94,4 +94,17 @@ uint32_t loopStart(const Region& region, MidiState& midiState) noexcept;
*/ */
uint32_t loopEnd(const Region& region, MidiState& midiState) noexcept; uint32_t loopEnd(const Region& region, MidiState& midiState) noexcept;
/**
* @brief Get the base pitch of the region depending on which note has been
* pressed and at which velocity.
*
* @param region
* @param noteNumber
* @param velocity
* @param midiState
* @param curveSet
* @return float
*/
float basePitchVariation(const Region& region, float noteNumber, float velocity, const MidiState& midiState, const CurveSet& curveSet) noexcept;
} }

View file

@ -483,7 +483,7 @@ bool Voice::startVoice(Layer* layer, int delay, const TriggerEvent& event) noexc
Tuning& tuning = resources.getTuning(); Tuning& tuning = resources.getTuning();
const float numberRetuned = tuning.getKeyFractional12TET(impl.triggerEvent_.number); const float numberRetuned = tuning.getKeyFractional12TET(impl.triggerEvent_.number);
impl.pitchRatio_ = region.getBasePitchVariation(numberRetuned, impl.triggerEvent_.value); impl.pitchRatio_ = basePitchVariation(region, numberRetuned, impl.triggerEvent_.value, midiState, curveSet);
// apply stretch tuning if set // apply stretch tuning if set
if (absl::optional<StretchTuning>& stretch = resources.getStretch()) if (absl::optional<StretchTuning>& stretch = resources.getStretch())

View file

@ -360,14 +360,16 @@ TEST_CASE("[Region] Offsets with CCs")
TEST_CASE("[Region] Pitch variation with veltrack") TEST_CASE("[Region] Pitch variation with veltrack")
{ {
Region region { 0 }; Region region { 0 };
MidiState midiState;
CurveSet curveSet { CurveSet::createPredefined() };
REQUIRE(region.getBasePitchVariation(60.0, 0_norm) == 1.0); REQUIRE(basePitchVariation(region, 60.0, 0_norm, midiState, curveSet) == 1.0);
REQUIRE(region.getBasePitchVariation(60.0, 64_norm) == 1.0); REQUIRE(basePitchVariation(region, 60.0, 64_norm, midiState, curveSet) == 1.0);
REQUIRE(region.getBasePitchVariation(60.0, 127_norm) == 1.0); REQUIRE(basePitchVariation(region, 60.0, 127_norm, midiState, curveSet) == 1.0);
region.parseOpcode({ "pitch_veltrack", "1200" }); region.parseOpcode({ "pitch_veltrack", "1200" });
REQUIRE(region.getBasePitchVariation(60.0, 0_norm) == 1.0); REQUIRE(basePitchVariation(region, 60.0, 0_norm, midiState, curveSet) == 1.0);
REQUIRE(region.getBasePitchVariation(60.0, 64_norm) == Approx(centsFactor(600.0)).margin(0.01f)); REQUIRE(basePitchVariation(region, 60.0, 64_norm, midiState, curveSet) == Approx(centsFactor(600.0)).margin(0.01f));
REQUIRE(region.getBasePitchVariation(60.0, 127_norm) == Approx(centsFactor(1200.0)).margin(0.01f)); REQUIRE(basePitchVariation(region, 60.0, 127_norm, midiState, curveSet) == Approx(centsFactor(1200.0)).margin(0.01f));
} }
TEST_CASE("[Synth] velcurve") TEST_CASE("[Synth] velcurve")