Handle the volume cc modifiers like the rest
This commit is contained in:
parent
bc60b19c4b
commit
bd85a97db3
3 changed files with 19 additions and 29 deletions
|
|
@ -294,7 +294,10 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
|
||||||
case hash("gain_cc&"):
|
case hash("gain_cc&"):
|
||||||
case hash("gain_oncc&"): // fallthrough
|
case hash("gain_oncc&"): // fallthrough
|
||||||
case hash("volume_oncc&"):
|
case hash("volume_oncc&"):
|
||||||
setCCPairFromOpcode(opcode, volumeCC, Default::volumeCCRange);
|
if (opcode.parameters.back() > config::numCCs)
|
||||||
|
return false;
|
||||||
|
if (auto value = readOpcode(opcode.value, Default::volumeCCRange))
|
||||||
|
volumeCC[opcode.parameters.back()] = *value;
|
||||||
break;
|
break;
|
||||||
case hash("amplitude"):
|
case hash("amplitude"):
|
||||||
if (auto value = readOpcode(opcode.value, Default::amplitudeRange))
|
if (auto value = readOpcode(opcode.value, Default::amplitudeRange))
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ struct Region {
|
||||||
float pan { normalizePercents(Default::pan) }; // pan
|
float pan { normalizePercents(Default::pan) }; // pan
|
||||||
float width { normalizePercents(Default::width) }; // width
|
float width { normalizePercents(Default::width) }; // width
|
||||||
float position { normalizePercents(Default::position) }; // position
|
float position { normalizePercents(Default::position) }; // position
|
||||||
absl::optional<CCValuePair<float>> volumeCC; // volume_oncc
|
CCMap<float> volumeCC { Default::zeroModifier }; // volume_oncc
|
||||||
CCMap<float> amplitudeCC { Default::zeroModifier }; // amplitude_oncc
|
CCMap<float> amplitudeCC { Default::zeroModifier }; // amplitude_oncc
|
||||||
CCMap<float> panCC { Default::zeroModifier }; // pan_oncc
|
CCMap<float> panCC { Default::zeroModifier }; // pan_oncc
|
||||||
CCMap<float> widthCC { Default::zeroModifier }; // width_oncc
|
CCMap<float> widthCC { Default::zeroModifier }; // width_oncc
|
||||||
|
|
|
||||||
|
|
@ -74,23 +74,11 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
|
||||||
speedRatio = static_cast<float>(currentPromise->sampleRate / this->sampleRate);
|
speedRatio = static_cast<float>(currentPromise->sampleRate / this->sampleRate);
|
||||||
}
|
}
|
||||||
pitchRatio = region->getBasePitchVariation(number, value);
|
pitchRatio = region->getBasePitchVariation(number, value);
|
||||||
|
|
||||||
baseVolumedB = region->getBaseVolumedB(number);
|
baseVolumedB = region->getBaseVolumedB(number);
|
||||||
auto volumedB = baseVolumedB;
|
|
||||||
if (region->volumeCC)
|
|
||||||
volumedB += resources.midiState.getCCValue(region->volumeCC->cc) * region->volumeCC->value;
|
|
||||||
volumeEnvelope.reset(db2mag(Default::volumeRange.clamp(volumedB)));
|
|
||||||
|
|
||||||
baseGain = region->getBaseGain();
|
baseGain = region->getBaseGain();
|
||||||
if (triggerType != TriggerType::CC)
|
if (triggerType != TriggerType::CC)
|
||||||
baseGain *= region->getNoteGain(number, value);
|
baseGain *= region->getNoteGain(number, value);
|
||||||
|
|
||||||
pitchBendEnvelope.setFunction([region](float bend){
|
|
||||||
const auto bendInCents = bend > 0.0f ? bend * static_cast<float>(region->bendUp) : -bend * static_cast<float>(region->bendDown);
|
|
||||||
return centsFactor(bendInCents);
|
|
||||||
});
|
|
||||||
pitchBendEnvelope.reset(resources.midiState.getPitchBend());
|
|
||||||
|
|
||||||
// Check that we can handle the number of filters; filters should be cleared here
|
// Check that we can handle the number of filters; filters should be cleared here
|
||||||
ASSERT((filters.capacity() - filters.size()) >= region->filters.size());
|
ASSERT((filters.capacity() - filters.size()) >= region->filters.size());
|
||||||
ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size());
|
ASSERT((equalizers.capacity() - equalizers.size()) >= region->equalizers.size());
|
||||||
|
|
@ -171,23 +159,14 @@ void sfz::Voice::registerCC(int delay, int ccNumber, float ccValue) noexcept
|
||||||
|
|
||||||
if (region->checkSustain && noteIsOff && ccNumber == config::sustainCC && ccValue < config::halfCCThreshold)
|
if (region->checkSustain && noteIsOff && ccNumber == config::sustainCC && ccValue < config::halfCCThreshold)
|
||||||
release(delay);
|
release(delay);
|
||||||
|
|
||||||
// Add a minimum delay for smoothing the envelopes
|
|
||||||
// TODO: this feels like a hack, revisit this along with the smoothed envelopes...
|
|
||||||
delay = max(delay, minEnvelopeDelay);
|
|
||||||
|
|
||||||
if (region->volumeCC && ccNumber == region->volumeCC->cc) {
|
|
||||||
const float newVolumedB { baseVolumedB + ccValue * region->volumeCC->value };
|
|
||||||
volumeEnvelope.registerEvent(delay, db2mag(Default::volumeRange.clamp(newVolumedB)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Voice::registerPitchWheel(int delay, float pitch) noexcept
|
void sfz::Voice::registerPitchWheel(int delay, float pitch) noexcept
|
||||||
{
|
{
|
||||||
if (state == State::idle)
|
if (state == State::idle)
|
||||||
return;
|
return;
|
||||||
|
UNUSED(delay);
|
||||||
pitchBendEnvelope.registerEvent(delay, pitch);
|
UNUSED(pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sfz::Voice::registerAftertouch(int delay, uint8_t aftertouch) noexcept
|
void sfz::Voice::registerAftertouch(int delay, uint8_t aftertouch) noexcept
|
||||||
|
|
@ -293,7 +272,12 @@ void sfz::Voice::ampStageMono(AudioSpan<float> buffer) noexcept
|
||||||
applyGain<float>(*modulationSpan, leftBuffer);
|
applyGain<float>(*modulationSpan, leftBuffer);
|
||||||
|
|
||||||
// Volume envelope
|
// Volume envelope
|
||||||
volumeEnvelope.getBlock(*modulationSpan);
|
fill<float>(*modulationSpan, db2mag(baseVolumedB));
|
||||||
|
for (auto& mod : region->volumeCC) {
|
||||||
|
const auto events = resources.midiState.getCCEvents(mod.cc);
|
||||||
|
multiplicativeEnvelope(events, *tempSpan, [&](float x) { return db2mag(x * mod.value); });
|
||||||
|
applyGain<float>(*tempSpan, *modulationSpan);
|
||||||
|
}
|
||||||
applyGain<float>(*modulationSpan, leftBuffer);
|
applyGain<float>(*modulationSpan, leftBuffer);
|
||||||
|
|
||||||
// AmpEG envelope
|
// AmpEG envelope
|
||||||
|
|
@ -330,17 +314,20 @@ void sfz::Voice::ampStageStereo(AudioSpan<float> buffer) noexcept
|
||||||
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.value, x, xfCurve); });
|
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeIn(mod.value, x, xfCurve); });
|
||||||
applyGain<float>(*tempSpan, *modulationSpan);
|
applyGain<float>(*tempSpan, *modulationSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& mod : region->crossfadeCCOutRange) {
|
for (auto& mod : region->crossfadeCCOutRange) {
|
||||||
const auto events = resources.midiState.getCCEvents(mod.cc);
|
const auto events = resources.midiState.getCCEvents(mod.cc);
|
||||||
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.value, x, xfCurve); });
|
linearEnvelope(events, *tempSpan, [&](float x) { return crossfadeOut(mod.value, x, xfCurve); });
|
||||||
applyGain<float>(*tempSpan, *modulationSpan);
|
applyGain<float>(*tempSpan, *modulationSpan);
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.applyGain(*modulationSpan);
|
buffer.applyGain(*modulationSpan);
|
||||||
|
|
||||||
// Volume envelope
|
// Volume envelope
|
||||||
volumeEnvelope.getBlock(*modulationSpan);
|
fill<float>(*modulationSpan, db2mag(baseVolumedB));
|
||||||
|
for (auto& mod : region->volumeCC) {
|
||||||
|
const auto events = resources.midiState.getCCEvents(mod.cc);
|
||||||
|
multiplicativeEnvelope(events, *tempSpan, [&](float x) { return db2mag(x * mod.value); });
|
||||||
|
applyGain<float>(*tempSpan, *modulationSpan);
|
||||||
|
}
|
||||||
buffer.applyGain(*modulationSpan);
|
buffer.applyGain(*modulationSpan);
|
||||||
|
|
||||||
// AmpEG envelope
|
// AmpEG envelope
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue