Use modifiers for panning/width
This commit is contained in:
parent
d59d29c72b
commit
97234177a1
5 changed files with 37 additions and 51 deletions
|
|
@ -54,9 +54,10 @@ namespace Default
|
|||
constexpr SfzLoopMode loopMode { SfzLoopMode::no_loop };
|
||||
constexpr Range<uint32_t> loopRange { 0, std::numeric_limits<uint32_t>::max() };
|
||||
|
||||
// Global ranges
|
||||
// common defaults
|
||||
constexpr Range<uint8_t> midi7Range { 0, 127 };
|
||||
constexpr Range<float> normalizedRange { 0.0f, 1.0f };
|
||||
constexpr float zeroModifier { 0.0f };
|
||||
|
||||
// Wavetable oscillator
|
||||
constexpr float oscillatorPhase { 0.0 };
|
||||
|
|
|
|||
|
|
@ -305,22 +305,34 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
|
|||
amplitudeCC[opcode.parameters.back()] = normalizePercents(*value);
|
||||
break;
|
||||
case hash("pan"):
|
||||
setValueFromOpcode(opcode, pan, Default::panRange);
|
||||
if (auto value = readOpcode(opcode.value, Default::panRange))
|
||||
pan = normalizePercents(*value);
|
||||
break;
|
||||
case hash("pan_oncc&"):
|
||||
setCCPairFromOpcode(opcode, panCC, Default::panCCRange);
|
||||
if (opcode.parameters.back() > config::numCCs)
|
||||
return false;
|
||||
if (auto value = readOpcode(opcode.value, Default::panCCRange))
|
||||
panCC[opcode.parameters.back()] = normalizePercents(*value);
|
||||
break;
|
||||
case hash("position"):
|
||||
setValueFromOpcode(opcode, position, Default::positionRange);
|
||||
if (auto value = readOpcode(opcode.value, Default::positionRange))
|
||||
position = normalizePercents(*value);
|
||||
break;
|
||||
case hash("position_oncc&"):
|
||||
setCCPairFromOpcode(opcode, positionCC, Default::positionCCRange);
|
||||
if (opcode.parameters.back() > config::numCCs)
|
||||
return false;
|
||||
if (auto value = readOpcode(opcode.value, Default::positionCCRange))
|
||||
positionCC[opcode.parameters.back()] = normalizePercents(*value);
|
||||
break;
|
||||
case hash("width"):
|
||||
setValueFromOpcode(opcode, width, Default::widthRange);
|
||||
if (auto value = readOpcode(opcode.value, Default::widthRange))
|
||||
width = normalizePercents(*value);
|
||||
break;
|
||||
case hash("width_oncc&"):
|
||||
setCCPairFromOpcode(opcode, widthCC, Default::widthCCRange);
|
||||
if (opcode.parameters.back() > config::numCCs)
|
||||
return false;
|
||||
if (auto value = readOpcode(opcode.value, Default::widthCCRange))
|
||||
widthCC[opcode.parameters.back()] = normalizePercents(*value);
|
||||
break;
|
||||
case hash("amp_keycenter"):
|
||||
setValueFromOpcode(opcode, ampKeycenter, Default::keyRange);
|
||||
|
|
|
|||
|
|
@ -277,10 +277,10 @@ struct Region {
|
|||
float width { Default::width }; // width
|
||||
float position { Default::position }; // position
|
||||
absl::optional<CCValuePair<float>> volumeCC; // volume_oncc
|
||||
CCMap<float> amplitudeCC { Default::amplitude }; // amplitude_oncc
|
||||
absl::optional<CCValuePair<float>> panCC; // pan_oncc
|
||||
absl::optional<CCValuePair<float>> widthCC; // width_oncc
|
||||
absl::optional<CCValuePair<float>> positionCC; // position_oncc
|
||||
CCMap<float> amplitudeCC { Default::zeroModifier }; // amplitude_oncc
|
||||
CCMap<float> panCC { Default::zeroModifier }; // pan_oncc
|
||||
CCMap<float> widthCC { Default::zeroModifier }; // width_oncc
|
||||
CCMap<float> positionCC { Default::zeroModifier }; // position_oncc
|
||||
uint8_t ampKeycenter { Default::ampKeycenter }; // amp_keycenter
|
||||
float ampKeytrack { Default::ampKeytrack }; // amp_keytrack
|
||||
float ampVeltrack { Default::ampVeltrack }; // amp_keytrack
|
||||
|
|
|
|||
|
|
@ -85,24 +85,6 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
|
|||
if (triggerType != TriggerType::CC)
|
||||
baseGain *= region->getNoteGain(number, value);
|
||||
|
||||
basePan = normalizePercents(region->pan);
|
||||
auto pan = basePan;
|
||||
if (region->panCC)
|
||||
pan += resources.midiState.getCCValue(region->panCC->cc) * normalizePercents(region->panCC->value);
|
||||
panEnvelope.reset(Default::symmetricNormalizedRange.clamp(pan));
|
||||
|
||||
basePosition = normalizePercents(region->position);
|
||||
auto position = basePosition;
|
||||
if (region->positionCC)
|
||||
position += resources.midiState.getCCValue(region->positionCC->cc) * normalizePercents(region->positionCC->value);
|
||||
positionEnvelope.reset(Default::symmetricNormalizedRange.clamp(position));
|
||||
|
||||
baseWidth = normalizePercents(region->width);
|
||||
auto width = baseWidth;
|
||||
if (region->widthCC)
|
||||
width += resources.midiState.getCCValue(region->widthCC->cc) * normalizePercents(region->widthCC->value);
|
||||
widthEnvelope.reset(Default::symmetricNormalizedRange.clamp(width));
|
||||
|
||||
pitchBendEnvelope.setFunction([region](float pitchValue){
|
||||
const auto normalizedBend = normalizeBend(pitchValue);
|
||||
const auto bendInCents = normalizedBend > 0.0f ? normalizedBend * static_cast<float>(region->bendUp) : -normalizedBend * static_cast<float>(region->bendDown);
|
||||
|
|
@ -199,21 +181,6 @@ void sfz::Voice::registerCC(int delay, int ccNumber, float ccValue) noexcept
|
|||
const float newVolumedB { baseVolumedB + ccValue * region->volumeCC->value };
|
||||
volumeEnvelope.registerEvent(delay, db2mag(Default::volumeRange.clamp(newVolumedB)));
|
||||
}
|
||||
|
||||
if (region->panCC && ccNumber == region->panCC->cc) {
|
||||
const float newPan { basePan + ccValue * normalizePercents(region->panCC->value) };
|
||||
panEnvelope.registerEvent(delay, Default::symmetricNormalizedRange.clamp(newPan));
|
||||
}
|
||||
|
||||
if (region->positionCC && ccNumber == region->positionCC->cc) {
|
||||
const float newPosition { basePosition + ccValue * normalizePercents(region->positionCC->value) };
|
||||
positionEnvelope.registerEvent(delay, Default::symmetricNormalizedRange.clamp(newPosition));
|
||||
}
|
||||
|
||||
if (region->widthCC && ccNumber == region->widthCC->cc) {
|
||||
const float newWidth { baseWidth + ccValue * normalizePercents(region->widthCC->value) };
|
||||
widthEnvelope.registerEvent(delay, Default::symmetricNormalizedRange.clamp(newWidth));
|
||||
}
|
||||
}
|
||||
|
||||
void sfz::Voice::registerPitchWheel(int delay, int pitch) noexcept
|
||||
|
|
@ -378,7 +345,9 @@ void sfz::Voice::processMono(AudioSpan<float> buffer) noexcept
|
|||
copy<float>(leftBuffer, rightBuffer);
|
||||
|
||||
// Apply panning
|
||||
panEnvelope.getBlock(modulationSpan);
|
||||
fill<float>(modulationSpan, 0.0f);
|
||||
getLinearEnvelope<float>(region->panCC, resources.midiState, modulationSpan, [](float modifier, float value) { return value * modifier; });
|
||||
add<float>(region->pan, modulationSpan);
|
||||
pan<float>(modulationSpan, leftBuffer, rightBuffer);
|
||||
}
|
||||
}
|
||||
|
|
@ -431,13 +400,20 @@ void sfz::Voice::processStereo(AudioSpan<float> buffer) noexcept
|
|||
ScopedTiming logger { panningDuration };
|
||||
|
||||
// Apply panning
|
||||
panEnvelope.getBlock(modulationSpan);
|
||||
fill<float>(modulationSpan, 0.0f);
|
||||
getLinearEnvelope<float>(region->panCC, resources.midiState, modulationSpan, [](float modifier, float value) { return value * modifier; });
|
||||
add<float>(region->pan, modulationSpan);
|
||||
pan<float>(modulationSpan, leftBuffer, rightBuffer);
|
||||
|
||||
// Apply the width/position process
|
||||
widthEnvelope.getBlock(modulationSpan);
|
||||
fill<float>(modulationSpan, 0.0f);
|
||||
getLinearEnvelope<float>(region->widthCC, resources.midiState, modulationSpan, [](float modifier, float value) { return value * modifier; });
|
||||
add<float>(region->width, modulationSpan);
|
||||
width<float>(modulationSpan, leftBuffer, rightBuffer);
|
||||
positionEnvelope.getBlock(modulationSpan);
|
||||
|
||||
fill<float>(modulationSpan, 0.0f);
|
||||
getLinearEnvelope<float>(region->positionCC, resources.midiState, modulationSpan, [](float modifier, float value) { return value * modifier; });
|
||||
add<float>(region->position, modulationSpan);
|
||||
pan<float>(modulationSpan, leftBuffer, rightBuffer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -268,9 +268,6 @@ private:
|
|||
float pitchRatio { 1.0 };
|
||||
float baseVolumedB{ 0.0 };
|
||||
float baseGain { 1.0 };
|
||||
float basePan { 0.0 };
|
||||
float basePosition { 0.0 };
|
||||
float baseWidth { 0.0 };
|
||||
float baseFrequency { 440.0 };
|
||||
float phase { 0.0f };
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue