Support multi-level volumes

This commit is contained in:
Jean Pierre Cimalando 2020-08-11 17:06:09 +02:00
parent 95bf4fc480
commit bf8b3fd111
3 changed files with 78 additions and 1 deletions

View file

@ -539,6 +539,27 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
case hash("rt_decay"):
setValueFromOpcode(opcode, rtDecay, Default::rtDecayRange);
break;
case hash("global_amplitude"):
if (auto value = readOpcode(opcode.value, Default::amplitudeRange))
globalAmplitude = normalizePercents(*value);
break;
case hash("master_amplitude"):
if (auto value = readOpcode(opcode.value, Default::amplitudeRange))
masterAmplitude = normalizePercents(*value);
break;
case hash("group_amplitude"):
if (auto value = readOpcode(opcode.value, Default::amplitudeRange))
groupAmplitude = normalizePercents(*value);
break;
case hash("global_volume"):
setValueFromOpcode(opcode, globalVolume, Default::volumeRange);
break;
case hash("master_volume"):
setValueFromOpcode(opcode, masterVolume, Default::volumeRange);
break;
case hash("group_volume"):
setValueFromOpcode(opcode, groupVolume, Default::volumeRange);
break;
// Performance parameters: filters
case hash("cutoff&"): // also cutoff
@ -1165,6 +1186,9 @@ float sfz::Region::getBaseVolumedB(int noteNumber) const noexcept
{
fast_real_distribution<float> volumeDistribution { -ampRandom, ampRandom };
auto baseVolumedB = volume + volumeDistribution(Random::randomGenerator);
baseVolumedB += globalVolume;
baseVolumedB += masterVolume;
baseVolumedB += groupVolume;
if (trigger == SfzTrigger::release || trigger == SfzTrigger::release_key)
baseVolumedB -= rtDecay * midiState.getNoteDuration(noteNumber);
return baseVolumedB;
@ -1172,7 +1196,13 @@ float sfz::Region::getBaseVolumedB(int noteNumber) const noexcept
float sfz::Region::getBaseGain() const noexcept
{
return amplitude;
float baseGain = amplitude;
baseGain *= globalAmplitude;
baseGain *= masterAmplitude;
baseGain *= groupAmplitude;
return baseGain;
}
float sfz::Region::getPhase() const noexcept

View file

@ -345,6 +345,13 @@ struct Region {
CCMap<Range<float>> crossfadeCCOutRange { Default::crossfadeCCOutRange }; // xfout_loccN xfout_hiccN
float rtDecay { Default::rtDecay }; // rt_decay
float globalAmplitude { 1.0 }; // global_amplitude
float masterAmplitude { 1.0 }; // master_amplitude
float groupAmplitude { 1.0 }; // group_amplitude
float globalVolume { 0.0 }; // global_volume
float masterVolume { 0.0 }; // master_volume
float groupVolume { 0.0 }; // group_volume
// Filters and EQs
std::vector<EQDescription> equalizers;
std::vector<FilterDescription> filters;

View file

@ -882,6 +882,46 @@ TEST_CASE("[Region] Parsing opcodes")
REQUIRE(region.crossfadeCCCurve == SfzCrossfadeCurve::gain);
}
SECTION("*_volume")
{
const std::pair<absl::string_view, float*> assoc_pairs[] = {
{"global_volume", &region.globalVolume},
{"master_volume", &region.masterVolume},
{"group_volume", &region.groupVolume},
};
for (auto a : assoc_pairs) {
REQUIRE(region.volume == 0.0f);
region.parseOpcode({ a.first, "4.2" });
REQUIRE(*a.second == 4.2f);
region.parseOpcode({ a.first, "-4.2" });
REQUIRE(*a.second == -4.2f);
region.parseOpcode({ a.first, "-123" });
REQUIRE(*a.second == -123.0f);
region.parseOpcode({ a.first, "-185" });
REQUIRE(*a.second == -144.0f);
region.parseOpcode({ a.first, "79" });
REQUIRE(*a.second == 48.0f);
}
}
SECTION("*_amplitude")
{
const std::pair<absl::string_view, float*> assoc_pairs[] = {
{"global_amplitude", &region.globalAmplitude},
{"master_amplitude", &region.masterAmplitude},
{"group_amplitude", &region.groupAmplitude},
};
for (auto a : assoc_pairs) {
REQUIRE(*a.second == 1.0_a);
region.parseOpcode({ a.first, "40" });
REQUIRE(*a.second == 0.4_a);
region.parseOpcode({ a.first, "-40" });
REQUIRE(*a.second == 0_a);
region.parseOpcode({ a.first, "140" });
REQUIRE(*a.second == 1.0_a);
}
}
SECTION("pitch_keycenter")
{
REQUIRE(region.pitchKeycenter == 60);