From 32682380c5114353d2a5ada0d0ac7bad2a44da53 Mon Sep 17 00:00:00 2001 From: Paul Fd Date: Sun, 25 Apr 2021 00:28:58 +0200 Subject: [PATCH] Convert discrete CC conditions without gaps Something like `hicc1=13` is actually translated to float as `13.999999999/127` instead of `13/127`. --- src/sfizz/Defaults.cpp | 6 +++++- src/sfizz/Defaults.h | 13 +++++++++++-- src/sfizz/Region.cpp | 8 ++++---- tests/FilesT.cpp | 3 ++- tests/RegionValuesT.cpp | 10 +++++----- 5 files changed, 27 insertions(+), 13 deletions(-) diff --git a/src/sfizz/Defaults.cpp b/src/sfizz/Defaults.cpp index 95d13145..dece22d5 100644 --- a/src/sfizz/Defaults.cpp +++ b/src/sfizz/Defaults.cpp @@ -49,7 +49,11 @@ 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|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 hiVel { 127, {0.0f, 127.0f}, kNormalizeMidi|kPermissiveBounds }; FloatSpec loChannelAftertouch { 0, {0, 127}, kNormalizeMidi|kPermissiveBounds }; diff --git a/src/sfizz/Defaults.h b/src/sfizz/Defaults.h index bee56977..7b7183ce 100644 --- a/src/sfizz/Defaults.h +++ b/src/sfizz/Defaults.h @@ -60,6 +60,7 @@ enum OpcodeFlags : int { kNormalizeBend = 1 << 7, kWrapPhase = 1 << 8, 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 @@ -97,8 +98,12 @@ struct OpcodeSpec return input; else if (flags & kNormalizePercent) return static_cast(input / U(100)); - else if (flags & kNormalizeMidi) - return static_cast(input / U(127)); + else if (flags & kNormalizeMidi) { + if ((flags & kFillGap) && (input <= U(126)) && input >= 0) + return std::nextafter(static_cast((input + 1.0f) / U(127)), 0.0f); + else + return static_cast(input / U(127)); + } else if (flags & kNormalizeBend) return static_cast(input / U(8191)); else if (flags & kDb2Mag) @@ -159,6 +164,10 @@ namespace Default extern const OpcodeSpec hiVel; extern const OpcodeSpec loCC; extern const OpcodeSpec hiCC; + extern const OpcodeSpec xfoutLoCC; + extern const OpcodeSpec xfoutHiCC; + extern const OpcodeSpec xfinHiCC; + extern const OpcodeSpec xfinLoCC; extern const OpcodeSpec loBend; extern const OpcodeSpec hiBend; extern const OpcodeSpec loNormalized; diff --git a/src/sfizz/Region.cpp b/src/sfizz/Region.cpp index 05e73b67..481cf0c8 100644 --- a/src/sfizz/Region.cpp +++ b/src/sfizz/Region.cpp @@ -495,28 +495,28 @@ bool sfz::Region::parseOpcode(const Opcode& rawOpcode, bool cleanOpcode) if (opcode.parameters.back() >= config::numCCs) return false; crossfadeCCInRange[opcode.parameters.back()].setStart( - opcode.read(Default::loCC) + opcode.read(Default::xfinLoCC) ); break; case hash("xfin_hicc&"): if (opcode.parameters.back() >= config::numCCs) return false; crossfadeCCInRange[opcode.parameters.back()].setEnd( - opcode.read(Default::loCC) // loCC for the proper default + opcode.read(Default::xfinHiCC) ); break; case hash("xfout_locc&"): if (opcode.parameters.back() >= config::numCCs) return false; crossfadeCCOutRange[opcode.parameters.back()].setStart( - opcode.read(Default::hiCC) // hiCC for the proper default + opcode.read(Default::xfoutLoCC) ); break; case hash("xfout_hicc&"): if (opcode.parameters.back() >= config::numCCs) return false; crossfadeCCOutRange[opcode.parameters.back()].setEnd( - opcode.read(Default::hiCC) + opcode.read(Default::xfoutHiCC) ); break; case hash("xf_cccurve"): diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index c1d568b2..8ea1c0e5 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -245,7 +245,8 @@ TEST_CASE("[Files] Pizz basic") REQUIRE(synth.getRegionView(i)->keyRange == Range(12, 22)); almostEqualRanges(synth.getRegionView(i)->velocityRange, { 97_norm, 127_norm }); 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(1)->randRange, { 0.25, 0.5 }); diff --git a/tests/RegionValuesT.cpp b/tests/RegionValuesT.cpp index 9628d3a6..d9402d9d 100644 --- a/tests/RegionValuesT.cpp +++ b/tests/RegionValuesT.cpp @@ -653,9 +653,9 @@ TEST_CASE("[Values] CC condition range") synth.dispatchMessage(client, 0, "/region3/cc_range1", "", nullptr); std::vector expected { "/region0/cc_range1,ff : { 0, 1 }", - "/region1/cc_range1,ff : { 0, 0.425197 }", - "/region2/cc_range1,ff : { 0, 0.425197 }", - "/region2/cc_range2,ff : { 0.015748, 0.0787402 }", + "/region1/cc_range1,ff : { 0, 0.433071 }", + "/region2/cc_range1,ff : { 0, 0.433071 }", + "/region2/cc_range2,ff : { 0.015748, 0.0866142 }", "/region3/cc_range1,ff : { 0.0787402, -0.00787402 }", }; REQUIRE(messageList == expected); @@ -1123,8 +1123,8 @@ TEST_CASE("[Values] Start on cc range") "/region0/start_cc_range1,N : { }", "/region0/start_cc_range2,N : { }", "/region1/start_cc_range1,ff : { 0.11811, 1 }", - "/region2/start_cc_range1,ff : { 0, 0.661417 }", - "/region3/start_cc_range1,ff : { 0.11811, 0.661417 }", + "/region2/start_cc_range1,ff : { 0, 0.669291 }", + "/region3/start_cc_range1,ff : { 0.11811, 0.669291 }", "/region4/start_cc_range2,ff : { 0.1, 1 }", "/region5/start_cc_range2,ff : { 0, 0.4 }", "/region6/start_cc_range2,ff : { 0.1, 0.4 }",