If an opcode is rejected by a region as unknown it is ignored thereafter
This commit is contained in:
parent
5a33c850a3
commit
2964850f80
4 changed files with 98 additions and 14 deletions
|
|
@ -85,8 +85,11 @@ namespace Default
|
||||||
inline constexpr Range<uint8_t> crossfadeKeyOutRange { 127, 127 };
|
inline constexpr Range<uint8_t> crossfadeKeyOutRange { 127, 127 };
|
||||||
inline constexpr Range<uint8_t> crossfadeVelInRange { 0, 0 };
|
inline constexpr Range<uint8_t> crossfadeVelInRange { 0, 0 };
|
||||||
inline constexpr Range<uint8_t> crossfadeVelOutRange { 127, 127 };
|
inline constexpr Range<uint8_t> crossfadeVelOutRange { 127, 127 };
|
||||||
|
inline constexpr Range<uint8_t> crossfadeCCInRange { 0, 0 };
|
||||||
|
inline constexpr Range<uint8_t> crossfadeCCOutRange { 127, 127 };
|
||||||
inline constexpr SfzCrossfadeCurve crossfadeKeyCurve { SfzCrossfadeCurve::power };
|
inline constexpr SfzCrossfadeCurve crossfadeKeyCurve { SfzCrossfadeCurve::power };
|
||||||
inline constexpr SfzCrossfadeCurve crossfadeVelCurve { SfzCrossfadeCurve::power };
|
inline constexpr SfzCrossfadeCurve crossfadeVelCurve { SfzCrossfadeCurve::power };
|
||||||
|
inline constexpr SfzCrossfadeCurve crossfadeCCCurve { SfzCrossfadeCurve::power };
|
||||||
|
|
||||||
// Performance parameters: pitch
|
// Performance parameters: pitch
|
||||||
inline constexpr uint8_t pitchKeycenter { 60 };
|
inline constexpr uint8_t pitchKeycenter { 60 };
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,12 @@
|
||||||
|
|
||||||
bool sfz::Region::parseOpcode(const Opcode& opcode)
|
bool sfz::Region::parseOpcode(const Opcode& opcode)
|
||||||
{
|
{
|
||||||
|
// Check that the parameter is well formed
|
||||||
|
if (opcode.parameter && !sfz::Default::ccRange.containsWithEnd(*opcode.parameter)) {
|
||||||
|
DBG("Wrong parameter value (" << std::to_string(*opcode.parameter) << ") for opcode " << opcode.opcode);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
switch (hash(opcode.opcode)) {
|
switch (hash(opcode.opcode)) {
|
||||||
// Sound source: sample playback
|
// Sound source: sample playback
|
||||||
case hash("sample"):
|
case hash("sample"):
|
||||||
|
|
@ -309,6 +315,38 @@ bool sfz::Region::parseOpcode(const Opcode& opcode)
|
||||||
DBG("Unknown crossfade power curve: " << std::string(opcode.value));
|
DBG("Unknown crossfade power curve: " << std::string(opcode.value));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case hash("xfin_locc"):
|
||||||
|
if (opcode.parameter) {
|
||||||
|
setRangeStartFromOpcode(opcode, crossfadeCCInRange[*opcode.parameter], Default::ccRange);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hash("xfin_hicc"):
|
||||||
|
if (opcode.parameter) {
|
||||||
|
setRangeEndFromOpcode(opcode, crossfadeCCInRange[*opcode.parameter], Default::velocityRange);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hash("xfout_locc"):
|
||||||
|
if (opcode.parameter) {
|
||||||
|
setRangeStartFromOpcode(opcode, crossfadeCCOutRange[*opcode.parameter], Default::velocityRange);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hash("xfout_hicc"):
|
||||||
|
if (opcode.parameter) {
|
||||||
|
setRangeEndFromOpcode(opcode, crossfadeCCOutRange[*opcode.parameter], Default::velocityRange);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case hash("xf_cccurve"):
|
||||||
|
switch (hash(opcode.value)) {
|
||||||
|
case hash("power"):
|
||||||
|
crossfadeCCCurve = SfzCrossfadeCurve::power;
|
||||||
|
break;
|
||||||
|
case hash("gain"):
|
||||||
|
crossfadeCCCurve = SfzCrossfadeCurve::gain;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBG("Unknown crossfade power curve: " << std::string(opcode.value));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// Performance parameters: pitch
|
// Performance parameters: pitch
|
||||||
case hash("pitch_keycenter"):
|
case hash("pitch_keycenter"):
|
||||||
|
|
@ -593,6 +631,7 @@ bool sfz::Region::isStereo() const noexcept
|
||||||
return this->numChannels == 2;
|
return this->numChannels == 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: lots and lots of repetition here...
|
||||||
float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
||||||
{
|
{
|
||||||
float baseGain { 1.0f };
|
float baseGain { 1.0f };
|
||||||
|
|
@ -605,7 +644,7 @@ float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
||||||
if (noteNumber < crossfadeKeyInRange.getStart())
|
if (noteNumber < crossfadeKeyInRange.getStart())
|
||||||
baseGain = 0.0f;
|
baseGain = 0.0f;
|
||||||
else if (noteNumber < crossfadeKeyInRange.getEnd()) {
|
else if (noteNumber < crossfadeKeyInRange.getEnd()) {
|
||||||
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeKeyInRange.getStart()) / crossfadeKeyInRange.length();
|
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeKeyInRange.getStart()) / (crossfadeKeyInRange.length() > 0 ? crossfadeKeyInRange.length() : 1);
|
||||||
if (crossfadeKeyCurve == SfzCrossfadeCurve::power)
|
if (crossfadeKeyCurve == SfzCrossfadeCurve::power)
|
||||||
baseGain *= sqrt(crossfadePosition);
|
baseGain *= sqrt(crossfadePosition);
|
||||||
if (crossfadeKeyCurve == SfzCrossfadeCurve::gain)
|
if (crossfadeKeyCurve == SfzCrossfadeCurve::gain)
|
||||||
|
|
@ -615,7 +654,7 @@ float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
||||||
if (noteNumber > crossfadeKeyOutRange.getEnd())
|
if (noteNumber > crossfadeKeyOutRange.getEnd())
|
||||||
baseGain = 0.0f;
|
baseGain = 0.0f;
|
||||||
else if (noteNumber > crossfadeKeyOutRange.getStart()) {
|
else if (noteNumber > crossfadeKeyOutRange.getStart()) {
|
||||||
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeKeyOutRange.getStart()) / crossfadeKeyOutRange.length();
|
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeKeyOutRange.getStart()) / (crossfadeKeyOutRange.length() > 0 ? crossfadeKeyOutRange.length() : 1);
|
||||||
if (crossfadeKeyCurve == SfzCrossfadeCurve::power)
|
if (crossfadeKeyCurve == SfzCrossfadeCurve::power)
|
||||||
baseGain *= sqrt(1 - crossfadePosition);
|
baseGain *= sqrt(1 - crossfadePosition);
|
||||||
if (crossfadeKeyCurve == SfzCrossfadeCurve::gain)
|
if (crossfadeKeyCurve == SfzCrossfadeCurve::gain)
|
||||||
|
|
@ -625,7 +664,7 @@ float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
||||||
if (velocity < crossfadeVelInRange.getStart())
|
if (velocity < crossfadeVelInRange.getStart())
|
||||||
baseGain = 0;
|
baseGain = 0;
|
||||||
else if (velocity < crossfadeVelInRange.getEnd()) {
|
else if (velocity < crossfadeVelInRange.getEnd()) {
|
||||||
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeVelInRange.getStart()) / crossfadeVelInRange.length();
|
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeVelInRange.getStart()) / (crossfadeVelInRange.length() > 0 ? crossfadeVelInRange.length() : 1);
|
||||||
if (crossfadeVelCurve == SfzCrossfadeCurve::power)
|
if (crossfadeVelCurve == SfzCrossfadeCurve::power)
|
||||||
baseGain *= sqrt(crossfadePosition);
|
baseGain *= sqrt(crossfadePosition);
|
||||||
if (crossfadeVelCurve == SfzCrossfadeCurve::gain)
|
if (crossfadeVelCurve == SfzCrossfadeCurve::gain)
|
||||||
|
|
@ -635,7 +674,7 @@ float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
||||||
if (velocity > crossfadeVelOutRange.getEnd())
|
if (velocity > crossfadeVelOutRange.getEnd())
|
||||||
baseGain = 0;
|
baseGain = 0;
|
||||||
else if (velocity > crossfadeVelOutRange.getStart()) {
|
else if (velocity > crossfadeVelOutRange.getStart()) {
|
||||||
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeVelOutRange.getStart()) / crossfadeVelOutRange.length();
|
const auto crossfadePosition = static_cast<float>(noteNumber - crossfadeVelOutRange.getStart()) / (crossfadeVelOutRange.length() > 0 ? crossfadeVelOutRange.length() : 1);
|
||||||
if (crossfadeVelCurve == SfzCrossfadeCurve::power)
|
if (crossfadeVelCurve == SfzCrossfadeCurve::power)
|
||||||
baseGain *= sqrt(1 - crossfadePosition);
|
baseGain *= sqrt(1 - crossfadePosition);
|
||||||
if (crossfadeVelCurve == SfzCrossfadeCurve::gain)
|
if (crossfadeVelCurve == SfzCrossfadeCurve::gain)
|
||||||
|
|
@ -645,25 +684,57 @@ float sfz::Region::getNoteGain(int noteNumber, uint8_t velocity) noexcept
|
||||||
return baseGain;
|
return baseGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float sfz::Region::getCCGain(const sfz::CCValueArray& ccState) noexcept
|
||||||
|
{
|
||||||
|
float gain { 1.0f };
|
||||||
|
|
||||||
|
for (const auto& valuePair : crossfadeCCInRange) {
|
||||||
|
const auto ccValue = ccState[valuePair.first];
|
||||||
|
const auto crossfadeRange = valuePair.second;
|
||||||
|
if (ccValue < crossfadeRange.getStart()) {
|
||||||
|
gain = 0.0f;
|
||||||
|
} else if (ccValue < crossfadeRange.getEnd()) {
|
||||||
|
const auto crossfadePosition = static_cast<float>(ccValue - crossfadeRange.getStart()) / (crossfadeRange.length() > 0 ? crossfadeRange.length() : 1);
|
||||||
|
if (crossfadeCCCurve == SfzCrossfadeCurve::power)
|
||||||
|
gain *= sqrt(crossfadePosition);
|
||||||
|
if (crossfadeVelCurve == SfzCrossfadeCurve::gain)
|
||||||
|
gain *= crossfadePosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& valuePair : crossfadeCCOutRange) {
|
||||||
|
const auto ccValue = ccState[valuePair.first];
|
||||||
|
const auto crossfadeRange = valuePair.second;
|
||||||
|
if (ccValue > crossfadeRange.getEnd()) {
|
||||||
|
gain = 0.0f;
|
||||||
|
} else if (ccValue > crossfadeRange.getStart()) {
|
||||||
|
const auto crossfadePosition = static_cast<float>(ccValue - crossfadeRange.getStart()) / (crossfadeRange.length() > 0 ? crossfadeRange.length() : 1);
|
||||||
|
if (crossfadeCCCurve == SfzCrossfadeCurve::power)
|
||||||
|
gain *= sqrt(1 - crossfadePosition);
|
||||||
|
if (crossfadeVelCurve == SfzCrossfadeCurve::gain)
|
||||||
|
gain *= 1 - crossfadePosition;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return gain;
|
||||||
|
}
|
||||||
|
|
||||||
float sfz::Region::velocityGain(uint8_t velocity) const noexcept
|
float sfz::Region::velocityGain(uint8_t velocity) const noexcept
|
||||||
{
|
{
|
||||||
float gaindB { 0.0 };
|
float gaindB { 0.0 };
|
||||||
if (velocityPoints.size() > 0)
|
if (velocityPoints.size() > 0) {
|
||||||
{
|
|
||||||
auto after = std::find_if(velocityPoints.begin(), velocityPoints.end(), [velocity](auto& val) { return val.first >= velocity; });
|
auto after = std::find_if(velocityPoints.begin(), velocityPoints.end(), [velocity](auto& val) { return val.first >= velocity; });
|
||||||
auto before = after == velocityPoints.begin() ? velocityPoints.begin() : after - 1;
|
auto before = after == velocityPoints.begin() ? velocityPoints.begin() : after - 1;
|
||||||
// Linear interpolation
|
// Linear interpolation
|
||||||
float relativePositionInSegment { static_cast<float>(velocity - before->first) / (after->first - before->first) };
|
float relativePositionInSegment { static_cast<float>(velocity - before->first) / (after->first - before->first) };
|
||||||
float segmentEndpoints { after->second - before->second };
|
float segmentEndpoints { after->second - before->second };
|
||||||
gaindB = db2pow(relativePositionInSegment * segmentEndpoints);
|
gaindB = db2pow(relativePositionInSegment * segmentEndpoints);
|
||||||
}
|
} else {
|
||||||
else
|
float floatVelocity { static_cast<float>(velocity) / 127 };
|
||||||
{
|
|
||||||
float floatVelocity { static_cast<float>(velocity)/127 };
|
|
||||||
if (ampVeltrack > 0)
|
if (ampVeltrack > 0)
|
||||||
gaindB = 40 * std::log(floatVelocity) / std::log(10.0f);
|
gaindB = 40 * std::log(floatVelocity) / std::log(10.0f);
|
||||||
else
|
else
|
||||||
gaindB = 40 * std::log(1-floatVelocity) / std::log(10.0f);
|
gaindB = 40 * std::log(1 - floatVelocity) / std::log(10.0f);
|
||||||
}
|
}
|
||||||
gaindB *= std::abs(ampVeltrack) / sfz::Default::ampVeltrackRange.getEnd();
|
gaindB *= std::abs(ampVeltrack) / sfz::Default::ampVeltrackRange.getEnd();
|
||||||
return db2pow(gaindB);
|
return db2pow(gaindB);
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ struct Region {
|
||||||
bool isStereo() const noexcept;
|
bool isStereo() const noexcept;
|
||||||
float getBasePitchVariation(int noteNumber, uint8_t velocity) noexcept;
|
float getBasePitchVariation(int noteNumber, uint8_t velocity) noexcept;
|
||||||
float getNoteGain(int noteNumber, uint8_t velocity) noexcept;
|
float getNoteGain(int noteNumber, uint8_t velocity) noexcept;
|
||||||
|
float getCCGain(const CCValueArray& ccState) noexcept;
|
||||||
float getBaseGain() noexcept;
|
float getBaseGain() noexcept;
|
||||||
float velocityGain(uint8_t velocity) const noexcept;
|
float velocityGain(uint8_t velocity) const noexcept;
|
||||||
uint32_t getOffset() noexcept;
|
uint32_t getOffset() noexcept;
|
||||||
|
|
@ -105,6 +106,9 @@ struct Region {
|
||||||
Range<uint8_t> crossfadeVelOutRange { Default::crossfadeVelOutRange };
|
Range<uint8_t> crossfadeVelOutRange { Default::crossfadeVelOutRange };
|
||||||
SfzCrossfadeCurve crossfadeKeyCurve { Default::crossfadeKeyCurve };
|
SfzCrossfadeCurve crossfadeKeyCurve { Default::crossfadeKeyCurve };
|
||||||
SfzCrossfadeCurve crossfadeVelCurve { Default::crossfadeVelCurve };
|
SfzCrossfadeCurve crossfadeVelCurve { Default::crossfadeVelCurve };
|
||||||
|
SfzCrossfadeCurve crossfadeCCCurve { Default::crossfadeCCCurve };
|
||||||
|
CCMap<Range<uint8_t>> crossfadeCCInRange { Default::crossfadeCCInRange }; // xfin_loccN xfin_hiccN
|
||||||
|
CCMap<Range<uint8_t>> crossfadeCCOutRange { Default::crossfadeCCOutRange }; // xfout_loccN xfout_hiccN
|
||||||
|
|
||||||
// Performance parameters: pitch
|
// Performance parameters: pitch
|
||||||
uint8_t pitchKeycenter { Default::pitchKeycenter }; // pitch_keycenter
|
uint8_t pitchKeycenter { Default::pitchKeycenter }; // pitch_keycenter
|
||||||
|
|
|
||||||
|
|
@ -54,9 +54,15 @@ void sfz::Synth::buildRegion(const std::vector<Opcode>& regionOpcodes)
|
||||||
auto lastRegion = std::make_unique<Region>();
|
auto lastRegion = std::make_unique<Region>();
|
||||||
|
|
||||||
auto parseOpcodes = [&](const auto& opcodes) {
|
auto parseOpcodes = [&](const auto& opcodes) {
|
||||||
for (auto& opcode : opcodes)
|
for (auto& opcode : opcodes) {
|
||||||
|
const auto unknown = absl::c_find_if(unknownOpcodes, [&](std::string_view sv) { return sv.compare(opcode.opcode) == 0; });
|
||||||
|
if (unknown != unknownOpcodes.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!lastRegion->parseOpcode(opcode))
|
if (!lastRegion->parseOpcode(opcode))
|
||||||
unknownOpcodes.insert(opcode.opcode);
|
unknownOpcodes.insert(opcode.opcode);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parseOpcodes(globalOpcodes);
|
parseOpcodes(globalOpcodes);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue