multiplicativeEnvelope free function for pitch

This commit is contained in:
Paul Ferrand 2020-03-30 21:51:21 +02:00
parent 9e3f496f9e
commit 088da9df65
4 changed files with 44 additions and 23 deletions

View file

@ -157,10 +157,15 @@ void sfz::MidiState::resetAllControllers(int delay) noexcept
pitchBendEvent(delay, 0.0f);
}
const sfz::EventVector& sfz::MidiState::getEvents(int ccIdx) const noexcept
const sfz::EventVector& sfz::MidiState::getCCEvents(int ccIdx) const noexcept
{
if (ccIdx < 0 || ccIdx > config::numCCs)
return nullEvent;
return cc[ccIdx];
}
const sfz::EventVector& sfz::MidiState::getPitchEvents() const noexcept
{
return pitchEvents;
}

View file

@ -121,7 +121,8 @@ public:
*/
void resetAllControllers(int delay) noexcept;
const EventVector& getEvents(int ccIdx) const noexcept;
const EventVector& getCCEvents(int ccIdx) const noexcept;
const EventVector& getPitchEvents() const noexcept;
private:

View file

@ -373,7 +373,7 @@ void multiplicativeEnvelope(const EventVector& events, absl::Span<float> envelop
const auto event = events[i];
const auto length = event.delay - lastDelay;
const auto nextValue = lambda(event.value);
const auto step = std::exp((std::log(nextValue) - std::log(currentValue)) / length);
const auto step = std::exp((std::log(nextValue) - std::log(lastValue)) / length);
multiplicativeRamp<float>(envelope.subspan(lastDelay, length), lastValue, step);
lastValue = nextValue;
lastDelay += length;

View file

@ -187,7 +187,7 @@ void sfz::Voice::registerPitchWheel(int delay, float pitch) noexcept
if (state == State::idle)
return;
pitchBendEnvelope.registerEvent(delay, pitch * 8191.0f);
pitchBendEnvelope.registerEvent(delay, pitch);
}
void sfz::Voice::registerAftertouch(int delay, uint8_t aftertouch) noexcept
@ -272,7 +272,7 @@ void sfz::Voice::ampStageMono(AudioSpan<float> buffer) noexcept
// Amplitude envelope
fill<float>(*modulationSpan, baseGain);
for (auto& mod : region->amplitudeCC) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
applyGain<float>(*tempSpan, *modulationSpan);
}
@ -281,12 +281,12 @@ void sfz::Voice::ampStageMono(AudioSpan<float> buffer) noexcept
// Crossfade envelopes
fill<float>(*modulationSpan, 1.0f);
for (auto& mod : region->crossfadeCCInRange) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.value, x, xfCurve); });
applyGain<float>(*tempSpan, *modulationSpan);
}
for (auto& mod : region->crossfadeCCOutRange) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.value, x, xfCurve); });
applyGain<float>(*tempSpan, *modulationSpan);
}
@ -317,25 +317,26 @@ void sfz::Voice::ampStageStereo(AudioSpan<float> buffer) noexcept
// Amplitude envelope
fill<float>(*modulationSpan, baseGain);
for (auto& mod : region->amplitudeCC) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
applyGain<float>(*tempSpan, *modulationSpan);
}
buffer.applyGain(*modulationSpan);
// Crossfade envelopes
fill<float>(*modulationSpan, 1.0f);
for (auto& mod : region->crossfadeCCInRange) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.value, x, xfCurve); });
applyGain<float>(*tempSpan, *modulationSpan);
}
for (auto& mod : region->crossfadeCCOutRange) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.value, x, xfCurve); });
applyGain<float>(*tempSpan, *modulationSpan);
}
buffer.applyGain(*modulationSpan);
// Volume envelope
@ -366,7 +367,7 @@ void sfz::Voice::panStageMono(AudioSpan<float> buffer) noexcept
// Apply panning
fill<float>(*modulationSpan, region->pan);
for (auto& mod : region->panCC) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
@ -389,7 +390,7 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
// panningModulation(*modulationSpan);
fill<float>(*modulationSpan, region->pan);
for (auto& mod : region->panCC) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
@ -399,7 +400,7 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
// widthModulation(*modulationSpan);
fill<float>(*modulationSpan, region->width);
for (auto& mod : region->widthCC) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
@ -408,7 +409,7 @@ void sfz::Voice::panStageStereo(AudioSpan<float> buffer) noexcept
// positionModulation(*modulationSpan);
fill<float>(*modulationSpan, region->position);
for (auto& mod : region->positionCC) {
const auto events = resources.midiState.getEvents(mod.cc);
const auto events = resources.midiState.getCCEvents(mod.cc);
linearEnvelope(events, *tempSpan, [&mod](float x) { return x * mod.value; });
add<float>(*tempSpan, *modulationSpan);
}
@ -472,10 +473,17 @@ void sfz::Voice::fillWithData(AudioSpan<float> buffer) noexcept
return;
fill<float>(*jumps, pitchRatio * speedRatio);
if (region->bendStep > 1)
pitchBendEnvelope.getQuantizedBlock(*bends, bendStepFactor);
else
pitchBendEnvelope.getBlock(*bends);
// if (region->bendStep > 1)
// pitchBendEnvelope.getQuantizedBlock(*bends, bendStepFactor);
// else
// pitchBendEnvelope.getBlock(*bends);
const auto events = resources.midiState.getPitchEvents();
const auto bendLambda = [this](float bend){
const auto bendInCents = bend > 0.0f ? bend * static_cast<float>(region->bendUp) : -bend * static_cast<float>(region->bendDown);
return centsFactor(bendInCents);
};
multiplicativeEnvelope(events, *bends, bendLambda);
DBG("Bend: " << bends->back());
applyGain<float>(*bends, *jumps);
jumps->front() += floatPositionOffset;
@ -558,11 +566,18 @@ void sfz::Voice::fillWithGenerator(AudioSpan<float> buffer) noexcept
float keycenterFrequency = midiNoteFrequency(region->pitchKeycenter);
fill<float>(*frequencies, pitchRatio * keycenterFrequency);
if (region->bendStep > 1)
pitchBendEnvelope.getQuantizedBlock(*bends, bendStepFactor);
else
pitchBendEnvelope.getBlock(*bends);
const auto events = resources.midiState.getPitchEvents();
const auto bendLambda = [this](float bend){
const auto bendInCents = bend > 0.0f ? bend * static_cast<float>(region->bendUp) : -bend * static_cast<float>(region->bendDown);
return centsFactor(bendInCents);
};
// if (region->bendStep > 1)
// pitchBendEnvelope.getQuantizedBlock(*bends, bendStepFactor);
// else
// pitchBendEnvelope.getBlock(*bends);
multiplicativeEnvelope(events, *bends, bendLambda);
DBG("Bend: " << bends->back());
applyGain<float>(*bends, *frequencies);
waveOscillator.processModulated(frequencies->data(), leftSpan.data(), buffer.getNumFrames());