Read booleans as a template overload

This commit is contained in:
Paul Fd 2020-12-30 01:16:39 +01:00 committed by Paul Ferrand
parent 0ab836787f
commit 17594241e7
11 changed files with 67 additions and 49 deletions

View file

@ -14,6 +14,7 @@ extern const OpcodeSpec<uint32_t> sampleEnd { uint32_t_max, Range<uint32_t>(0, u
extern const OpcodeSpec<uint32_t> sampleCount { 0, Range<uint32_t>(0, uint32_t_max), 0 };
extern const OpcodeSpec<uint32_t> loopRange { 0, Range<uint32_t>(0, uint32_t_max), 0 };
extern const OpcodeSpec<float> loopCrossfade { 1e-3, Range<float>(1e-3, 1.0f), kEnforceLowerBound | kEnforceUpperBound };
extern const OpcodeSpec<OscillatorEnabled> oscillator { OscillatorEnabled::Auto, Range<OscillatorEnabled>(OscillatorEnabled::Auto, OscillatorEnabled::On), 0 };
extern const OpcodeSpec<float> oscillatorPhase { 0.0f, Range<float>(0.0f, 1.0f), 0 };
extern const OpcodeSpec<int> oscillatorMode { 0, Range<int>(0, 2), kIgnoreOOB };
extern const OpcodeSpec<int> oscillatorMulti { 1, Range<int>(1, config::oscillatorsPerVoice), kIgnoreOOB };
@ -37,6 +38,8 @@ extern const OpcodeSpec<uint8_t> smoothCC { 0, Range<uint8_t>(0, 100), kIgnoreOO
extern const OpcodeSpec<uint8_t> curveCC { 0, Range<uint8_t>(0, 255), kIgnoreOOB };
extern const OpcodeSpec<uint8_t> sustainCC { 64, Range<uint8_t>(0, 127), kIgnoreOOB };
extern const OpcodeSpec<float> sustainThreshold { 0.0039f, Range<float>(0.0f, 1.0f), kIgnoreOOB };
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<float> bpm { 0.0f, Range<float>(0.0f, 500.0f), kEnforceLowerBound };
extern const OpcodeSpec<uint8_t> sequence { 1, Range<uint8_t>(1, 100), kIgnoreOOB };
extern const OpcodeSpec<float> volume { 0.0f, Range<float>(-144.0f, 48.0f), 0 };
@ -57,6 +60,7 @@ extern const OpcodeSpec<float> ampKeytrack { 0.0f, Range<float>(-96.0f, 12.0f),
extern const OpcodeSpec<float> ampVeltrack { 100.0f, Range<float>(-100.0f, 100.0f), kIgnoreOOB };
extern const OpcodeSpec<float> ampVelcurve { 0.0f, Range<float>(0.0f, 1.0f), kEnforceLowerBound | kEnforceUpperBound };
extern const OpcodeSpec<float> ampRandom { 0.0f, Range<float>(0.0f, 24.0f), kEnforceLowerBound };
extern const OpcodeSpec<bool> rtDead { false, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<float> rtDecay { 0.0f, Range<float>(0.0f, 200.0f), kEnforceLowerBound };
extern const OpcodeSpec<float> filterCutoff { 0.0f, Range<float>(0.0f, 20000.0f), kEnforceLowerBound | kEnforceUpperBound };
extern const OpcodeSpec<float> filterCutoffMod { 0.0f, Range<float>(-12000.0f, 12000.0f), kEnforceLowerBound };
@ -105,6 +109,7 @@ extern const OpcodeSpec<float> egPercent { 0.0f, Range<float>(0.0f, 100.0f), kEn
extern const OpcodeSpec<float> egPercentMod { 0.0f, Range<float>(-100.0f, 100.0f), 0 };
extern const OpcodeSpec<float> egDepth { 0.0f, Range<float>(-12000.0f, 12000.0f), 0 };
extern const OpcodeSpec<float> egVel2Depth { 0.0f, Range<float>(-12000.0f, 12000.0f), 0 };
extern const OpcodeSpec<bool> flexEGAmpeg { false, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<int> flexEGDynamic { 0, Range<int>(0, 1), kIgnoreOOB };
extern const OpcodeSpec<int> flexEGSustain { 0, Range<int>(0, 100), kIgnoreOOB };
extern const OpcodeSpec<float> flexEGPointTime { 0.0f, Range<float>(0.0f, 100.0f), kEnforceLowerBound };
@ -123,6 +128,7 @@ extern const OpcodeSpec<float> distoDepth { 0.0f, Range<float>(0.0f, 100.0f), kE
extern const OpcodeSpec<unsigned> distoStages { 1, Range<unsigned>(1, maxDistoStages), kEnforceLowerBound };
extern const OpcodeSpec<float> compAttack { 0.005f, Range<float>(0.0f, 10.0f), kEnforceLowerBound };
extern const OpcodeSpec<float> compRelease { 0.05f, Range<float>(0.0f, 10.0f), kEnforceLowerBound };
extern const OpcodeSpec<bool> compSTLink { false, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<float> compThreshold { 0.0f, Range<float>(-100.0f, 0.0f), kIgnoreOOB };
extern const OpcodeSpec<float> compRatio { 1.0f, Range<float>(1.0f, 50.0f), kIgnoreOOB };
extern const OpcodeSpec<float> compGain { 0.0f, Range<float>(-100.0f, 100.0f), 0 };
@ -130,6 +136,7 @@ extern const OpcodeSpec<float> fverbSize { 0.0f, Range<float>(0.0f, 100.0f), kEn
extern const OpcodeSpec<float> fverbPredelay { 0.0f, Range<float>(0.0f, 10.0f), kEnforceLowerBound };
extern const OpcodeSpec<float> fverbTone { 100.0f, Range<float>(0.0f, 100.0f), kIgnoreOOB };
extern const OpcodeSpec<float> fverbDamp { 0.0f, Range<float>(0.0f, 100.0f), kIgnoreOOB };
extern const OpcodeSpec<bool> gateSTLink { false, Range<bool>(0, 1), 0 };
extern const OpcodeSpec<float> gateAttack { 0.005f, Range<float>(0.0f, 10.0f), kEnforceLowerBound };
extern const OpcodeSpec<float> gateRelease { 0.05f, Range<float>(0.0f, 10.0f), kEnforceLowerBound };
extern const OpcodeSpec<float> gateHold { 0.0f, Range<float>(0.0f, 10.0f), kEnforceLowerBound };

View file

@ -29,16 +29,18 @@
#include <limits>
#include <cstdint>
enum class SfzTrigger { attack, release, release_key, first, legato };
enum class SfzLoopMode { no_loop, one_shot, loop_continuous, loop_sustain };
enum class SfzOffMode { fast, normal, time };
enum class SfzVelocityOverride { current, previous };
enum class SfzCrossfadeCurve { gain, power };
enum class SfzSelfMask { mask, dontMask };
enum class SfzTrigger { attack = 0, release, release_key, first, legato };
enum class SfzLoopMode { no_loop = 0, one_shot, loop_continuous, loop_sustain };
enum class SfzOffMode { fast = 0, normal, time };
enum class SfzVelocityOverride { current = 0, previous };
enum class SfzCrossfadeCurve { gain = 0, power };
enum class SfzSelfMask { mask = 0, dontMask };
namespace sfz
{
enum class OscillatorEnabled { Auto = -1, Off = 0, On = 1 };
enum OpcodeFlags : int {
kIgnoreOOB = 1,
kEnforceLowerBound = 1 << 1,
@ -66,6 +68,7 @@ namespace Default
extern const OpcodeSpec<uint32_t> loopRange;
extern const OpcodeSpec<float> loopCrossfade;
extern const OpcodeSpec<float> oscillatorPhase;
extern const OpcodeSpec<OscillatorEnabled> oscillator;
extern const OpcodeSpec<int> oscillatorMode;
extern const OpcodeSpec<int> oscillatorMulti;
extern const OpcodeSpec<float> oscillatorDetune;
@ -87,6 +90,8 @@ namespace Default
extern const OpcodeSpec<uint8_t> curveCC;
extern const OpcodeSpec<uint8_t> smoothCC;
extern const OpcodeSpec<uint8_t> sustainCC;
extern const OpcodeSpec<bool> checkSustain;
extern const OpcodeSpec<bool> checkSostenuto;
extern const OpcodeSpec<float> sustainThreshold;
extern const OpcodeSpec<float> bpm;
extern const OpcodeSpec<uint8_t> sequence;
@ -108,6 +113,7 @@ namespace Default
extern const OpcodeSpec<float> ampVeltrack;
extern const OpcodeSpec<float> ampVelcurve;
extern const OpcodeSpec<float> ampRandom;
extern const OpcodeSpec<bool> rtDead;
extern const OpcodeSpec<float> rtDecay;
extern const OpcodeSpec<float> filterCutoff;
extern const OpcodeSpec<float> filterCutoffMod;
@ -156,6 +162,7 @@ namespace Default
extern const OpcodeSpec<float> egPercentMod;
extern const OpcodeSpec<float> egDepth;
extern const OpcodeSpec<float> egVel2Depth;
extern const OpcodeSpec<bool> flexEGAmpeg;
extern const OpcodeSpec<int> flexEGDynamic;
extern const OpcodeSpec<int> flexEGSustain;
extern const OpcodeSpec<float> flexEGPointTime;
@ -175,6 +182,7 @@ namespace Default
extern const OpcodeSpec<float> compAttack;
extern const OpcodeSpec<float> compRelease;
extern const OpcodeSpec<float> compThreshold;
extern const OpcodeSpec<bool> compSTLink;
extern const OpcodeSpec<float> compRatio;
extern const OpcodeSpec<float> compGain;
extern const OpcodeSpec<float> fverbSize;
@ -183,6 +191,7 @@ namespace Default
extern const OpcodeSpec<float> fverbDamp;
extern const OpcodeSpec<float> gateAttack;
extern const OpcodeSpec<float> gateRelease;
extern const OpcodeSpec<bool> gateSTLink;
extern const OpcodeSpec<float> gateHold;
extern const OpcodeSpec<float> gateThreshold;
extern const OpcodeSpec<float> lofiBitred;
@ -190,11 +199,6 @@ namespace Default
extern const OpcodeSpec<float> rectify;
extern const OpcodeSpec<unsigned> stringsNumber;
// Boolean default values
constexpr bool rtDead { false };
constexpr bool checkSustain { true }; // sustain_sw
constexpr bool checkSostenuto { true }; // sostenuto_sw
// Default/max count for objects
constexpr int numEQs { 3 };
constexpr int numFilters { 2 };

View file

@ -35,7 +35,7 @@ struct FlexEGDescription {
int sustain { Default::flexEGSustain.value }; // index of the sustain point (default to 0 in ARIA)
std::vector<FlexEGPoint> points;
// ARIA
bool ampeg = false; // replaces the SFZv1 AmpEG (lowest with this bit wins)
bool ampeg { Default::flexEGAmpeg.value }; // replaces the SFZv1 AmpEG (lowest with this bit wins)
};
} // namespace sfz

View file

@ -294,6 +294,22 @@ absl::optional<bool> readBooleanFromOpcode(const Opcode& opcode)
return absl::nullopt;
}
template <>
absl::optional<OscillatorEnabled> Opcode::read(OpcodeSpec<OscillatorEnabled>) const
{
auto v = readBooleanFromOpcode(*this);
if (!v)
return absl::nullopt;
return *v ? OscillatorEnabled::On : OscillatorEnabled::Off;
}
template <>
absl::optional<bool> Opcode::read(OpcodeSpec<bool>) const
{
return readBooleanFromOpcode(*this);
}
} // namespace sfz
std::ostream &operator<<(std::ostream &os, const sfz::Opcode &opcode)

View file

@ -19,7 +19,9 @@ namespace sfz
*/
template <class Type>
class Range {
static_assert(std::is_arithmetic<Type>::value, "The Type should be arithmetic");
// static_assert(std::is_arithmetic<Type>::value
// || (std::is_enum<Type>::value && std::is_same<typename std::underlying_type<Type>::type, int>::value),
// "The Type should be arithmetic");
public:
constexpr Range() = default;

View file

@ -163,8 +163,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
oscillatorPhase = (*value >= 0) ? wrapPhase(*value) : -1.0f;
break;
case hash("oscillator"):
if (auto value = readBooleanFromOpcode(opcode))
oscillatorEnabled = *value ? OscillatorEnabled::On : OscillatorEnabled::Off;
oscillatorEnabled = opcode.read(Default::oscillator).value_or(oscillatorEnabled);
break;
case hash("oscillator_mode"):
oscillatorMode = opcode.read(Default::oscillatorMode).value_or(oscillatorMode);
@ -243,13 +242,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
}
break;
case hash("rt_dead"):
if (opcode.value == "on") {
rtDead = true;
} else if (opcode.value == "off") {
rtDead = false;
} else {
DBG("Unkown rt_dead value:" << opcode.value);
}
rtDead = opcode.read(Default::rtDead).value_or(rtDead);
break;
// Region logic: key mapping
case hash("lokey"):
@ -387,10 +380,10 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
sustainThreshold = normalizeCC(*value);
break;
case hash("sustain_sw"):
checkSustain = readBooleanFromOpcode(opcode).value_or(Default::checkSustain);
checkSustain = opcode.read(Default::checkSustain).value_or(checkSustain);
break;
case hash("sostenuto_sw"):
checkSostenuto = readBooleanFromOpcode(opcode).value_or(Default::checkSostenuto);
checkSostenuto = opcode.read(Default::checkSostenuto).value_or(checkSostenuto);
break;
// Region logic: internal conditions
case hash("lochanaft"):
@ -1263,7 +1256,7 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode)
return false;
if (!extendIfNecessary(flexEGs, egNumber, Default::numFlexEGs))
return false;
if (auto ampeg = readBooleanFromOpcode(opcode)) {
if (auto ampeg = opcode.read(Default::flexEGAmpeg)) {
FlexEGDescription& desc = flexEGs[egNumber - 1];
if (desc.ampeg != *ampeg) {
desc.ampeg = *ampeg;

View file

@ -332,8 +332,7 @@ struct Region {
// Wavetable oscillator
float oscillatorPhase { Default::oscillatorPhase.value };
enum class OscillatorEnabled { Auto = -1, Off = 0, On = 1 };
OscillatorEnabled oscillatorEnabled { OscillatorEnabled::Auto }; // oscillator
OscillatorEnabled oscillatorEnabled { Default::oscillator.value }; // oscillator
bool hasWavetableSample { false }; // (set according to sample file)
int oscillatorMode { Default::oscillatorMode.value };
int oscillatorMulti { Default::oscillatorMulti.value };
@ -349,7 +348,7 @@ struct Region {
absl::optional<uint32_t> notePolyphony {}; // note_polyphony
uint32_t polyphony { config::maxVoices }; // polyphony
SfzSelfMask selfMask { Default::selfMask };
bool rtDead { Default::rtDead };
bool rtDead { Default::rtDead.value };
// Region logic: key mapping
Range<uint8_t> keyRange { Default::key.bounds }; //lokey, hikey and key
@ -366,8 +365,8 @@ struct Region {
absl::optional<uint8_t> previousKeyswitch {}; // sw_previous
absl::optional<uint8_t> defaultSwitch {};
SfzVelocityOverride velocityOverride { Default::velocityOverride }; // sw_vel
bool checkSustain { Default::checkSustain }; // sustain_sw
bool checkSostenuto { Default::checkSostenuto }; // sostenuto_sw
bool checkSustain { Default::checkSustain.value }; // sustain_sw
bool checkSostenuto { Default::checkSostenuto.value }; // sostenuto_sw
uint16_t sustainCC { Default::sustainCC.value }; // sustain_cc
float sustainThreshold { Default::sustainThreshold.value }; // sustain_cc

View file

@ -31,7 +31,7 @@ namespace fx {
struct Compressor::Impl {
faustCompressor _compressor[2];
bool _stlink = false;
bool _stlink { Default::compSTLink.value };
float _inputGain { Default::compGain.value };
AudioBuffer<float, 2> _tempBuffer2x { 2, _oversampling * config::defaultSamplesPerBlock };
AudioBuffer<float, 2> _gain2x { 2, _oversampling * config::defaultSamplesPerBlock };
@ -191,8 +191,7 @@ namespace fx {
impl._inputGain = db2mag(*value);
break;
case hash("comp_stlink"):
if (auto value = readBooleanFromOpcode(opc))
impl._stlink = *value;
impl._stlink = opc.read(Default::compSTLink).value_or(impl._stlink);
break;
}
}

View file

@ -34,7 +34,7 @@ namespace fx {
struct Gate::Impl {
faustGate _gate[2];
bool _stlink = false;
bool _stlink { Default::gateSTLink.value };
float _inputGain = 1.0;
AudioBuffer<float, 2> _tempBuffer2x { 2, _oversampling * config::defaultSamplesPerBlock };
AudioBuffer<float, 2> _gain2x { 2, _oversampling * config::defaultSamplesPerBlock };
@ -190,9 +190,7 @@ namespace fx {
}
break;
case hash("gate_stlink"):
if (auto value = readBooleanFromOpcode(opc))
impl._stlink = *value;
break;
impl._stlink = opc.read(Default::gateSTLink).value_or(impl._stlink);
}
}

View file

@ -282,7 +282,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
// generator with multi
region = synth.getRegionView(regionNumber++);
@ -290,7 +290,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(region->isStereo());
REQUIRE(region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
// explicit wavetable
region = synth.getRegionView(regionNumber++);
@ -298,7 +298,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(!region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::On);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::On);
// explicit wavetable with multi
region = synth.getRegionView(regionNumber++);
@ -306,7 +306,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(region->isStereo());
REQUIRE(!region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::On);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::On);
// explicit disabled wavetable
region = synth.getRegionView(regionNumber++);
@ -314,7 +314,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(!region->isGenerator());
REQUIRE(!region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Off);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Off);
// explicit disabled wavetable with multi
region = synth.getRegionView(regionNumber++);
@ -322,7 +322,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(!region->isGenerator());
REQUIRE(!region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Off);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Off);
// implicit wavetable (sound file < 3000 frames)
region = synth.getRegionView(regionNumber++);
@ -330,7 +330,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(!region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
// implicit non-wavetable (sound file >= 3000 frames)
region = synth.getRegionView(regionNumber++);
@ -338,7 +338,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(!region->isGenerator());
REQUIRE(!region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
// generator with multi=1 (single)
region = synth.getRegionView(regionNumber++);
@ -346,7 +346,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
// generator with multi=2 (ring modulation)
region = synth.getRegionView(regionNumber++);
@ -354,7 +354,7 @@ TEST_CASE("[Files] Channels (channels_multi.sfz)")
REQUIRE(!region->isStereo());
REQUIRE(region->isGenerator());
REQUIRE(region->isOscillator());
REQUIRE(region->oscillatorEnabled == Region::OscillatorEnabled::Auto);
REQUIRE(region->oscillatorEnabled == OscillatorEnabled::Auto);
}
TEST_CASE("[Files] wrong (overlapping) replacement for defines")

View file

@ -2347,7 +2347,7 @@ TEST_CASE("[Values] Sustain switch")
"/region0/sustain_sw,T : { }",
"/region1/sustain_sw,F : { }",
"/region2/sustain_sw,T : { }",
"/region3/sustain_sw,T : { }",
"/region3/sustain_sw,F : { }",
};
REQUIRE(messageList == expected);
}
@ -2373,7 +2373,7 @@ TEST_CASE("[Values] Sostenuto switch")
"/region0/sostenuto_sw,T : { }",
"/region1/sostenuto_sw,F : { }",
"/region2/sostenuto_sw,T : { }",
"/region3/sostenuto_sw,T : { }",
"/region3/sostenuto_sw,F : { }",
};
REQUIRE(messageList == expected);
}