This commit is contained in:
Paul Fd 2021-02-03 10:43:05 +01:00 committed by Paul Ferrand
parent 293e7a935f
commit 9a1e3971a9
10 changed files with 113 additions and 81 deletions

View file

@ -137,7 +137,6 @@ set(SFIZZ_SOURCES
sfizz/Wavetables.cpp sfizz/Wavetables.cpp
sfizz/Tuning.cpp sfizz/Tuning.cpp
sfizz/RegionSet.cpp sfizz/RegionSet.cpp
sfizz/Defaults.cpp
sfizz/PolyphonyGroup.cpp sfizz/PolyphonyGroup.cpp
sfizz/VoiceManager.cpp sfizz/VoiceManager.cpp
sfizz/VoiceStealing.cpp sfizz/VoiceStealing.cpp
@ -201,6 +200,7 @@ set(SFIZZ_PARSER_HEADERS
set(SFIZZ_PARSER_SOURCES set(SFIZZ_PARSER_SOURCES
sfizz/Opcode.cpp sfizz/Opcode.cpp
sfizz/Defaults.cpp
sfizz/OpcodeCleanup.cpp sfizz/OpcodeCleanup.cpp
sfizz/parser/Parser.cpp sfizz/parser/Parser.cpp
sfizz/parser/ParserPrivate.cpp) sfizz/parser/ParserPrivate.cpp)

View file

@ -1,6 +1,4 @@
#include "Defaults.h" #include "Defaults.h"
#include "MathHelpers.h"
#include "SfzHelpers.h"
namespace sfz { namespace sfz {
@ -23,7 +21,7 @@ extern const OpcodeSpec<int> oscillatorMode { 0, Range<int>(0, 2), 0 };
extern const OpcodeSpec<int> oscillatorMulti { 1, Range<int>(1, config::oscillatorsPerVoice), 0 }; extern const OpcodeSpec<int> oscillatorMulti { 1, Range<int>(1, config::oscillatorsPerVoice), 0 };
extern const OpcodeSpec<float> oscillatorDetune { 0.0f, Range<float>(-12000.0f, 12000.0f), 0 }; extern const OpcodeSpec<float> oscillatorDetune { 0.0f, Range<float>(-12000.0f, 12000.0f), 0 };
extern const OpcodeSpec<float> oscillatorDetuneMod { 0.0f, Range<float>(-12000.0f, 12000.0f), 0 }; extern const OpcodeSpec<float> oscillatorDetuneMod { 0.0f, Range<float>(-12000.0f, 12000.0f), 0 };
extern const OpcodeSpec<float> oscillatorModDepth { 0.0f, Range<float>(0.0f, 10000.0f), kNormalizePercent }; extern const OpcodeSpec<float> oscillatorModDepth { 0.0f, Range<float>(0.0f, 10000.0f), 0 };
extern const OpcodeSpec<float> oscillatorModDepthMod { 0.0f, Range<float>(0.0f, 10000.0f), 0 }; extern const OpcodeSpec<float> oscillatorModDepthMod { 0.0f, Range<float>(0.0f, 10000.0f), 0 };
extern const OpcodeSpec<int> oscillatorQuality { 1, Range<int>(0, 3), 0 }; extern const OpcodeSpec<int> oscillatorQuality { 1, Range<int>(0, 3), 0 };
extern const OpcodeSpec<uint32_t> group { 0, Range<uint32_t>(0, uint32_t_max), 0 }; extern const OpcodeSpec<uint32_t> group { 0, Range<uint32_t>(0, uint32_t_max), 0 };
@ -33,14 +31,14 @@ extern const OpcodeSpec<uint32_t> notePolyphony { config::maxVoices, Range<uint3
extern const OpcodeSpec<uint8_t> key { 60, Range<uint8_t>(0, 127), kCanBeNote }; extern const OpcodeSpec<uint8_t> key { 60, Range<uint8_t>(0, 127), kCanBeNote };
extern const OpcodeSpec<uint8_t> loKey { 0, Range<uint8_t>(0, 127), kCanBeNote }; extern const OpcodeSpec<uint8_t> loKey { 0, Range<uint8_t>(0, 127), kCanBeNote };
extern const OpcodeSpec<uint8_t> hiKey { 127, Range<uint8_t>(0, 127), kCanBeNote }; extern const OpcodeSpec<uint8_t> hiKey { 127, Range<uint8_t>(0, 127), kCanBeNote };
extern const OpcodeSpec<float> loCC { 0.0f , Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> loCC { 0, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<float> hiCC { 1.0f , Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> hiCC { 127, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<float> loVel { 0.0f , Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> loVel { 0, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<float> hiVel { 1.0f , Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> hiVel { 127, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<uint8_t> loChannelAftertouch { 0, Range<uint8_t>(0, 127), 0 }; extern const OpcodeSpec<uint8_t> loChannelAftertouch { 0, Range<uint8_t>(0, 127), 0 };
extern const OpcodeSpec<uint8_t> hiChannelAftertouch { 127, Range<uint8_t>(0, 127), 0 }; extern const OpcodeSpec<uint8_t> hiChannelAftertouch { 127, Range<uint8_t>(0, 127), 0 };
extern const OpcodeSpec<float> loBend { -1.0f, Range<float>(-8192.0f, 8192.0f), kNormalizeBend }; extern const OpcodeSpec<float> loBend { -8192, Range<float>(-8192.0f, 8192.0f), kNormalizeBend };
extern const OpcodeSpec<float> hiBend { 1.0f, Range<float>(-8192.0f, 8192.0f), kNormalizeBend }; extern const OpcodeSpec<float> hiBend { 8192, Range<float>(-8192.0f, 8192.0f), kNormalizeBend };
extern const OpcodeSpec<float> loNormalized { 0.0f, Range<float>(0.0f, 1.0f), 0 }; extern const OpcodeSpec<float> loNormalized { 0.0f, Range<float>(0.0f, 1.0f), 0 };
extern const OpcodeSpec<float> hiNormalized { 1.0f, Range<float>(0.0f, 1.0f), 0 }; extern const OpcodeSpec<float> hiNormalized { 1.0f, Range<float>(0.0f, 1.0f), 0 };
extern const OpcodeSpec<float> loBipolar { -1.0f, Range<float>(-1.0f, 1.0f), 0 }; extern const OpcodeSpec<float> loBipolar { -1.0f, Range<float>(-1.0f, 1.0f), 0 };
@ -49,7 +47,7 @@ extern const OpcodeSpec<uint16_t> ccNumber { 0, Range<uint16_t>(0, config::numCC
extern const OpcodeSpec<uint8_t> smoothCC { 0, Range<uint8_t>(0, 100), 0 }; extern const OpcodeSpec<uint8_t> smoothCC { 0, Range<uint8_t>(0, 100), 0 };
extern const OpcodeSpec<uint8_t> curveCC { 0, Range<uint8_t>(0, 255), 0 }; extern const OpcodeSpec<uint8_t> curveCC { 0, Range<uint8_t>(0, 255), 0 };
extern const OpcodeSpec<uint8_t> sustainCC { 64, Range<uint8_t>(0, 127), 0 }; extern const OpcodeSpec<uint8_t> sustainCC { 64, Range<uint8_t>(0, 127), 0 };
extern const OpcodeSpec<float> sustainThreshold { 0.0039f, Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> sustainThreshold { 1, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<bool> checkSustain { true, Range<bool>(0, 1), 0 }; extern const OpcodeSpec<bool> checkSustain { true, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<bool> checkSostenuto { true, Range<bool>(0, 1), 0 }; extern const OpcodeSpec<bool> checkSostenuto { true, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<float> loBPM { 0.0f, Range<float>(0.0f, 500.0f), 0 }; extern const OpcodeSpec<float> loBPM { 0.0f, Range<float>(0.0f, 500.0f), 0 };
@ -58,19 +56,19 @@ extern const OpcodeSpec<uint8_t> sequence { 1, Range<uint8_t>(1, 100), 0 };
extern const OpcodeSpec<float> volume { 0.0f, Range<float>(-144.0f, 48.0f), 0 }; extern const OpcodeSpec<float> volume { 0.0f, Range<float>(-144.0f, 48.0f), 0 };
extern const OpcodeSpec<float> volumeMod { 0.0f, Range<float>(-144.0f, 48.0f), 0 }; extern const OpcodeSpec<float> volumeMod { 0.0f, Range<float>(-144.0f, 48.0f), 0 };
extern const OpcodeSpec<float> amplitude { 100.0f, Range<float>(0.0f, 10000.0f), kNormalizePercent }; extern const OpcodeSpec<float> amplitude { 100.0f, Range<float>(0.0f, 10000.0f), kNormalizePercent };
extern const OpcodeSpec<float> amplitudeMod { 0.0f, Range<float>(0.0f, 10000.0f), kNormalizePercent }; extern const OpcodeSpec<float> amplitudeMod { 0.0f, Range<float>(0.0f, 10000.0f), 0 };
extern const OpcodeSpec<float> pan { 0.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent }; extern const OpcodeSpec<float> pan { 0.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent };
extern const OpcodeSpec<float> panMod { 0.0f, Range<float>(-200.0f, 200.0f), kNormalizePercent }; extern const OpcodeSpec<float> panMod { 0.0f, Range<float>(-200.0f, 200.0f), 0 };
extern const OpcodeSpec<float> position { 0.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent }; extern const OpcodeSpec<float> position { 0.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent };
extern const OpcodeSpec<float> positionMod { 0.0f, Range<float>(-200.0f, 200.0f), kNormalizePercent }; extern const OpcodeSpec<float> positionMod { 0.0f, Range<float>(-200.0f, 200.0f), 0 };
extern const OpcodeSpec<float> width { 100.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent }; extern const OpcodeSpec<float> width { 100.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent };
extern const OpcodeSpec<float> widthMod { 0.0f, Range<float>(-200.0f, 200.0f), kNormalizePercent }; extern const OpcodeSpec<float> widthMod { 0.0f, Range<float>(-200.0f, 200.0f), 0 };
extern const OpcodeSpec<float> crossfadeIn { 0.0f, Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> crossfadeIn { 0.0f, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<float> crossfadeInNorm { 0.0f, Range<float>(0.0f, 1.0f), 0 }; extern const OpcodeSpec<float> crossfadeInNorm { 0.0f, Range<float>(0.0f, 1.0f), 0 };
extern const OpcodeSpec<float> crossfadeOut { 1.0f, Range<float>(0.0f, 127.0f), kNormalizeMidi }; extern const OpcodeSpec<float> crossfadeOut { 127.0f, Range<float>(0.0f, 127.0f), kNormalizeMidi };
extern const OpcodeSpec<float> crossfadeOutNorm { 1.0f, Range<float>(0.0f, 1.0f), 0 }; extern const OpcodeSpec<float> crossfadeOutNorm { 1.0f, Range<float>(0.0f, 1.0f), 0 };
extern const OpcodeSpec<float> ampKeytrack { 0.0f, Range<float>(-96.0f, 12.0f), 0 }; extern const OpcodeSpec<float> ampKeytrack { 0.0f, Range<float>(-96.0f, 12.0f), 0 };
extern const OpcodeSpec<float> ampVeltrack { 100.0f, Range<float>(-100.0f, 100.0f), 0 }; extern const OpcodeSpec<float> ampVeltrack { 100.0f, Range<float>(-100.0f, 100.0f), kNormalizePercent };
extern const OpcodeSpec<float> ampVelcurve { 0.0f, Range<float>(0.0f, 1.0f), 0 }; extern const OpcodeSpec<float> ampVelcurve { 0.0f, Range<float>(0.0f, 1.0f), 0 };
extern const OpcodeSpec<float> ampRandom { 0.0f, Range<float>(0.0f, 24.0f), 0 }; extern const OpcodeSpec<float> ampRandom { 0.0f, Range<float>(0.0f, 24.0f), 0 };
extern const OpcodeSpec<bool> rtDead { false, Range<bool>(0, 1), 0 }; extern const OpcodeSpec<bool> rtDead { false, Range<bool>(0, 1), 0 };
@ -144,7 +142,7 @@ extern const OpcodeSpec<float> compRelease { 0.05f, Range<float>(0.0f, 10.0f), 0
extern const OpcodeSpec<bool> compSTLink { false, Range<bool>(0, 1), 0 }; extern const OpcodeSpec<bool> compSTLink { false, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<float> compThreshold { 0.0f, Range<float>(-100.0f, 0.0f), 0 }; extern const OpcodeSpec<float> compThreshold { 0.0f, Range<float>(-100.0f, 0.0f), 0 };
extern const OpcodeSpec<float> compRatio { 1.0f, Range<float>(1.0f, 50.0f), 0 }; extern const OpcodeSpec<float> compRatio { 1.0f, Range<float>(1.0f, 50.0f), 0 };
extern const OpcodeSpec<float> compGain { 1.0f, Range<float>(-100.0f, 100.0f), kDb2Mag }; extern const OpcodeSpec<float> compGain { 0.0f, Range<float>(-100.0f, 100.0f), kDb2Mag };
extern const OpcodeSpec<float> fverbSize { 0.0f, Range<float>(0.0f, 100.0f), 0 }; extern const OpcodeSpec<float> fverbSize { 0.0f, Range<float>(0.0f, 100.0f), 0 };
extern const OpcodeSpec<float> fverbPredelay { 0.0f, Range<float>(0.0f, 10.0f), 0 }; extern const OpcodeSpec<float> fverbPredelay { 0.0f, Range<float>(0.0f, 10.0f), 0 };
extern const OpcodeSpec<float> fverbTone { 100.0f, Range<float>(0.0f, 100.0f), 0 }; extern const OpcodeSpec<float> fverbTone { 100.0f, Range<float>(0.0f, 100.0f), 0 };

View file

@ -24,11 +24,14 @@
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once #pragma once
#include <limits>
#include <cstdint>
#include <type_traits>
#include "Range.h" #include "Range.h"
#include "Config.h" #include "Config.h"
#include "SfzFilter.h" #include "SfzFilter.h"
#include <limits> #include "SfzHelpers.h"
#include <cstdint> #include "MathHelpers.h"
namespace sfz namespace sfz
@ -68,10 +71,40 @@ enum OpcodeFlags : int {
template<class T> template<class T>
struct OpcodeSpec struct OpcodeSpec
{ {
T defaultValue; T defaultInputValue;
Range<T> bounds; Range<T> bounds;
int flags; int flags;
operator T() const { return defaultValue; } template<class U=T>
typename std::enable_if<std::is_arithmetic<U>::value, U>::type normalizeInput(U input) const
{
constexpr auto needsOperation {
kNormalizePercent |
kNormalizeMidi |
kNormalizeBend |
kDb2Mag
};
if (!(flags & needsOperation))
return input;
else if (flags & kNormalizePercent)
return normalizePercents(input);
else if (flags & kNormalizeMidi)
return normalize7Bits(input);
else if (flags & kNormalizeBend)
return normalizeBend(input);
else if (flags & kDb2Mag)
return db2mag(input);
else // just in case
return input;
}
template<class U=T>
typename std::enable_if<!std::is_arithmetic<U>::value, U>::type normalizeInput(U input) const
{
return input;
}
operator T() const { return normalizeInput(defaultInputValue); }
}; };
namespace Default namespace Default

View file

@ -155,9 +155,9 @@ absl::optional<T> readInt_(OpcodeSpec<T> spec, absl::string_view v)
#define INSTANTIATE_FOR_INTEGRAL(T) \ #define INSTANTIATE_FOR_INTEGRAL(T) \
template <> \ template <> \
T Opcode::read(OpcodeSpec<T> spec) const \ absl::optional<T> Opcode::readOptional(OpcodeSpec<T> spec) const \
{ \ { \
return readInt_<T>(spec, value).value_or(spec.defaultValue); \ return readInt_<T>(spec, value); \
} }
INSTANTIATE_FOR_INTEGRAL(uint8_t) INSTANTIATE_FOR_INTEGRAL(uint8_t)
@ -205,23 +205,14 @@ absl::optional<T> readFloat_(OpcodeSpec<T> spec, absl::string_view v)
return {}; return {};
} }
if (spec.flags & kNormalizeMidi) return spec.normalizeInput(returnedValue);
returnedValue = normalize7Bits(returnedValue);
else if (spec.flags & kNormalizePercent)
returnedValue = normalizePercents(returnedValue);
else if (spec.flags & kNormalizeBend)
returnedValue = normalizeBend(returnedValue);
else if (spec.flags & kDb2Mag)
returnedValue = db2mag(returnedValue);
return returnedValue;
} }
#define INSTANTIATE_FOR_FLOATING_POINT(T) \ #define INSTANTIATE_FOR_FLOATING_POINT(T) \
template <> \ template <> \
T Opcode::read(OpcodeSpec<T> spec) const \ absl::optional<T> Opcode::readOptional(OpcodeSpec<T> spec) const \
{ \ { \
return readFloat_<T>(spec, value).value_or(spec.defaultValue); \ return readFloat_<T>(spec, value); \
} }
INSTANTIATE_FOR_FLOATING_POINT(float) INSTANTIATE_FOR_FLOATING_POINT(float)
@ -292,17 +283,17 @@ absl::optional<bool> readBooleanFromOpcode(const Opcode& opcode)
} }
template <> template <>
OscillatorEnabled Opcode::read(OpcodeSpec<OscillatorEnabled> spec) const absl::optional<OscillatorEnabled> Opcode::readOptional(OpcodeSpec<OscillatorEnabled>) const
{ {
auto v = readBooleanFromOpcode(*this); auto v = readBooleanFromOpcode(*this);
if (!v) if (!v)
return spec.defaultValue; return {};
return *v ? OscillatorEnabled::On : OscillatorEnabled::Off; return *v ? OscillatorEnabled::On : OscillatorEnabled::Off;
} }
template <> template <>
Trigger Opcode::read(OpcodeSpec<Trigger> spec) const absl::optional<Trigger> Opcode::readOptional(OpcodeSpec<Trigger>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("attack"): return Trigger::attack; case hash("attack"): return Trigger::attack;
@ -313,11 +304,11 @@ Trigger Opcode::read(OpcodeSpec<Trigger> spec) const
} }
DBG("Unknown trigger value: " << value); DBG("Unknown trigger value: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
CrossfadeCurve Opcode::read(OpcodeSpec<CrossfadeCurve> spec) const absl::optional<CrossfadeCurve> Opcode::readOptional(OpcodeSpec<CrossfadeCurve>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("power"): return CrossfadeCurve::power; case hash("power"): return CrossfadeCurve::power;
@ -325,11 +316,11 @@ CrossfadeCurve Opcode::read(OpcodeSpec<CrossfadeCurve> spec) const
} }
DBG("Unknown crossfade power curve: " << value); DBG("Unknown crossfade power curve: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
OffMode Opcode::read(OpcodeSpec<OffMode> spec) const absl::optional<OffMode> Opcode::readOptional(OpcodeSpec<OffMode>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("fast"): return OffMode::fast; case hash("fast"): return OffMode::fast;
@ -338,11 +329,11 @@ OffMode Opcode::read(OpcodeSpec<OffMode> spec) const
} }
DBG("Unknown off mode: " << value); DBG("Unknown off mode: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
FilterType Opcode::read(OpcodeSpec<FilterType> spec) const absl::optional<FilterType> Opcode::readOptional(OpcodeSpec<FilterType>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("lpf_1p"): return kFilterLpf1p; case hash("lpf_1p"): return kFilterLpf1p;
@ -371,11 +362,11 @@ FilterType Opcode::read(OpcodeSpec<FilterType> spec) const
} }
DBG("Unknown filter type: " << value); DBG("Unknown filter type: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
EqType Opcode::read(OpcodeSpec<EqType> spec) const absl::optional<EqType> Opcode::readOptional(OpcodeSpec<EqType>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("peak"): return kEqPeak; case hash("peak"): return kEqPeak;
@ -384,11 +375,11 @@ EqType Opcode::read(OpcodeSpec<EqType> spec) const
} }
DBG("Unknown EQ type: " << value); DBG("Unknown EQ type: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
VelocityOverride Opcode::read(OpcodeSpec<VelocityOverride> spec) const absl::optional<VelocityOverride> Opcode::readOptional(OpcodeSpec<VelocityOverride>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("current"): return VelocityOverride::current; case hash("current"): return VelocityOverride::current;
@ -396,11 +387,11 @@ VelocityOverride Opcode::read(OpcodeSpec<VelocityOverride> spec) const
} }
DBG("Unknown velocity override: " << value); DBG("Unknown velocity override: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
SelfMask Opcode::read(OpcodeSpec<SelfMask> spec) const absl::optional<SelfMask> Opcode::readOptional(OpcodeSpec<SelfMask>) const
{ {
switch (hash(value)) { switch (hash(value)) {
case hash("on"): case hash("on"):
@ -409,25 +400,28 @@ SelfMask Opcode::read(OpcodeSpec<SelfMask> spec) const
} }
DBG("Unknown velocity override: " << value); DBG("Unknown velocity override: " << value);
return spec.defaultValue; return absl::nullopt;
} }
template <> template <>
bool Opcode::read(OpcodeSpec<bool> spec) const absl::optional<bool> Opcode::readOptional(OpcodeSpec<bool>) const
{ {
return readBooleanFromOpcode(*this).value_or(spec.defaultValue); return readBooleanFromOpcode(*this);
} }
template <> template <>
LFOWave Opcode::read(OpcodeSpec<LFOWave> spec) const absl::optional<LFOWave> Opcode::readOptional(OpcodeSpec<LFOWave> spec) const
{ {
const OpcodeSpec<int> intSpec { const OpcodeSpec<int> intSpec {
static_cast<int>(spec.defaultValue), static_cast<int>(spec.defaultInputValue),
Range<int>(static_cast<int>(spec.bounds.getStart()), static_cast<int>(spec.bounds.getEnd())), Range<int>(static_cast<int>(spec.bounds.getStart()), static_cast<int>(spec.bounds.getEnd())),
0 0
}; };
int value = read(intSpec);
return static_cast<LFOWave>(value); if (auto value = readOptional(intSpec))
return static_cast<LFOWave>(*value);
return absl::nullopt;
} }
} // namespace sfz } // namespace sfz

View file

@ -102,7 +102,10 @@ struct Opcode {
} }
template <class T> template <class T>
T read(OpcodeSpec<T> spec) const; absl::optional<T> readOptional(OpcodeSpec<T> spec) const;
template <class T>
T read(OpcodeSpec<T> spec) const { return readOptional(spec).value_or(spec); }
private: private:
static OpcodeCategory identifyCategory(absl::string_view name); static OpcodeCategory identifyCategory(absl::string_view name);

View file

@ -283,8 +283,8 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
break; break;
case hash("sw_last"): case hash("sw_last"):
if (!lastKeyswitchRange) { if (!lastKeyswitchRange) {
lastKeyswitch = opcode.read(Default::key); lastKeyswitch = opcode.readOptional(Default::key);
keySwitched = false; keySwitched = !lastKeyswitch.has_value();
} }
break; break;
case hash("sw_lolast"): case hash("sw_lolast"):
@ -315,15 +315,15 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
keyswitchLabel = opcode.value; keyswitchLabel = opcode.value;
break; break;
case hash("sw_down"): case hash("sw_down"):
downKeyswitch = opcode.read(Default::key); downKeyswitch = opcode.readOptional(Default::key);
keySwitched = false; keySwitched = !downKeyswitch.has_value();
break; break;
case hash("sw_up"): case hash("sw_up"):
upKeyswitch = opcode.read(Default::key); upKeyswitch = opcode.readOptional(Default::key);
break; break;
case hash("sw_previous"): case hash("sw_previous"):
previousKeyswitch = opcode.read(Default::key); previousKeyswitch = opcode.readOptional(Default::key);
previousKeySwitched = false; previousKeySwitched = !previousKeyswitch.has_value();
break; break;
case hash("sw_vel"): case hash("sw_vel"):
velocityOverride = velocityOverride =

View file

@ -389,7 +389,7 @@ struct Region {
float position { normalizePercents(Default::position) }; // position float position { normalizePercents(Default::position) }; // position
uint8_t ampKeycenter { Default::key }; // amp_keycenter uint8_t ampKeycenter { Default::key }; // amp_keycenter
float ampKeytrack { Default::ampKeytrack }; // amp_keytrack float ampKeytrack { Default::ampKeytrack }; // amp_keytrack
float ampVeltrack { normalizePercents(Default::ampVeltrack) }; // amp_veltrack float ampVeltrack { Default::ampVeltrack }; // amp_veltrack
std::vector<std::pair<uint8_t, float>> velocityPoints; // amp_velcurve_N std::vector<std::pair<uint8_t, float>> velocityPoints; // amp_velcurve_N
absl::optional<Curve> velCurve {}; absl::optional<Curve> velCurve {};
float ampRandom { Default::ampRandom }; // amp_random float ampRandom { Default::ampRandom }; // amp_random

View file

@ -16,7 +16,6 @@
#include "MathHelpers.h" #include "MathHelpers.h"
#include "SIMDHelpers.h" #include "SIMDHelpers.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "Defaults.h"
namespace sfz { namespace sfz {
@ -126,6 +125,12 @@ constexpr float normalize7Bits(T value)
return static_cast<float>(min(max(value, T { 0 }), T { 127 })) / 127.0f; return static_cast<float>(min(max(value, T { 0 }), T { 127 })) / 127.0f;
} }
template <>
constexpr float normalize7Bits(bool value)
{
return value ? 1.0f : 0.0f;
}
/** /**
* @brief Normalize a CC value between 0.0 and 1.0 * @brief Normalize a CC value between 0.0 and 1.0
* *
@ -188,11 +193,11 @@ inline CXX14_CONSTEXPR uint8_t offsetAndClampKey(uint8_t key, int offset)
{ {
const int offsetKey { key + offset }; const int offsetKey { key + offset };
if (offsetKey > std::numeric_limits<uint8_t>::max()) if (offsetKey > std::numeric_limits<uint8_t>::max())
return Default::key.bounds.getEnd(); return 127;
if (offsetKey < std::numeric_limits<uint8_t>::min()) if (offsetKey < std::numeric_limits<uint8_t>::min())
return Default::key.bounds.getStart(); return 0;
return Default::key.bounds.clamp(static_cast<uint8_t>(offsetKey)); return clamp<uint8_t>(static_cast<uint8_t>(offsetKey), 0, 127);
} }
namespace literals { namespace literals {

View file

@ -318,7 +318,7 @@ TEST_CASE("[Opcode] opcode read (uint8_t)")
{ {
Opcode opcode { "", "110" }; Opcode opcode { "", "110" };
OpcodeSpec<uint8_t> spec { 0, Range<uint8_t>(0, 100), 0 }; OpcodeSpec<uint8_t> spec { 0, Range<uint8_t>(0, 100), 0 };
REQUIRE( opcode.read(spec) == spec.defaultValue ); REQUIRE( opcode.read(spec) == spec.defaultInputValue );
} }
SECTION("Clamp upper") SECTION("Clamp upper")
@ -353,7 +353,7 @@ TEST_CASE("[Opcode] opcode read (uint8_t)")
{ {
Opcode opcode { "", "garbage10" }; Opcode opcode { "", "garbage10" };
OpcodeSpec<uint8_t> spec { 0, Range<uint8_t>(0, 100), 0 }; OpcodeSpec<uint8_t> spec { 0, Range<uint8_t>(0, 100), 0 };
REQUIRE( opcode.read(spec) == spec.defaultValue ); REQUIRE( opcode.read(spec) == spec.defaultInputValue );
} }
SECTION("Can be note") SECTION("Can be note")
@ -458,7 +458,7 @@ TEST_CASE("[Opcode] opcode read (float)")
{ {
Opcode opcode { "", "110" }; Opcode opcode { "", "110" };
OpcodeSpec<float> spec { 0.0f, Range<float>(-100.0f, 100.0f), 0 }; OpcodeSpec<float> spec { 0.0f, Range<float>(-100.0f, 100.0f), 0 };
REQUIRE( opcode.read(spec) == spec.defaultValue ); REQUIRE( opcode.read(spec) == spec.defaultInputValue );
} }
SECTION("Clamp upper") SECTION("Clamp upper")

View file

@ -747,7 +747,7 @@ TEST_CASE("[Values] Upswitch")
"/region2/sw_up,N : { }", "/region2/sw_up,N : { }",
"/region3/sw_up,N : { }", "/region3/sw_up,N : { }",
"/region4/sw_up,i : { 60 }", "/region4/sw_up,i : { 60 }",
"/region5/sw_up,i : { 60 }", "/region5/sw_up,N : { }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
} }
@ -778,7 +778,7 @@ TEST_CASE("[Values] Downswitch")
"/region2/sw_down,N : { }", "/region2/sw_down,N : { }",
"/region3/sw_down,N : { }", "/region3/sw_down,N : { }",
"/region4/sw_down,i : { 60 }", "/region4/sw_down,i : { 60 }",
"/region5/sw_down,i : { 60 }", "/region5/sw_down,N : { }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
} }
@ -809,7 +809,7 @@ TEST_CASE("[Values] Previous keyswitch")
"/region2/sw_previous,N : { }", "/region2/sw_previous,N : { }",
"/region3/sw_previous,N : { }", "/region3/sw_previous,N : { }",
"/region4/sw_previous,i : { 60 }", "/region4/sw_previous,i : { 60 }",
"/region5/sw_previous,i : { 64 }", "/region5/sw_previous,N : { }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
} }
@ -889,7 +889,7 @@ TEST_CASE("[Values] BPM range")
"/region0/bpm_range,ff : { 0, 500 }", "/region0/bpm_range,ff : { 0, 500 }",
"/region1/bpm_range,ff : { 34.1, 60.2 }", "/region1/bpm_range,ff : { 34.1, 60.2 }",
"/region2/bpm_range,ff : { 0, 60 }", "/region2/bpm_range,ff : { 0, 60 }",
"/region3/bpm_range,ff : { 0, 0 }", "/region3/bpm_range,ff : { 20, 500 }",
"/region4/bpm_range,ff : { 10, 10 }", "/region4/bpm_range,ff : { 10, 10 }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
@ -1553,12 +1553,11 @@ TEST_CASE("[Values] Amp Veltrack")
)"); )");
synth.dispatchMessage(client, 0, "/region0/amp_veltrack", "", nullptr); synth.dispatchMessage(client, 0, "/region0/amp_veltrack", "", nullptr);
synth.dispatchMessage(client, 0, "/region1/amp_veltrack", "", nullptr); synth.dispatchMessage(client, 0, "/region1/amp_veltrack", "", nullptr);
// TODO: activate for the new region parser ; ignore oob synth.dispatchMessage(client, 0, "/region2/amp_veltrack", "", nullptr);
// synth.dispatchMessage(client, 0, "/region2/amp_veltrack", "", nullptr);
std::vector<std::string> expected { std::vector<std::string> expected {
"/region0/amp_veltrack,f : { 100 }", "/region0/amp_veltrack,f : { 100 }",
"/region1/amp_veltrack,f : { 10.1 }", "/region1/amp_veltrack,f : { 10.1 }",
// "/region2/amp_veltrack,f : { 100 }", "/region2/amp_veltrack,f : { 100 }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
} }