Merge pull request #855 from paulfd/discrete-cc-gap

Convert discrete CC conditions without gaps
This commit is contained in:
Paul Ferrand 2021-04-27 10:47:27 +02:00 committed by GitHub
commit 7342402431
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 27 additions and 13 deletions

View file

@ -49,7 +49,11 @@ UInt8Spec key { 60, {0, 127}, kCanBeNote };
UInt8Spec loKey { 0, {0, 127}, kCanBeNote }; UInt8Spec loKey { 0, {0, 127}, kCanBeNote };
UInt8Spec hiKey { 127, {0, 127}, kCanBeNote }; UInt8Spec hiKey { 127, {0, 127}, kCanBeNote };
FloatSpec loCC { 0, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; FloatSpec loCC { 0, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds };
FloatSpec hiCC { 127, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; FloatSpec hiCC { 127, {0.0f, 127.0f}, kNormalizeMidi|kFillGap|kPermissiveBounds };
FloatSpec xfoutLoCC { 127.0f, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds };
FloatSpec xfoutHiCC { 127.0f, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds };
FloatSpec xfinLoCC { 0.0f, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds };
FloatSpec xfinHiCC { 0.0f, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds };
FloatSpec loVel { 0, {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 hiVel { 127, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds };
FloatSpec loChannelAftertouch { 0, {0, 127}, kNormalizeMidi|kPermissiveBounds }; FloatSpec loChannelAftertouch { 0, {0, 127}, kNormalizeMidi|kPermissiveBounds };

View file

@ -60,6 +60,7 @@ enum OpcodeFlags : int {
kNormalizeBend = 1 << 7, kNormalizeBend = 1 << 7,
kWrapPhase = 1 << 8, kWrapPhase = 1 << 8,
kDb2Mag = 1 << 9, kDb2Mag = 1 << 9,
kFillGap = 1 << 10, // Fill in the gap when converting from discrete midi values to float, so that 13 is actually 13.999999...
}; };
template<class T> template<class T>
@ -97,8 +98,12 @@ struct OpcodeSpec
return input; return input;
else if (flags & kNormalizePercent) else if (flags & kNormalizePercent)
return static_cast<U>(input / U(100)); return static_cast<U>(input / U(100));
else if (flags & kNormalizeMidi) else if (flags & kNormalizeMidi) {
return static_cast<U>(input / U(127)); if ((flags & kFillGap) && (input <= U(126)) && input >= 0)
return std::nextafter(static_cast<U>((input + 1.0f) / U(127)), 0.0f);
else
return static_cast<U>(input / U(127));
}
else if (flags & kNormalizeBend) else if (flags & kNormalizeBend)
return static_cast<U>(input / U(8191)); return static_cast<U>(input / U(8191));
else if (flags & kDb2Mag) else if (flags & kDb2Mag)
@ -159,6 +164,10 @@ namespace Default
extern const OpcodeSpec<float> hiVel; extern const OpcodeSpec<float> hiVel;
extern const OpcodeSpec<float> loCC; extern const OpcodeSpec<float> loCC;
extern const OpcodeSpec<float> hiCC; extern const OpcodeSpec<float> hiCC;
extern const OpcodeSpec<float> xfoutLoCC;
extern const OpcodeSpec<float> xfoutHiCC;
extern const OpcodeSpec<float> xfinHiCC;
extern const OpcodeSpec<float> xfinLoCC;
extern const OpcodeSpec<float> loBend; extern const OpcodeSpec<float> loBend;
extern const OpcodeSpec<float> hiBend; extern const OpcodeSpec<float> hiBend;
extern const OpcodeSpec<float> loNormalized; extern const OpcodeSpec<float> loNormalized;

View file

@ -495,28 +495,28 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode, bool cleanOpcode)
if (opcode.parameters.back() >= config::numCCs) if (opcode.parameters.back() >= config::numCCs)
return false; return false;
crossfadeCCInRange[opcode.parameters.back()].setStart( crossfadeCCInRange[opcode.parameters.back()].setStart(
opcode.read(Default::loCC) opcode.read(Default::xfinLoCC)
); );
break; break;
case hash("xfin_hicc&"): case hash("xfin_hicc&"):
if (opcode.parameters.back() >= config::numCCs) if (opcode.parameters.back() >= config::numCCs)
return false; return false;
crossfadeCCInRange[opcode.parameters.back()].setEnd( crossfadeCCInRange[opcode.parameters.back()].setEnd(
opcode.read(Default::loCC) // loCC for the proper default opcode.read(Default::xfinHiCC)
); );
break; break;
case hash("xfout_locc&"): case hash("xfout_locc&"):
if (opcode.parameters.back() >= config::numCCs) if (opcode.parameters.back() >= config::numCCs)
return false; return false;
crossfadeCCOutRange[opcode.parameters.back()].setStart( crossfadeCCOutRange[opcode.parameters.back()].setStart(
opcode.read(Default::hiCC) // hiCC for the proper default opcode.read(Default::xfoutLoCC)
); );
break; break;
case hash("xfout_hicc&"): case hash("xfout_hicc&"):
if (opcode.parameters.back() >= config::numCCs) if (opcode.parameters.back() >= config::numCCs)
return false; return false;
crossfadeCCOutRange[opcode.parameters.back()].setEnd( crossfadeCCOutRange[opcode.parameters.back()].setEnd(
opcode.read(Default::hiCC) opcode.read(Default::xfoutHiCC)
); );
break; break;
case hash("xf_cccurve"): case hash("xf_cccurve"):

View file

@ -246,7 +246,8 @@ TEST_CASE("[Files] Pizz basic")
REQUIRE(synth.getRegionView(i)->keyRange == Range<uint8_t>(12, 22)); REQUIRE(synth.getRegionView(i)->keyRange == Range<uint8_t>(12, 22));
almostEqualRanges(synth.getRegionView(i)->velocityRange, { 97_norm, 127_norm }); almostEqualRanges(synth.getRegionView(i)->velocityRange, { 97_norm, 127_norm });
REQUIRE(synth.getRegionView(i)->pitchKeycenter == 21); REQUIRE(synth.getRegionView(i)->pitchKeycenter == 21);
almostEqualRanges(synth.getRegionView(i)->ccConditions.getWithDefault(107), { 0_norm, 13_norm }); almostEqualRanges(synth.getRegionView(i)->ccConditions.getWithDefault(107),
{ 0_norm, std::nextafter(14_norm, 0.0f) }); // Fill in the gap from 13_norm to "almost 14_norm"
} }
almostEqualRanges(synth.getRegionView(0)->randRange, { 0, 0.25 }); almostEqualRanges(synth.getRegionView(0)->randRange, { 0, 0.25 });
almostEqualRanges(synth.getRegionView(1)->randRange, { 0.25, 0.5 }); almostEqualRanges(synth.getRegionView(1)->randRange, { 0.25, 0.5 });

View file

@ -653,9 +653,9 @@ TEST_CASE("[Values] CC condition range")
synth.dispatchMessage(client, 0, "/region3/cc_range1", "", nullptr); synth.dispatchMessage(client, 0, "/region3/cc_range1", "", nullptr);
std::vector<std::string> expected { std::vector<std::string> expected {
"/region0/cc_range1,ff : { 0, 1 }", "/region0/cc_range1,ff : { 0, 1 }",
"/region1/cc_range1,ff : { 0, 0.425197 }", "/region1/cc_range1,ff : { 0, 0.433071 }",
"/region2/cc_range1,ff : { 0, 0.425197 }", "/region2/cc_range1,ff : { 0, 0.433071 }",
"/region2/cc_range2,ff : { 0.015748, 0.0787402 }", "/region2/cc_range2,ff : { 0.015748, 0.0866142 }",
"/region3/cc_range1,ff : { 0.0787402, -0.00787402 }", "/region3/cc_range1,ff : { 0.0787402, -0.00787402 }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
@ -1123,8 +1123,8 @@ TEST_CASE("[Values] Start on cc range")
"/region0/start_cc_range1,N : { }", "/region0/start_cc_range1,N : { }",
"/region0/start_cc_range2,N : { }", "/region0/start_cc_range2,N : { }",
"/region1/start_cc_range1,ff : { 0.11811, 1 }", "/region1/start_cc_range1,ff : { 0.11811, 1 }",
"/region2/start_cc_range1,ff : { 0, 0.661417 }", "/region2/start_cc_range1,ff : { 0, 0.669291 }",
"/region3/start_cc_range1,ff : { 0.11811, 0.661417 }", "/region3/start_cc_range1,ff : { 0.11811, 0.669291 }",
"/region4/start_cc_range2,ff : { 0.1, 1 }", "/region4/start_cc_range2,ff : { 0.1, 1 }",
"/region5/start_cc_range2,ff : { 0, 0.4 }", "/region5/start_cc_range2,ff : { 0, 0.4 }",
"/region6/start_cc_range2,ff : { 0.1, 0.4 }", "/region6/start_cc_range2,ff : { 0.1, 0.4 }",