From 0196fb57ad55c88eaaa33d4626509878ad4e76fb Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Fri, 19 Mar 2021 17:51:45 +0100 Subject: [PATCH] Remove opcode limits --- src/sfizz/Defaults.cpp | 231 +++++++++++++++++----------------- src/sfizz/Defaults.h | 22 ++-- src/sfizz/FilterDescription.h | 4 +- src/sfizz/FilterPool.cpp | 2 +- src/sfizz/FlexEGDescription.h | 2 +- src/sfizz/LFO.cpp | 8 +- src/sfizz/ModifierHelpers.h | 12 +- src/sfizz/Opcode.cpp | 3 +- src/sfizz/Range.h | 22 ++-- src/sfizz/Region.cpp | 19 +-- src/sfizz/Region.h | 38 +++--- src/sfizz/SfzHelpers.h | 2 +- src/sfizz/Synth.cpp | 8 +- tests/DirectRegionT.cpp | 2 +- tests/RegionValuesT.cpp | 121 +++++++++--------- tests/TestHelpers.h | 4 +- 16 files changed, 250 insertions(+), 250 deletions(-) diff --git a/src/sfizz/Defaults.cpp b/src/sfizz/Defaults.cpp index b01a8f77..d3c6393d 100644 --- a/src/sfizz/Defaults.cpp +++ b/src/sfizz/Defaults.cpp @@ -17,135 +17,133 @@ using UInt32Spec = const OpcodeSpec; using BoolSpec = const OpcodeSpec; template using ESpec = const OpcodeSpec; -FloatSpec delay { 0.0f, {0.0f, 100.0f}, 0 }; -FloatSpec delayRandom { 0.0f, {0.0f, 100.0f}, 0 }; -FloatSpec delayMod { 0.0f, {0.0f, 100.0f}, 0 }; -Int64Spec offset { 0, {0, uint32_t_max}, 0 }; -Int64Spec offsetMod { 0, {0, uint32_t_max}, 0 }; -Int64Spec offsetRandom { 0, {0, uint32_t_max}, 0 }; -UInt32Spec sampleEnd { uint32_t_max, {0, uint32_t_max}, kEnforceLowerBound }; -UInt32Spec sampleCount { 0, {0, uint32_t_max}, 0 }; -UInt32Spec loopStart { 0, {0, uint32_t_max}, 0 }; -UInt32Spec loopEnd { uint32_t_max, {0, uint32_t_max}, 0 }; -UInt32Spec loopCount { 0, {0, uint32_t_max}, 0 }; -FloatSpec loopCrossfade { 1e-3, {1e-3, 1.0f}, 0 }; +FloatSpec delay { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec delayRandom { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec delayMod { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +Int64Spec offset { 0, {0, uint32_t_max}, kPermissiveBounds }; +Int64Spec offsetMod { 0, {0, uint32_t_max}, kPermissiveBounds }; +Int64Spec offsetRandom { 0, {0, uint32_t_max}, kPermissiveBounds }; +UInt32Spec sampleEnd { uint32_t_max, {0, uint32_t_max}, kEnforceBounds }; +UInt32Spec sampleCount { 0, {0, uint32_t_max}, kEnforceUpperBound }; +UInt32Spec loopStart { 0, {0, uint32_t_max}, kEnforceUpperBound }; +UInt32Spec loopEnd { uint32_t_max, {0, uint32_t_max}, kEnforceUpperBound }; +UInt32Spec loopCount { 0, {0, uint32_t_max}, kEnforceUpperBound }; +FloatSpec loopCrossfade { 1e-3, {1e-3, 1.0f}, kEnforceLowerBound|kPermissiveUpperBound }; ESpec oscillator { OscillatorEnabled::Auto, {OscillatorEnabled::Auto, OscillatorEnabled::On}, 0 }; -FloatSpec oscillatorPhase { 0.0f, {-1000.0f, 1000.0f}, 0 }; +FloatSpec oscillatorPhase { 0.0f, {-1000.0f, 1000.0f}, kPermissiveBounds }; Int32Spec oscillatorMode { 0, {0, 2}, 0 }; -Int32Spec oscillatorMulti { 1, {1, config::oscillatorsPerVoice}, 0 }; -FloatSpec oscillatorDetune { 0.0f, {-12000.0f, 12000.0f}, 0 }; -FloatSpec oscillatorDetuneMod { 0.0f, {-12000.0f, 12000.0f}, 0 }; -FloatSpec oscillatorModDepth { 0.0f, {0.0f, 10000.0f}, kNormalizePercent }; -FloatSpec oscillatorModDepthMod { 0.0f, {0.0f, 10000.0f}, kNormalizePercent }; +Int32Spec oscillatorMulti { 1, {1, config::oscillatorsPerVoice}, kEnforceBounds }; +FloatSpec oscillatorDetune { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec oscillatorDetuneMod { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec oscillatorModDepth { 0.0f, {0.0f, 10000.0f}, kNormalizePercent|kPermissiveBounds }; +FloatSpec oscillatorModDepthMod { 0.0f, {0.0f, 10000.0f}, kNormalizePercent|kPermissiveBounds }; Int32Spec oscillatorQuality { 1, {0, 3}, 0 }; UInt32Spec group { 0, {0, uint32_t_max}, 0 }; -FloatSpec offTime { 6e-3f, {0.0f, 100.0f}, 0 }; -UInt32Spec polyphony { config::maxVoices, {0, config::maxVoices}, 0 }; -UInt32Spec notePolyphony { config::maxVoices, {0, config::maxVoices}, 0 }; +FloatSpec offTime { 6e-3f, {0.0f, 100.0f}, kPermissiveBounds }; +UInt32Spec polyphony { config::maxVoices, {0, config::maxVoices}, kEnforceBounds }; +UInt32Spec notePolyphony { config::maxVoices, {0, config::maxVoices}, kEnforceBounds }; UInt8Spec key { 60, {0, 127}, kCanBeNote }; UInt8Spec loKey { 0, {0, 127}, kCanBeNote }; UInt8Spec hiKey { 127, {0, 127}, kCanBeNote }; -FloatSpec loCC { 0, {0.0f, 127.0f}, kNormalizeMidi }; -FloatSpec hiCC { 127, {0.0f, 127.0f}, kNormalizeMidi }; -FloatSpec loVel { 0, {0.0f, 127.0f}, kNormalizeMidi }; -FloatSpec hiVel { 127, {0.0f, 127.0f}, kNormalizeMidi }; -FloatSpec loChannelAftertouch { 0, {0, 127}, kNormalizeMidi }; -FloatSpec hiChannelAftertouch { 127, {0, 127}, kNormalizeMidi }; -FloatSpec loBend { -8192, {-8192.0f, 8192.0f}, kNormalizeBend }; -FloatSpec hiBend { 8192, {-8192.0f, 8192.0f}, kNormalizeBend }; -FloatSpec loNormalized { 0.0f, {0.0f, 1.0f}, 0 }; -FloatSpec hiNormalized { 1.0f, {0.0f, 1.0f}, 0 }; -FloatSpec loBipolar { -1.0f, {-1.0f, 1.0f}, 0 }; -FloatSpec hiBipolar { 1.0f, {-1.0f, 1.0f}, 0 }; +FloatSpec loCC { 0, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; +FloatSpec hiCC { 127, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; +FloatSpec loVel { 0, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; +FloatSpec hiVel { 127, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; +FloatSpec loChannelAftertouch { 0, {0, 127}, kNormalizeMidi|kPermissiveBounds }; +FloatSpec hiChannelAftertouch { 127, {0, 127}, kNormalizeMidi|kPermissiveBounds }; +FloatSpec loBend { -8191, {-8192.0f, 8191.0f}, kNormalizeBend|kPermissiveBounds }; +FloatSpec hiBend { 8191, {-8192.0f, 8191.0f}, kNormalizeBend|kPermissiveBounds }; +FloatSpec loNormalized { 0.0f, {0.0f, 1.0f}, kPermissiveBounds }; +FloatSpec hiNormalized { 1.0f, {0.0f, 1.0f}, kPermissiveBounds }; +FloatSpec loBipolar { -1.0f, {-1.0f, 1.0f}, kPermissiveBounds }; +FloatSpec hiBipolar { 1.0f, {-1.0f, 1.0f}, kPermissiveBounds }; UInt16Spec ccNumber { 0, {0, config::numCCs}, 0 }; UInt16Spec smoothCC { 0, {0, 100}, kPermissiveUpperBound }; UInt8Spec curveCC { 0, {0, 255}, 0 }; UInt8Spec sustainCC { 64, {0, 127}, 0 }; -FloatSpec sustainThreshold { 1.0f, {0.0f, 127.0f}, kNormalizeMidi }; -BoolSpec checkSustain { true, {0, 1}, 0 }; -BoolSpec checkSostenuto { true, {0, 1}, 0 }; -FloatSpec loBPM { 0.0f, {0.0f, 500.0f}, 0 }; -FloatSpec hiBPM { 500.0f, {0.0f, 500.0f}, 0 }; +FloatSpec sustainThreshold { 1.0f, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; +BoolSpec checkSustain { true, {0, 1}, kEnforceBounds }; +BoolSpec checkSostenuto { true, {0, 1}, kEnforceBounds }; +FloatSpec loBPM { 0.0f, {0.0f, 500.0f}, kPermissiveBounds }; +FloatSpec hiBPM { 500.0f, {0.0f, 500.0f}, kPermissiveBounds }; UInt8Spec sequence { 1, {1, 100}, 0 }; -FloatSpec volume { 0.0f, {-144.0f, 48.0f}, 0 }; -FloatSpec volumeMod { 0.0f, {-144.0f, 48.0f}, 0 }; -FloatSpec amplitude { 100.0f, {0.0f, 10000.0f}, kNormalizePercent }; -FloatSpec amplitudeMod { 0.0f, {0.0f, 10000.0f}, 0 }; -FloatSpec pan { 0.0f, {-100.0f, 100.0f}, kNormalizePercent }; -FloatSpec panMod { 0.0f, {-200.0f, 200.0f}, 0 }; -FloatSpec position { 0.0f, {-100.0f, 100.0f}, kNormalizePercent }; -FloatSpec positionMod { 0.0f, {-200.0f, 200.0f}, 0 }; -FloatSpec width { 100.0f, {-100.0f, 100.0f}, kNormalizePercent }; -FloatSpec widthMod { 0.0f, {-200.0f, 200.0f}, 0 }; -FloatSpec crossfadeIn { 0.0f, {0.0f, 127.0f}, kNormalizeMidi }; -FloatSpec crossfadeInNorm { 0.0f, {0.0f, 1.0f}, 0 }; -FloatSpec crossfadeOut { 127.0f, {0.0f, 127.0f}, kNormalizeMidi }; -FloatSpec crossfadeOutNorm { 1.0f, {0.0f, 1.0f}, 0 }; -FloatSpec ampKeytrack { 0.0f, {-96.0f, 12.0f}, 0 }; -FloatSpec ampVeltrack { 100.0f, {-100.0f, 100.0f}, kNormalizePercent }; -FloatSpec ampVelcurve { 0.0f, {0.0f, 1.0f}, 0 }; -FloatSpec ampRandom { 0.0f, {-24.0f, 24.0f}, 0 }; -BoolSpec rtDead { false, {false, true}, 0 }; -FloatSpec rtDecay { 0.0f, {0.0f, 200.0f}, 0 }; -FloatSpec filterCutoff { 0.0f, {0.0f, 20000.0f}, kEnforceUpperBound }; -FloatSpec filterCutoffMod { 0.0f, {-12000.0f, 12000.0f}, 0 }; -FloatSpec filterResonance { 0.0f, {0.0f, 96.0f}, 0 }; -FloatSpec filterResonanceMod { 0.0f, {0.0f, 96.0f}, 0 }; -FloatSpec filterGain { 0.0f, {-96.0f, 96.0f}, 0 }; -FloatSpec filterGainMod { 0.0f, {-96.0f, 96.0f}, 0 }; -FloatSpec filterRandom { 0.0f, {-12000.0f, 12000.0f}, 0 }; -Int32Spec filterKeytrack { 0, {0, 1200}, 0 }; -Int32Spec filterVeltrack { 0, {-12000, 12000}, 0 }; -FloatSpec eqBandwidth { 1.0f, {0.001f, 4.0f}, 0 }; -FloatSpec eqBandwidthMod { 0.0f, {-4.0f, 4.0f}, 0 }; -FloatSpec eqFrequency { 0.0f, {0.0f, 20000.0f}, kEnforceUpperBound }; -FloatSpec eqFrequencyMod { 0.0f, {-20000.0f, 20000.0f}, 0 }; -FloatSpec eqGain { 0.0f, {-96.0f, 96.0f}, 0 }; -FloatSpec eqGainMod { 0.0f, {-96.0f, 96.0f}, 0 }; -FloatSpec eqVel2Frequency { 0.0f, {-30000.0f, 30000.0f}, 0 }; -FloatSpec eqVel2Gain { 0.0f, {-96.0f, 96.0f}, 0 }; -Int32Spec pitchKeytrack { 100, {-1200, 1200}, 0 }; -FloatSpec pitchRandom { 0.0f, {-12000.0f, 12000.0f}, 0 }; -Int32Spec pitchVeltrack { 0, {-12000, 12000}, 0 }; -Int32Spec transpose { 0, {-127, 127}, 0 }; -FloatSpec pitch { 0.0f, {-2400.0f, 2400.0f}, 0 }; -FloatSpec pitchMod { 0.0f, {-2400.0f, 2400.0f}, 0 }; -FloatSpec bendUp { 200.0f, {-12000.0f, 12000.0f}, 0 }; -FloatSpec bendDown { -200.0f, {-12000.0f, 12000.0f}, 0 }; -FloatSpec bendStep { 1.0f, {1.0f, 1200.0f}, 0 }; -FloatSpec ampLFODepth { 0.0f, {-10.0f, 10.0f}, 0 }; -FloatSpec pitchLFODepth { 0.0f, {-1200.0f, 1200.0f}, 0 }; -FloatSpec filLFODepth { 0.0f, {-1200.0f, 1200.0f}, 0 }; -FloatSpec lfoFreq { 0.0f, {0.0f, 100.0f}, 0 }; -FloatSpec lfoFreqMod { 0.0f, {-100.0f, 100.0f}, 0 }; -FloatSpec lfoBeats { 0.0f, {0.0f, 1000.0f}, 0 }; -FloatSpec lfoBeatsMod { 0.0f, {-1000.0f, 1000.0f}, 0 }; -FloatSpec lfoPhase { 0.0f, {0.0f, 1.0f}, kWrapPhase }; -FloatSpec lfoDelay { 0.0f, {0.0f, 30.0f}, 0 }; -FloatSpec lfoFade { 0.0f, {0.0f, 30.0f}, 0 }; -UInt32Spec lfoCount { 0, {0, 1000}, 0 }; -UInt32Spec lfoSteps { 0, {0, static_cast(config::maxLFOSteps)}, 0 }; -FloatSpec lfoStepX { 0.0f, {-100.0f, 100.0f}, kNormalizePercent }; +FloatSpec volume { 0.0f, {-144.0f, 48.0f}, kPermissiveBounds }; +FloatSpec volumeMod { 0.0f, {-144.0f, 48.0f}, kPermissiveBounds }; +FloatSpec amplitude { 100.0f, {0.0f, 10000.0f}, kNormalizePercent|kPermissiveBounds }; +FloatSpec amplitudeMod { 0.0f, {0.0f, 10000.0f}, kPermissiveBounds }; +FloatSpec pan { 0.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds }; +FloatSpec panMod { 0.0f, {-200.0f, 200.0f}, kPermissiveBounds }; +FloatSpec position { 0.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds }; +FloatSpec positionMod { 0.0f, {-200.0f, 200.0f}, kPermissiveBounds }; +FloatSpec width { 100.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds }; +FloatSpec widthMod { 0.0f, {-200.0f, 200.0f}, kPermissiveBounds }; +FloatSpec ampKeytrack { 0.0f, {-96.0f, 12.0f}, kPermissiveBounds }; +FloatSpec ampVeltrack { 100.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds }; +FloatSpec ampVelcurve { 0.0f, {0.0f, 1.0f}, kPermissiveBounds }; +FloatSpec ampRandom { 0.0f, {-24.0f, 24.0f}, kPermissiveBounds }; +BoolSpec rtDead { false, {false, true}, kEnforceBounds }; +FloatSpec rtDecay { 0.0f, {0.0f, 200.0f}, kEnforceLowerBound|kPermissiveUpperBound }; +FloatSpec filterCutoff { 0.0f, {0.0f, 20000.0f}, kPermissiveBounds }; +FloatSpec filterCutoffMod { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec filterResonance { 0.0f, {0.0f, 96.0f}, kPermissiveBounds }; +FloatSpec filterResonanceMod { 0.0f, {0.0f, 96.0f}, kPermissiveBounds }; +FloatSpec filterGain { 0.0f, {-96.0f, 96.0f}, kPermissiveBounds }; +FloatSpec filterGainMod { 0.0f, {-96.0f, 96.0f}, kPermissiveBounds }; +FloatSpec filterRandom { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec filterKeytrack { 0, {0, 1200}, kPermissiveBounds }; +FloatSpec filterVeltrack { 0, {-12000, 12000}, kPermissiveBounds }; +FloatSpec eqBandwidth { 1.0f, {0.001f, 4.0f}, kPermissiveBounds }; +FloatSpec eqBandwidthMod { 0.0f, {-4.0f, 4.0f}, kPermissiveBounds }; +FloatSpec eqFrequency { 0.0f, {0.0f, 20000.0f}, kPermissiveBounds }; +FloatSpec eqFrequencyMod { 0.0f, {-20000.0f, 20000.0f}, kPermissiveBounds }; +FloatSpec eqGain { 0.0f, {-96.0f, 96.0f}, kPermissiveBounds }; +FloatSpec eqGainMod { 0.0f, {-96.0f, 96.0f}, kPermissiveBounds }; +FloatSpec eqVel2Frequency { 0.0f, {-30000.0f, 30000.0f}, kPermissiveBounds }; +FloatSpec eqVel2Gain { 0.0f, {-96.0f, 96.0f}, kPermissiveBounds }; +FloatSpec pitchKeytrack { 100, {-1200, 1200}, kPermissiveBounds }; +FloatSpec pitchRandom { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec pitchVeltrack { 0, {-12000, 12000}, kPermissiveBounds }; +FloatSpec transpose { 0, {-127, 127}, kPermissiveBounds }; +FloatSpec pitch { 0.0f, {-2400.0f, 2400.0f}, kPermissiveBounds }; +FloatSpec pitchMod { 0.0f, {-2400.0f, 2400.0f}, kPermissiveBounds }; +FloatSpec bendUp { 200.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec bendDown { -200.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec bendStep { 1.0f, {1.0f, 1200.0f}, kEnforceLowerBound|kPermissiveBounds }; +FloatSpec ampLFODepth { 0.0f, {-10.0f, 10.0f}, kPermissiveBounds }; +FloatSpec pitchLFODepth { 0.0f, {-1200.0f, 1200.0f}, kPermissiveBounds }; +FloatSpec filLFODepth { 0.0f, {-1200.0f, 1200.0f}, kPermissiveBounds }; +FloatSpec lfoFreq { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec lfoFreqMod { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds }; +FloatSpec lfoBeats { 0.0f, {0.0f, 1000.0f}, kPermissiveBounds }; +FloatSpec lfoBeatsMod { 0.0f, {-1000.0f, 1000.0f}, kPermissiveBounds }; +FloatSpec lfoPhase { 0.0f, {0.0f, 1.0f}, kWrapPhase|kPermissiveBounds }; +FloatSpec lfoDelay { 0.0f, {0.0f, 30.0f}, kPermissiveBounds }; +FloatSpec lfoFade { 0.0f, {0.0f, 30.0f}, kPermissiveBounds }; +UInt32Spec lfoCount { 0, {0, 1000}, kEnforceLowerBound|kPermissiveUpperBound }; +UInt32Spec lfoSteps { 0, {0, static_cast(config::maxLFOSteps)}, kEnforceBounds }; +FloatSpec lfoStepX { 0.0f, {-100.0f, 100.0f}, kNormalizePercent|kPermissiveBounds }; ESpec lfoWave { LFOWave::Triangle, {LFOWave::Triangle, LFOWave::RandomSH}, 0 }; -FloatSpec lfoOffset { 0.0f, {-1.0f, 1.0f}, 0 }; -FloatSpec lfoRatio { 1.0f, {0.0f, 100.0f}, 0 }; -FloatSpec lfoScale { 1.0f, {0.0f, 1.0f}, 0 }; -FloatSpec egTime { 0.0f, {0.0f, 100.0f}, 0 }; -FloatSpec egRelease { 0.001f, {0.0f, 100.0f}, 0 }; -FloatSpec egTimeMod { 0.0f, {-100.0f, 100.0f}, 0 }; -FloatSpec egPercent { 0.0f, {0.0f, 100.0f}, 0 }; -FloatSpec egPercentMod { 0.0f, {-100.0f, 100.0f}, 0 }; -FloatSpec egDepth { 0.0f, {-12000.0f, 12000.0f}, 0 }; -FloatSpec egVel2Depth { 0.0f, {-12000.0f, 12000.0f}, 0 }; -BoolSpec flexEGAmpeg { false, {0, 1}, 0 }; -Int32Spec flexEGDynamic { 0, {0, 1}, 0 }; -Int32Spec flexEGSustain { 0, {0, 100}, 0 }; -FloatSpec flexEGPointTime { 0.0f, {0.0f, 100.0f}, 0 }; -FloatSpec flexEGPointLevel { 0.0f, {-1.0f, 1.0f}, 0 }; -FloatSpec flexEGPointShape { 0.0f, {-100.0f, 100.0f}, 0 }; -Int32Spec sampleQuality { 1, {1, 10}, 0 }; -Int32Spec octaveOffset { 0, {-10, 10}, 0 }; -Int32Spec noteOffset { 0, {-127, 127}, 0 }; +FloatSpec lfoOffset { 0.0f, {-1.0f, 1.0f}, kPermissiveBounds }; +FloatSpec lfoRatio { 1.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec lfoScale { 1.0f, {0.0f, 1.0f}, kPermissiveBounds }; +FloatSpec egTime { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec egRelease { 0.001f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec egTimeMod { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds }; +FloatSpec egPercent { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec egPercentMod { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds }; +FloatSpec egDepth { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +FloatSpec egVel2Depth { 0.0f, {-12000.0f, 12000.0f}, kPermissiveBounds }; +BoolSpec flexEGAmpeg { false, {0, 1}, kEnforceBounds }; +BoolSpec flexEGDynamic { 0, {0, 1}, kEnforceBounds }; +Int32Spec flexEGSustain { 0, {0, 100}, kEnforceLowerBound|kPermissiveUpperBound }; +FloatSpec flexEGPointTime { 0.0f, {0.0f, 100.0f}, kPermissiveBounds }; +FloatSpec flexEGPointLevel { 0.0f, {-1.0f, 1.0f}, kPermissiveBounds }; +FloatSpec flexEGPointShape { 0.0f, {-100.0f, 100.0f}, kPermissiveBounds }; +Int32Spec sampleQuality { 1, {0, 10}, 0 }; +Int32Spec octaveOffset { 0, {-10, 10}, kPermissiveBounds }; +Int32Spec noteOffset { 0, {-127, 127}, kPermissiveBounds }; + +// TODO: effect opcode flags FloatSpec effect { 0.0f, {0.0f, 100.0f}, kNormalizePercent }; FloatSpec effectPercent { 0.0f, {0.0f, 100.0f}, 0 }; ESpec apanWaveform { LFOWave::Triangle, {LFOWave::Triangle, LFOWave::Saw}, 0 }; @@ -174,6 +172,7 @@ FloatSpec lofiBitred { 0.0f, {0.0f, 100.0f}, 0 }; FloatSpec lofiDecim { 0.0f, {0.0f, 100.0f}, 0 }; FloatSpec rectify { 0.0f, {0.0f, 100.0f}, 0 }; UInt32Spec stringsNumber { maxStrings, {0, maxStrings}, 0 }; + ESpec trigger { Trigger::attack, {Trigger::attack, Trigger::release_key}, 0}; ESpec crossfadeCurve { CrossfadeCurve::power, {CrossfadeCurve::gain, CrossfadeCurve::power}, 0}; ESpec offMode { OffMode::fast, {OffMode::fast, OffMode::time}, 0}; diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index 8e0dec68..28dba5fa 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -88,11 +88,11 @@ struct OpcodeSpec if (!(flags & needsOperation)) return input; else if (flags & kNormalizePercent) - return static_cast(normalizePercents(input)); + return static_cast(input / U(100)); else if (flags & kNormalizeMidi) - return static_cast(normalize7Bits(input)); + return static_cast(input / U(127)); else if (flags & kNormalizeBend) - return static_cast(normalizeBend(input)); + return static_cast(input / U(8191)); else if (flags & kDb2Mag) return static_cast(db2mag(input)); else // just in case @@ -177,10 +177,6 @@ namespace Default extern const OpcodeSpec positionMod; extern const OpcodeSpec width; extern const OpcodeSpec widthMod; - extern const OpcodeSpec crossfadeIn; - extern const OpcodeSpec crossfadeInNorm; - extern const OpcodeSpec crossfadeOut; - extern const OpcodeSpec crossfadeOutNorm; extern const OpcodeSpec ampKeytrack; extern const OpcodeSpec ampVeltrack; extern const OpcodeSpec ampVelcurve; @@ -194,8 +190,8 @@ namespace Default extern const OpcodeSpec filterGain; extern const OpcodeSpec filterGainMod; extern const OpcodeSpec filterRandom; - extern const OpcodeSpec filterKeytrack; - extern const OpcodeSpec filterVeltrack; + extern const OpcodeSpec filterKeytrack; + extern const OpcodeSpec filterVeltrack; extern const OpcodeSpec eqBandwidth; extern const OpcodeSpec eqBandwidthMod; extern const OpcodeSpec eqFrequency; @@ -204,10 +200,10 @@ namespace Default extern const OpcodeSpec eqGainMod; extern const OpcodeSpec eqVel2Frequency; extern const OpcodeSpec eqVel2Gain; - extern const OpcodeSpec pitchKeytrack; + extern const OpcodeSpec pitchKeytrack; extern const OpcodeSpec pitchRandom; - extern const OpcodeSpec pitchVeltrack; - extern const OpcodeSpec transpose; + extern const OpcodeSpec pitchVeltrack; + extern const OpcodeSpec transpose; extern const OpcodeSpec pitch; extern const OpcodeSpec pitchMod; extern const OpcodeSpec bendUp; @@ -238,7 +234,7 @@ namespace Default extern const OpcodeSpec egDepth; extern const OpcodeSpec egVel2Depth; extern const OpcodeSpec flexEGAmpeg; - extern const OpcodeSpec flexEGDynamic; + extern const OpcodeSpec flexEGDynamic; extern const OpcodeSpec flexEGSustain; extern const OpcodeSpec flexEGPointTime; extern const OpcodeSpec flexEGPointLevel; diff --git a/src/sfizz/FilterDescription.h b/src/sfizz/FilterDescription.h index 612d1e58..4674477c 100644 --- a/src/sfizz/FilterDescription.h +++ b/src/sfizz/FilterDescription.h @@ -17,9 +17,9 @@ struct FilterDescription float cutoff { Default::filterCutoff }; float resonance { Default::filterCutoff }; float gain { Default::filterGain }; - int keytrack { Default::filterKeytrack }; + float keytrack { Default::filterKeytrack }; uint8_t keycenter { Default::key }; - int veltrack { Default::filterVeltrack }; + float veltrack { Default::filterVeltrack }; float random { Default::filterRandom }; FilterType type { FilterType::kFilterLpf2p }; }; diff --git a/src/sfizz/FilterPool.cpp b/src/sfizz/FilterPool.cpp index 42427a8c..75044278 100644 --- a/src/sfizz/FilterPool.cpp +++ b/src/sfizz/FilterPool.cpp @@ -35,7 +35,7 @@ void sfz::FilterHolder::setup(const Region& region, unsigned filterId, int noteN } const auto keytrack = description->keytrack * (noteNumber - description->keycenter); baseCutoff *= centsFactor(keytrack); - const auto veltrack = static_cast(description->veltrack) * velocity; + const auto veltrack = description->veltrack * velocity; baseCutoff *= centsFactor(veltrack); baseCutoff = Default::filterCutoff.bounds.clamp(baseCutoff); diff --git a/src/sfizz/FlexEGDescription.h b/src/sfizz/FlexEGDescription.h index 8ba22069..a4cc75ef 100644 --- a/src/sfizz/FlexEGDescription.h +++ b/src/sfizz/FlexEGDescription.h @@ -31,7 +31,7 @@ private: }; struct FlexEGDescription { - int dynamic { Default::flexEGDynamic }; // whether parameters can be modulated while EG runs + bool dynamic { Default::flexEGDynamic }; // whether parameters can be modulated while EG runs int sustain { Default::flexEGSustain }; // index of the sustain point (default to 0 in ARIA) std::vector points; // ARIA diff --git a/src/sfizz/LFO.cpp b/src/sfizz/LFO.cpp index 24aa8d6e..3b23dfb3 100644 --- a/src/sfizz/LFO.cpp +++ b/src/sfizz/LFO.cpp @@ -362,18 +362,14 @@ void LFO::generatePhase(unsigned nth, absl::Span phases) for (size_t i = 0; i < numFrames; ++i) { phases[i] = phase; float incr = ratio * samplePeriod * baseFreq; - phase += incr; - int numWraps = (int)phase; - phase -= numWraps; + phase = wrapPhase(phase + incr); } } else { for (size_t i = 0; i < numFrames; ++i) { phases[i] = phase; float incr = ratio * samplePeriod * (baseFreq + freqMod[i]); - phase += incr; - int numWraps = (int)phase; - phase -= numWraps; + phase = wrapPhase(phase + incr); } } } diff --git a/src/sfizz/ModifierHelpers.h b/src/sfizz/ModifierHelpers.h index f3061111..6a2e26b5 100644 --- a/src/sfizz/ModifierHelpers.h +++ b/src/sfizz/ModifierHelpers.h @@ -15,14 +15,14 @@ namespace sfz { /** * @brief Compute a crossfade in value with respect to a crossfade range (note, velocity, cc, ...) */ -template -float crossfadeIn(const sfz::Range& crossfadeRange, U value, CrossfadeCurve curve) +template +float crossfadeIn(const sfz::Range& crossfadeRange, U value, CrossfadeCurve curve) { if (value < crossfadeRange.getStart()) return 0.0f; const auto length = static_cast(crossfadeRange.length()); - if (length == 0.0f) + if (length <= 0.0f) return 1.0f; else if (value < crossfadeRange.getEnd()) { @@ -39,14 +39,14 @@ float crossfadeIn(const sfz::Range& crossfadeRange, U value, CrossfadeCurve c /** * @brief Compute a crossfade out value with respect to a crossfade range (note, velocity, cc, ...) */ -template -float crossfadeOut(const sfz::Range& crossfadeRange, U value, CrossfadeCurve curve) +template +float crossfadeOut(const sfz::Range& crossfadeRange, U value, CrossfadeCurve curve) { if (value > crossfadeRange.getEnd()) return 0.0f; const auto length = static_cast(crossfadeRange.length()); - if (length == 0.0f) + if (length <= 0.0f) return 1.0f; else if (value > crossfadeRange.getStart()) { diff --git a/src/sfizz/Opcode.cpp b/src/sfizz/Opcode.cpp index a09301da..fdf66adf 100644 --- a/src/sfizz/Opcode.cpp +++ b/src/sfizz/Opcode.cpp @@ -222,7 +222,8 @@ absl::optional readFloat_(OpcodeSpec spec, absl::string_view v) if (spec.flags & kWrapPhase) returnedValue = wrapPhase(returnedValue); - else if (returnedValue > static_cast(spec.bounds.getEnd())) { + + if (returnedValue > static_cast(spec.bounds.getEnd())) { if (spec.flags & kEnforceUpperBound) return spec.bounds.getEnd(); else if (!(spec.flags & kPermissiveUpperBound)) diff --git a/src/sfizz/Range.h b/src/sfizz/Range.h index 24785e9a..10b7ca68 100644 --- a/src/sfizz/Range.h +++ b/src/sfizz/Range.h @@ -32,6 +32,12 @@ public: { } + + constexpr Range(const Range& other) + : Range(other.getStart(), other.getEnd()) + { + } + constexpr Type getStart() const noexcept { return _start; } constexpr Type getEnd() const noexcept { return _end; } /** @@ -149,27 +155,27 @@ template using UncheckedRange = Range; } -template -bool operator==(const sfz::Range& lhs, const sfz::Range& rhs) +template +bool operator==(const sfz::Range& lhs, const sfz::Range& rhs) { return (lhs.getStart() == rhs.getStart()) && (lhs.getEnd() == rhs.getEnd()); } -template -bool operator!=(const sfz::Range& lhs, const sfz::Range& rhs) +template +bool operator!=(const sfz::Range& lhs, const sfz::Range& rhs) { return (lhs.getStart() != rhs.getStart()) || (lhs.getEnd() != rhs.getEnd()); } -template -bool operator==(const sfz::Range& lhs, const std::pair& rhs) +template +bool operator==(const sfz::Range& lhs, const std::pair& rhs) { return (lhs.getStart() == rhs.first) && (lhs.getEnd() == rhs.second); } -template -bool operator==(const std::pair& lhs, const sfz::Range& rhs) +template +bool operator==(const std::pair& lhs, const sfz::Range& rhs) { return rhs == lhs; } diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 02ed7293..061988de 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -194,13 +194,18 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode) keyRange.setStart(opcode.read(Default::loKey)); break; case hash("hikey"): - triggerOnNote = (opcode.value != "-1"); - keyRange.setEnd(opcode.read(Default::hiKey)); + { + absl::optional optValue = opcode.readOptional(Default::hiKey); + triggerOnNote = optValue != absl::nullopt; + uint8_t value = optValue.value_or(Default::hiKey); + keyRange.setEnd(value); + } break; case hash("key"): - triggerOnNote = (opcode.value != "-1"); { - auto value = opcode.read(Default::key); + absl::optional optValue = opcode.readOptional(Default::key); + triggerOnNote = optValue != absl::nullopt; + uint8_t value = optValue.value_or(Default::key); keyRange.setStart(value); keyRange.setEnd(value); pitchKeycenter = value; @@ -1491,7 +1496,7 @@ bool sfz::Region::registerNoteOn(int noteNumber, float velocity, float randValue velocity = midiState.getLastVelocity(); const bool velOk = velocityRange.containsWithEnd(velocity); - const bool randOk = randRange.contains(randValue) || (randValue == 1.0f && randRange.getEnd() == 1.0f); + const bool randOk = randRange.contains(randValue) || (randValue >= 1.0f && randRange.isValid() && randRange.getEnd() >= 1.0f); const bool firstLegatoNote = (trigger == Trigger::first && midiState.getActiveNotes() == 1); const bool attackTrigger = (trigger == Trigger::attack); const bool notFirstLegatoNote = (trigger == Trigger::legato && midiState.getActiveNotes() > 1); @@ -1513,7 +1518,7 @@ bool sfz::Region::registerNoteOff(int noteNumber, float velocity, float randValu const bool keyOk = keyRange.containsWithEnd(noteNumber); const bool velOk = velocityRange.containsWithEnd(velocity); - const bool randOk = randRange.contains(randValue); + const bool randOk = randRange.contains(randValue) || (randValue >= 1.0f && randRange.isValid() && randRange.getEnd() >= 1.0f); if (!(velOk && keyOk && randOk)) return false; @@ -1587,7 +1592,7 @@ float sfz::Region::getBasePitchVariation(float noteNumber, float velocity) const ASSERT(velocity >= 0.0f && velocity <= 1.0f); fast_real_distribution pitchDistribution { 0.0f, pitchRandom }; - auto pitchVariationInCents = pitchKeytrack * (noteNumber - pitchKeycenter); // note difference with pitch center + float pitchVariationInCents = pitchKeytrack * (noteNumber - pitchKeycenter); // note difference with pitch center pitchVariationInCents += pitch; // sample tuning pitchVariationInCents += config::centPerSemitone * transpose; // sample transpose pitchVariationInCents += velocity * pitchVeltrack; // track velocity diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 89e720ac..dec0c9c8 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -364,7 +364,7 @@ struct Region { uint32_t sampleEnd { Default::sampleEnd }; // end absl::optional sampleCount {}; // count absl::optional loopMode {}; // loopmode - Range loopRange { Default::loopStart, Default::loopEnd }; //loopstart and loopend + UncheckedRange loopRange { Default::loopStart, Default::loopEnd }; //loopstart and loopend absl::optional loopCount {}; // count float loopCrossfade { Default::loopCrossfade }; // loop_crossfade @@ -389,14 +389,14 @@ struct Region { bool rtDead { Default::rtDead }; // Region logic: key mapping - Range keyRange { Default::loKey, Default::hiKey }; //lokey, hikey and key - Range velocityRange { Default::loVel, Default::hiVel }; // hivel and lovel + UncheckedRange keyRange { Default::loKey, Default::hiKey }; //lokey, hikey and key + UncheckedRange velocityRange { Default::loVel, Default::hiVel }; // hivel and lovel // Region logic: MIDI conditions - Range bendRange { Default::loBend, Default::hiBend }; // hibend and lobend - CCMap> ccConditions {{ Default::loCC, Default::hiCC }}; + UncheckedRange bendRange { Default::loBend, Default::hiBend }; // hibend and lobend + CCMap> ccConditions {{ Default::loCC, Default::hiCC }}; absl::optional lastKeyswitch {}; // sw_last - absl::optional> lastKeyswitchRange {}; // sw_last + absl::optional> lastKeyswitchRange {}; // sw_last absl::optional keyswitchLabel {}; absl::optional upKeyswitch {}; // sw_up absl::optional downKeyswitch {}; // sw_down @@ -409,15 +409,15 @@ struct Region { float sustainThreshold { Default::sustainThreshold }; // sustain_cc // Region logic: internal conditions - Range aftertouchRange { Default::loChannelAftertouch, Default::hiChannelAftertouch }; // hichanaft and lochanaft - Range bpmRange { Default::loBPM, Default::hiBPM }; // hibpm and lobpm - Range randRange { Default::loNormalized, Default::hiNormalized }; // hirand and lorand + UncheckedRange aftertouchRange { Default::loChannelAftertouch, Default::hiChannelAftertouch }; // hichanaft and lochanaft + UncheckedRange bpmRange { Default::loBPM, Default::hiBPM }; // hibpm and lobpm + UncheckedRange randRange { Default::loNormalized, Default::hiNormalized }; // hirand and lorand uint8_t sequenceLength { Default::sequence }; // seq_length uint8_t sequencePosition { Default::sequence }; // seq_position // Region logic: triggers Trigger trigger { Default::trigger }; // trigger - CCMap> ccTriggers {{ Default::loCC, Default::hiCC }}; // on_loccN on_hiccN + CCMap> ccTriggers {{ Default::loCC, Default::hiCC }}; // on_loccN on_hiccN // Performance parameters: amplifier float volume { Default::volume }; // volume @@ -431,15 +431,15 @@ struct Region { std::vector> velocityPoints; // amp_velcurve_N absl::optional velCurve {}; float ampRandom { Default::ampRandom }; // amp_random - Range crossfadeKeyInRange { Default::crossfadeKeyInRange }; - Range crossfadeKeyOutRange { Default::crossfadeKeyOutRange }; - Range crossfadeVelInRange { Default::crossfadeVelInRange }; - Range crossfadeVelOutRange { Default::crossfadeVelOutRange }; + UncheckedRange crossfadeKeyInRange { Default::crossfadeKeyInRange }; + UncheckedRange crossfadeKeyOutRange { Default::crossfadeKeyOutRange }; + UncheckedRange crossfadeVelInRange { Default::crossfadeVelInRange }; + UncheckedRange crossfadeVelOutRange { Default::crossfadeVelOutRange }; CrossfadeCurve crossfadeKeyCurve { Default::crossfadeCurve }; CrossfadeCurve crossfadeVelCurve { Default::crossfadeCurve }; CrossfadeCurve crossfadeCCCurve { Default::crossfadeCurve }; - CCMap> crossfadeCCInRange { Default::crossfadeCCInRange }; // xfin_loccN xfin_hiccN - CCMap> crossfadeCCOutRange { Default::crossfadeCCOutRange }; // xfout_loccN xfout_hiccN + CCMap> crossfadeCCInRange { Default::crossfadeCCInRange }; // xfin_loccN xfin_hiccN + CCMap> crossfadeCCOutRange { Default::crossfadeCCOutRange }; // xfout_loccN xfout_hiccN float rtDecay { Default::rtDecay }; // rt_decay float globalAmplitude { 1.0 }; // global_amplitude @@ -456,10 +456,10 @@ struct Region { // Performance parameters: pitch uint8_t pitchKeycenter { Default::key }; // pitch_keycenter bool pitchKeycenterFromSample { false }; - int pitchKeytrack { Default::pitchKeytrack }; // pitch_keytrack + float pitchKeytrack { Default::pitchKeytrack }; // pitch_keytrack float pitchRandom { Default::pitchRandom }; // pitch_random - int pitchVeltrack { Default::pitchVeltrack }; // pitch_veltrack - int transpose { Default::transpose }; // transpose + float pitchVeltrack { Default::pitchVeltrack }; // pitch_veltrack + float transpose { Default::transpose }; // transpose float pitch { Default::pitch }; // tune float bendUp { Default::bendUp }; float bendDown { Default::bendDown }; diff --git a/src/sfizz/SfzHelpers.h b/src/sfizz/SfzHelpers.h index 1e63678d..b5fe5df2 100644 --- a/src/sfizz/SfzHelpers.h +++ b/src/sfizz/SfzHelpers.h @@ -168,7 +168,7 @@ constexpr float normalizeVelocity(T velocity) template constexpr float normalizePercents(T percentValue) { - return percentValue * 0.01f; + return percentValue / 100.0f; } /** diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index abdefb14..9e86c81e 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -598,6 +598,10 @@ void Synth::Impl::finalizeSfzLoad() if (region->loopRange.getEnd() == Default::loopEnd) region->loopRange.setEnd(region->sampleEnd); + // if range is invalid, disable the loop + if (!region->loopRange.isValid()) + region->loopMode = absl::nullopt; + if (fileInformation->numChannels == 2) region->hasStereoSample = true; @@ -750,7 +754,7 @@ void Synth::Impl::finalizeSfzLoad() // cache the set of keys assigned for (const RegionPtr& regionPtr : regions_) { - Range keyRange = regionPtr->keyRange; + UncheckedRange keyRange = regionPtr->keyRange; unsigned loKey = keyRange.getStart(); unsigned hiKey = keyRange.getEnd(); for (unsigned key = loKey; key <= hiKey; ++key) @@ -761,7 +765,7 @@ void Synth::Impl::finalizeSfzLoad() if (absl::optional sw = regionPtr->lastKeyswitch) { swLastSlots_.set(*sw); } - else if (absl::optional> swRange = regionPtr->lastKeyswitchRange) { + else if (absl::optional> swRange = regionPtr->lastKeyswitchRange) { unsigned loKey = swRange->getStart(); unsigned hiKey = swRange->getEnd(); for (unsigned key = loKey; key <= hiKey; ++key) diff --git a/tests/DirectRegionT.cpp b/tests/DirectRegionT.cpp index 2ae1d821..75c66453 100644 --- a/tests/DirectRegionT.cpp +++ b/tests/DirectRegionT.cpp @@ -23,7 +23,7 @@ TEST_CASE("[Direct Region Tests] amp_velcurve") region.parseOpcode({ "amp_velcurve_6", "0.4" }); REQUIRE(region.velocityPoints.back() == std::pair(6, 0.4f)); region.parseOpcode({ "amp_velcurve_127", "-1.0" }); - REQUIRE(region.velocityPoints.back() == std::pair(127, 0.0f)); + REQUIRE(region.velocityPoints.back() == std::pair(127, -1.0f)); region.parseOpcode({ "amp_velcurve_008", "0.3" }); REQUIRE(region.velocityPoints.back() == std::pair(8, 0.3f)); region.parseOpcode({ "amp_velcurve_064", "0.9" }); diff --git a/tests/RegionValuesT.cpp b/tests/RegionValuesT.cpp index c1944e55..6b5dfbf5 100644 --- a/tests/RegionValuesT.cpp +++ b/tests/RegionValuesT.cpp @@ -31,14 +31,12 @@ TEST_CASE("[Values] Delay") synth.dispatchMessage(client, 0, "/region0/delay", "", nullptr); synth.dispatchMessage(client, 0, "/region1/delay", "", nullptr); synth.dispatchMessage(client, 0, "/region2/delay", "", nullptr); - // TODO: activate for the new region parser ; ignore the second value - // synth.dispatchMessage(client, 0, "/region3/delay", "", nullptr); + synth.dispatchMessage(client, 0, "/region3/delay", "", nullptr); std::vector expected { "/region0/delay,f : { 0 }", "/region1/delay,f : { 1 }", - "/region2/delay,f : { 0 }", - // TODO: activate for the new region parser ; ignore the second value - // "/region3/delay,f : { 1 }", + "/region2/delay,f : { -1 }", + "/region3/delay,f : { -1 }", }; REQUIRE(messageList == expected); } @@ -54,12 +52,12 @@ TEST_CASE("[Values] Delay") synth.dispatchMessage(client, 0, "/region0/delay_random", "", nullptr); synth.dispatchMessage(client, 0, "/region1/delay_random", "", nullptr); synth.dispatchMessage(client, 0, "/region2/delay_random", "", nullptr); - // synth.dispatchMessage(client, 0, "/region3/delay_random", "", nullptr); + synth.dispatchMessage(client, 0, "/region3/delay_random", "", nullptr); std::vector expected { "/region0/delay_random,f : { 0 }", "/region1/delay_random,f : { 1 }", - "/region2/delay_random,f : { 0 }", - // "/region3/delay_random,f : { 1 }", + "/region2/delay_random,f : { -1 }", + "/region3/delay_random,f : { -1 }", }; REQUIRE(messageList == expected); } @@ -76,14 +74,13 @@ TEST_CASE("[Values] Delay") synth.dispatchMessage(client, 0, "/region1/delay_cc12", "", nullptr); synth.dispatchMessage(client, 0, "/region2/delay_cc12", "", nullptr); synth.dispatchMessage(client, 0, "/region3/delay_cc14", "", nullptr); - // TODO: activate for the new region parser ; ignore the second value - // synth.dispatchMessage(client, 0, "/region3/delay_cc12", "", nullptr); + synth.dispatchMessage(client, 0, "/region3/delay_cc12", "", nullptr); std::vector expected { "/region0/delay_cc12,f : { 0 }", "/region1/delay_cc12,f : { 1.5 }", - "/region2/delay_cc12,f : { 0 }", + "/region2/delay_cc12,f : { -1.5 }", "/region3/delay_cc14,f : { 3 }", - // "/region3/delay_cc12,f : { 2 }", + "/region3/delay_cc12,f : { -12 }", }; REQUIRE(messageList == expected); } @@ -131,14 +128,12 @@ TEST_CASE("[Values] Offset") synth.dispatchMessage(client, 0, "/region0/offset", "", nullptr); synth.dispatchMessage(client, 0, "/region1/offset", "", nullptr); synth.dispatchMessage(client, 0, "/region2/offset", "", nullptr); - // TODO: activate for the new region parser ; ignore the second value - // synth.dispatchMessage(client, 0, "/region3/offset", "", nullptr); + synth.dispatchMessage(client, 0, "/region3/offset", "", nullptr); std::vector expected { "/region0/offset,h : { 0 }", "/region1/offset,h : { 12 }", - "/region2/offset,h : { 0 }", - // TODO: activate for the new region parser ; ignore the second value - // "/region3/offset,f : { 12 }", + "/region2/offset,h : { -1 }", + "/region3/offset,h : { -1 }", }; REQUIRE(messageList == expected); } @@ -154,13 +149,12 @@ TEST_CASE("[Values] Offset") synth.dispatchMessage(client, 0, "/region0/offset_random", "", nullptr); synth.dispatchMessage(client, 0, "/region1/offset_random", "", nullptr); synth.dispatchMessage(client, 0, "/region2/offset_random", "", nullptr); - // TODO: activate for the new region parser ; ignore the second value - // synth.dispatchMessage(client, 0, "/region3/offset_random", "", nullptr); + synth.dispatchMessage(client, 0, "/region3/offset_random", "", nullptr); std::vector expected { "/region0/offset_random,h : { 0 }", "/region1/offset_random,h : { 1 }", - "/region2/offset_random,h : { 0 }", - // "/region3/offset_random,f : { 1 }", + "/region2/offset_random,h : { -1 }", + "/region3/offset_random,h : { -1 }", }; REQUIRE(messageList == expected); } @@ -177,14 +171,13 @@ TEST_CASE("[Values] Offset") synth.dispatchMessage(client, 0, "/region1/offset_cc12", "", nullptr); synth.dispatchMessage(client, 0, "/region2/offset_cc12", "", nullptr); synth.dispatchMessage(client, 0, "/region3/offset_cc14", "", nullptr); - // TODO: activate for the new region parser ; ignore the second value - // synth.dispatchMessage(client, 0, "/region3/offset_cc12", "", nullptr); + synth.dispatchMessage(client, 0, "/region3/offset_cc12", "", nullptr); std::vector expected { "/region0/offset_cc12,h : { 0 }", "/region1/offset_cc12,h : { 12 }", - "/region2/offset_cc12,h : { 0 }", + "/region2/offset_cc12,h : { -12 }", "/region3/offset_cc14,h : { 14 }", - // "/region3/offset_cc12,h : { 12 }", + "/region3/offset_cc12,h : { -12 }", }; REQUIRE(messageList == expected); } @@ -465,7 +458,7 @@ TEST_CASE("[Values] Off time") std::vector expected { "/region0/off_time,f : { 0.006 }", "/region1/off_time,f : { 0.1 }", - "/region2/off_time,f : { 0.006 }", + "/region2/off_time,f : { -1 }", }; REQUIRE(messageList == expected); } @@ -556,8 +549,8 @@ TEST_CASE("[Values] Velocity range") std::vector expected { "/region0/vel_range,ff : { 0, 1 }", "/region1/vel_range,ff : { 0.267717, 0.472441 }", - "/region2/vel_range,ff : { 0, 0.472441 }", - "/region3/vel_range,ff : { 0, 1 }", + "/region2/vel_range,ff : { -0.023622, 0.472441 }", + "/region3/vel_range,ff : { 0, -0.00787402 }", }; REQUIRE(messageList == expected); } @@ -582,7 +575,7 @@ TEST_CASE("[Values] Bend range") "/region0/bend_range,ff : { -1, 1 }", "/region1/bend_range,ff : { 0.108778, 0.24417 }", "/region2/bend_range,ff : { -0.108778, 0.108778 }", - "/region3/bend_range,ff : { -1, 1 }", + "/region3/bend_range,ff : { -1, -1.22085 }", }; REQUIRE(messageList == expected); } @@ -612,7 +605,7 @@ TEST_CASE("[Values] CC condition range") "/region1/cc_range1,ff : { 0, 0.425197 }", "/region2/cc_range1,ff : { 0, 0.425197 }", "/region2/cc_range2,ff : { 0.015748, 0.0787402 }", - "/region3/cc_range1,ff : { 0.0787402, 1 }", + "/region3/cc_range1,ff : { 0.0787402, -0.00787402 }", }; REQUIRE(messageList == expected); } @@ -635,7 +628,7 @@ TEST_CASE("[Values] CC condition range") "/region1/cc_range1,ff : { 0, 0.1 }", "/region2/cc_range1,ff : { 0, 0.1 }", "/region2/cc_range2,ff : { 0.1, 0.2 }", - "/region3/cc_range1,ff : { 0.1, 1 }", + "/region3/cc_range1,ff : { 0.1, -0.1 }", }; REQUIRE(messageList == expected); } @@ -658,7 +651,7 @@ TEST_CASE("[Values] CC condition range") "/region1/cc_range1,ff : { 0, 0.1 }", "/region2/cc_range1,ff : { 0, 0.1 }", "/region2/cc_range2,ff : { 0.1, 0.2 }", - "/region3/cc_range1,ff : { 0.1, 1 }", + "/region3/cc_range1,ff : { 0.1, -0.1 }", }; REQUIRE(messageList == expected); } @@ -871,9 +864,9 @@ TEST_CASE("[Values] Aftertouch range") std::vector expected { "/region0/chanaft_range,ff : { 0, 1 }", "/region1/chanaft_range,ff : { 0.267717, 0.472441 }", - "/region2/chanaft_range,ff : { 0, 0.472441 }", - "/region3/chanaft_range,ff : { 0.15748, 1 }", - "/region4/chanaft_range,ff : { 0.0787402, 0.0787402 }", + "/region2/chanaft_range,ff : { -0.023622, 0.472441 }", + "/region3/chanaft_range,ff : { 0.15748, -0.00787402 }", + "/region4/chanaft_range,ff : { 0.15748, 0.0787402 }", }; REQUIRE(messageList == expected); } @@ -899,9 +892,9 @@ TEST_CASE("[Values] BPM range") std::vector expected { "/region0/bpm_range,ff : { 0, 500 }", "/region1/bpm_range,ff : { 34.1, 60.2 }", - "/region2/bpm_range,ff : { 0, 60 }", - "/region3/bpm_range,ff : { 20, 500 }", - "/region4/bpm_range,ff : { 10, 10 }", + "/region2/bpm_range,ff : { -3, 60 }", + "/region3/bpm_range,ff : { 20, -1 }", + "/region4/bpm_range,ff : { 20, 10 }", }; REQUIRE(messageList == expected); } @@ -927,9 +920,9 @@ TEST_CASE("[Values] Rand range") std::vector expected { "/region0/rand_range,ff : { 0, 1 }", "/region1/rand_range,ff : { 0.2, 0.4 }", - "/region2/rand_range,ff : { 0, 0.4 }", - "/region3/rand_range,ff : { 0.2, 1 }", - "/region4/rand_range,ff : { 0.1, 0.1 }", + "/region2/rand_range,ff : { -0.1, 0.4 }", + "/region3/rand_range,ff : { 0.2, -0.1 }", + "/region4/rand_range,ff : { 0.2, 0.1 }", }; REQUIRE(messageList == expected); } @@ -1568,7 +1561,7 @@ TEST_CASE("[Values] Amp Veltrack") std::vector expected { "/region0/amp_veltrack,f : { 100 }", "/region1/amp_veltrack,f : { 10.1 }", - "/region2/amp_veltrack,f : { 100 }", + "/region2/amp_veltrack,f : { -132 }", }; REQUIRE(messageList == expected); } @@ -1623,7 +1616,7 @@ TEST_CASE("[Values] Crossfade key range") "/region1/xfin_key_range,ii : { 10, 40 }", "/region2/xfin_key_range,ii : { 60, 83 }", "/region3/xfin_key_range,ii : { 0, 40 }", - "/region4/xfin_key_range,ii : { 0, 0 }", + "/region4/xfin_key_range,ii : { 10, 0 }", }; REQUIRE(messageList == expected); } @@ -1646,7 +1639,7 @@ TEST_CASE("[Values] Crossfade key range") "/region0/xfout_key_range,ii : { 127, 127 }", "/region1/xfout_key_range,ii : { 10, 40 }", "/region2/xfout_key_range,ii : { 60, 83 }", - "/region3/xfout_key_range,ii : { 40, 40 }", + "/region3/xfout_key_range,ii : { 127, 40 }", "/region4/xfout_key_range,ii : { 10, 127 }", }; REQUIRE(messageList == expected); @@ -1676,8 +1669,8 @@ TEST_CASE("[Values] Crossfade velocity range") std::vector expected { "/region0/xfin_vel_range,ff : { 0, 0 }", "/region1/xfin_vel_range,ff : { 0.0787402, 0.314961 }", - "/region2/xfin_vel_range,ff : { 0, 0.314961 }", - "/region3/xfin_vel_range,ff : { 0, 0 }", + "/region2/xfin_vel_range,ff : { -0.0787402, 0.314961 }", + "/region3/xfin_vel_range,ff : { 0.0787402, 1.10236 }", }; REQUIRE(messageList == expected); } @@ -1697,8 +1690,8 @@ TEST_CASE("[Values] Crossfade velocity range") std::vector expected { "/region0/xfout_vel_range,ff : { 1, 1 }", "/region1/xfout_vel_range,ff : { 0.0787402, 0.314961 }", - "/region2/xfout_vel_range,ff : { 0.314961, 0.314961 }", - "/region3/xfout_vel_range,ff : { 0.0787402, 1 }", + "/region2/xfout_vel_range,ff : { -0.0787402, 0.314961 }", + "/region3/xfout_vel_range,ff : { 0.0787402, 1.10236 }", }; REQUIRE(messageList == expected); } @@ -1797,8 +1790,8 @@ TEST_CASE("[Values] Crossfade CC range") std::vector expected { "/region0/xfin_cc_range4,N : { }", "/region1/xfin_cc_range4,ff : { 0.0787402, 0.314961 }", - "/region2/xfin_cc_range4,ff : { 0, 0.314961 }", - "/region3/xfin_cc_range4,ff : { 0, 0 }", + "/region2/xfin_cc_range4,ff : { -0.0787402, 0.314961 }", + "/region3/xfin_cc_range4,ff : { 0.0787402, 1.10236 }", }; REQUIRE(messageList == expected); } @@ -1818,8 +1811,8 @@ TEST_CASE("[Values] Crossfade CC range") std::vector expected { "/region0/xfout_cc_range4,N : { }", "/region1/xfout_cc_range4,ff : { 0.0787402, 0.314961 }", - "/region2/xfout_cc_range4,ff : { 0.314961, 0.314961 }", - "/region3/xfout_cc_range4,ff : { 0.0787402, 1 }", + "/region2/xfout_cc_range4,ff : { -0.0787402, 0.314961 }", + "/region3/xfout_cc_range4,ff : { 0.0787402, 1.10236 }", }; REQUIRE(messageList == expected); } @@ -1977,8 +1970,8 @@ TEST_CASE("[Values] Transpose") "/region0/transpose,i : { 0 }", "/region1/transpose,i : { 10 }", "/region2/transpose,i : { -4 }", - "/region3/transpose,i : { 0 }", - "/region4/transpose,i : { 0 }", + "/region3/transpose,i : { -400 }", + "/region4/transpose,i : { 400 }", }; REQUIRE(messageList == expected); } @@ -2427,7 +2420,7 @@ TEST_CASE("[Values] Sustain low") std::vector expected { "/region0/sustain_lo,f : { 0.00787402 }", "/region1/sustain_lo,f : { 0.0787402 }", - "/region2/sustain_lo,f : { 0.00787402 }", + "/region2/sustain_lo,f : { -0.00787402 }", }; REQUIRE(messageList == expected); } @@ -2538,7 +2531,7 @@ TEST_CASE("[Values] Oscillator detune/mod depth") "/region2/oscillator_detune,f : { -1200.2 }", "/region0/oscillator_mod_depth,f : { 0 }", "/region3/oscillator_mod_depth,f : { 1564.75 }", - "/region4/oscillator_mod_depth,f : { 0 }", + "/region4/oscillator_mod_depth,f : { -2.2 }", }; REQUIRE(messageList == expected); } @@ -2903,14 +2896,14 @@ TEST_CASE("[Values] Filter value bounds") SECTION("Cutoff") { synth.loadSfzString(fs::current_path() / "tests/TestFiles/value_tests.sfz", R"( - sample=kick.wav cutoff=20000000 // Clamp the value + sample=kick.wav cutoff=100000 sample=kick.wav cutoff=50 cutoff=-100 )"); synth.dispatchMessage(client, 0, "/region0/filter0/cutoff", "", nullptr); synth.dispatchMessage(client, 0, "/region1/filter0/cutoff", "", nullptr); std::vector expected { - "/region0/filter0/cutoff,f : { 20000 }", - "/region1/filter0/cutoff,f : { 0 }", + "/region0/filter0/cutoff,f : { 100000 }", + "/region1/filter0/cutoff,f : { -100 }", }; REQUIRE(messageList == expected); } @@ -2922,7 +2915,7 @@ TEST_CASE("[Values] Filter value bounds") )"); synth.dispatchMessage(client, 0, "/region0/filter0/resonance", "", nullptr); std::vector expected { - "/region0/filter0/resonance,f : { 0 }", + "/region0/filter0/resonance,f : { -5 }", }; REQUIRE(messageList == expected); } @@ -3109,14 +3102,14 @@ TEST_CASE("[Values] EQ value bounds") SECTION("Frequency") { synth.loadSfzString(fs::current_path() / "tests/TestFiles/value_tests.sfz", R"( - sample=kick.wav eq1_freq=20000000 // Clamp the value + sample=kick.wav eq1_freq=100000 sample=kick.wav eq1_freq=50 eq1_freq=-100 )"); synth.dispatchMessage(client, 0, "/region0/eq0/frequency", "", nullptr); synth.dispatchMessage(client, 0, "/region1/eq0/frequency", "", nullptr); std::vector expected { - "/region0/eq0/frequency,f : { 20000 }", - "/region1/eq0/frequency,f : { 50 }", + "/region0/eq0/frequency,f : { 100000 }", + "/region1/eq0/frequency,f : { -100 }", }; REQUIRE(messageList == expected); } @@ -3128,7 +3121,7 @@ TEST_CASE("[Values] EQ value bounds") )"); synth.dispatchMessage(client, 0, "/region0/eq0/bandwidth", "", nullptr); std::vector expected { - "/region0/eq0/bandwidth,f : { 1 }", + "/region0/eq0/bandwidth,f : { -5 }", }; REQUIRE(messageList == expected); } diff --git a/tests/TestHelpers.h b/tests/TestHelpers.h index feb6823f..23e83a6a 100644 --- a/tests/TestHelpers.h +++ b/tests/TestHelpers.h @@ -33,8 +33,8 @@ private: sfz::ModKey target_; }; -template -void almostEqualRanges(const sfz::Range& lhs, const sfz::Range& rhs) +template +void almostEqualRanges(const Range& lhs, const Range& rhs) { REQUIRE(lhs.getStart() == Approx(rhs.getStart())); REQUIRE(lhs.getEnd() == Approx(rhs.getEnd()));