Make the aftertouch opcode normalized

This commit is contained in:
Jean Pierre Cimalando 2021-03-19 14:26:47 +01:00
parent 8672a5b5f7
commit 4dc429a572
9 changed files with 37 additions and 24 deletions

View file

@ -49,8 +49,8 @@ FloatSpec loCC { 0, {0.0f, 127.0f}, kNormalizeMidi };
FloatSpec hiCC { 127, {0.0f, 127.0f}, kNormalizeMidi }; FloatSpec hiCC { 127, {0.0f, 127.0f}, kNormalizeMidi };
FloatSpec loVel { 0, {0.0f, 127.0f}, kNormalizeMidi }; FloatSpec loVel { 0, {0.0f, 127.0f}, kNormalizeMidi };
FloatSpec hiVel { 127, {0.0f, 127.0f}, kNormalizeMidi }; FloatSpec hiVel { 127, {0.0f, 127.0f}, kNormalizeMidi };
UInt8Spec loChannelAftertouch { 0, {0, 127}, 0 }; FloatSpec loChannelAftertouch { 0, {0, 127}, kNormalizeMidi };
UInt8Spec hiChannelAftertouch { 127, {0, 127}, 0 }; FloatSpec hiChannelAftertouch { 127, {0, 127}, kNormalizeMidi };
FloatSpec loBend { -8192, {-8192.0f, 8192.0f}, kNormalizeBend }; FloatSpec loBend { -8192, {-8192.0f, 8192.0f}, kNormalizeBend };
FloatSpec hiBend { 8192, {-8192.0f, 8192.0f}, kNormalizeBend }; FloatSpec hiBend { 8192, {-8192.0f, 8192.0f}, kNormalizeBend };
FloatSpec loNormalized { 0.0f, {0.0f, 1.0f}, 0 }; FloatSpec loNormalized { 0.0f, {0.0f, 1.0f}, 0 };

View file

@ -153,8 +153,8 @@ namespace Default
extern const OpcodeSpec<float> hiNormalized; extern const OpcodeSpec<float> hiNormalized;
extern const OpcodeSpec<float> loBipolar; extern const OpcodeSpec<float> loBipolar;
extern const OpcodeSpec<float> hiBipolar; extern const OpcodeSpec<float> hiBipolar;
extern const OpcodeSpec<uint8_t> loChannelAftertouch; extern const OpcodeSpec<float> loChannelAftertouch;
extern const OpcodeSpec<uint8_t> hiChannelAftertouch; extern const OpcodeSpec<float> hiChannelAftertouch;
extern const OpcodeSpec<uint16_t> ccNumber; extern const OpcodeSpec<uint16_t> ccNumber;
extern const OpcodeSpec<uint8_t> curveCC; extern const OpcodeSpec<uint8_t> curveCC;
extern const OpcodeSpec<uint8_t> smoothCC; extern const OpcodeSpec<uint8_t> smoothCC;

View file

@ -1565,7 +1565,7 @@ void sfz::Region::registerPitchWheel(float pitch) noexcept
pitchSwitched = false; pitchSwitched = false;
} }
void sfz::Region::registerAftertouch(uint8_t aftertouch) noexcept void sfz::Region::registerAftertouch(float aftertouch) noexcept
{ {
if (aftertouchRange.containsWithEnd(aftertouch)) if (aftertouchRange.containsWithEnd(aftertouch))
aftertouchSwitched = true; aftertouchSwitched = true;

View file

@ -150,7 +150,7 @@ struct Region {
* *
* @param aftertouch * @param aftertouch
*/ */
void registerAftertouch(uint8_t aftertouch) noexcept; void registerAftertouch(float aftertouch) noexcept;
/** /**
* @brief Register tempo * @brief Register tempo
* *
@ -409,7 +409,7 @@ struct Region {
float sustainThreshold { Default::sustainThreshold }; // sustain_cc float sustainThreshold { Default::sustainThreshold }; // sustain_cc
// Region logic: internal conditions // Region logic: internal conditions
Range<uint8_t> aftertouchRange { Default::loChannelAftertouch, Default::hiChannelAftertouch }; // hichanaft and lochanaft Range<float> aftertouchRange { Default::loChannelAftertouch, Default::hiChannelAftertouch }; // hichanaft and lochanaft
Range<float> bpmRange { Default::loBPM, Default::hiBPM }; // hibpm and lobpm Range<float> bpmRange { Default::loBPM, Default::hiBPM }; // hibpm and lobpm
Range<float> randRange { Default::loNormalized, Default::hiNormalized }; // hirand and lorand Range<float> randRange { Default::loNormalized, Default::hiNormalized }; // hirand and lorand
uint8_t sequenceLength { Default::sequence }; // seq_length uint8_t sequenceLength { Default::sequence }; // seq_length

View file

@ -1257,22 +1257,27 @@ void Synth::pitchWheel(int delay, int pitch) noexcept
} }
void Synth::aftertouch(int delay, uint8_t aftertouch) noexcept void Synth::aftertouch(int delay, uint8_t aftertouch) noexcept
{
const float normalizedAftertouch = normalize7Bits(aftertouch);
hdAftertouch(delay, normalizedAftertouch);
}
void Synth::hdAftertouch(int delay, float normAftertouch) noexcept
{ {
Impl& impl = *impl_; Impl& impl = *impl_;
ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration }; ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration };
const auto normalizedAftertouch = normalize7Bits(aftertouch); impl.resources_.midiState.channelAftertouchEvent(delay, normAftertouch);
impl.resources_.midiState.channelAftertouchEvent(delay, normalizedAftertouch);
for (auto& region : impl.regions_) { for (auto& region : impl.regions_) {
region->registerAftertouch(aftertouch); region->registerAftertouch(normAftertouch);
} }
for (auto& voice : impl.voiceManager_) { for (auto& voice : impl.voiceManager_) {
voice.registerAftertouch(delay, aftertouch); voice.registerAftertouch(delay, normAftertouch);
} }
impl.performHdcc(delay, ExtendedCCs::channelAftertouch, normalizedAftertouch, false); impl.performHdcc(delay, ExtendedCCs::channelAftertouch, normAftertouch, false);
} }
void Synth::tempo(int delay, float secondsPerBeat) noexcept void Synth::tempo(int delay, float secondsPerBeat) noexcept

View file

@ -389,6 +389,14 @@ public:
* @param aftertouch the aftertouch value * @param aftertouch the aftertouch value
*/ */
void aftertouch(int delay, uint8_t aftertouch) noexcept; void aftertouch(int delay, uint8_t aftertouch) noexcept;
/**
* @brief Send a high precision aftertouch event to the synth
*
* @param delay the delay at which the event occurs; this should be lower than the size of
* the block in the next call to renderBlock().
* @param normAftertouch the normalized aftertouch value, in domain 0 to 1
*/
void hdAftertouch(int delay, float normAftertouch) noexcept;
/** /**
* @brief Send a tempo event to the synth * @brief Send a tempo event to the synth
* *

View file

@ -374,9 +374,9 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co
MATCH("/region&/chanaft_range", "") { MATCH("/region&/chanaft_range", "") {
GET_REGION_OR_BREAK(indices[0]) GET_REGION_OR_BREAK(indices[0])
sfizz_arg_t args[2]; sfizz_arg_t args[2];
args[0].i = region.aftertouchRange.getStart(); args[0].f = region.aftertouchRange.getStart();
args[1].i = region.aftertouchRange.getEnd(); args[1].f = region.aftertouchRange.getEnd();
client.receive(delay, path, "ii", args); client.receive(delay, path, "ff", args);
} break; } break;
MATCH("/region&/bpm_range", "") { MATCH("/region&/bpm_range", "") {

View file

@ -90,13 +90,13 @@ TEST_CASE("Region activation", "Region tests")
{ {
region.parseOpcode({ "lochanaft", "56" }); region.parseOpcode({ "lochanaft", "56" });
region.parseOpcode({ "hichanaft", "68" }); region.parseOpcode({ "hichanaft", "68" });
region.registerAftertouch(0); region.registerAftertouch(sfz::normalize7Bits(0));
REQUIRE(!region.isSwitchedOn()); REQUIRE(!region.isSwitchedOn());
region.registerAftertouch(56); region.registerAftertouch(sfz::normalize7Bits(56));
REQUIRE(region.isSwitchedOn()); REQUIRE(region.isSwitchedOn());
region.registerAftertouch(68); region.registerAftertouch(sfz::normalize7Bits(68));
REQUIRE(region.isSwitchedOn()); REQUIRE(region.isSwitchedOn());
region.registerAftertouch(98); region.registerAftertouch(sfz::normalize7Bits(98));
REQUIRE(!region.isSwitchedOn()); REQUIRE(!region.isSwitchedOn());
} }

View file

@ -869,11 +869,11 @@ TEST_CASE("[Values] Aftertouch range")
synth.dispatchMessage(client, 0, "/region3/chanaft_range", "", nullptr); synth.dispatchMessage(client, 0, "/region3/chanaft_range", "", nullptr);
synth.dispatchMessage(client, 0, "/region4/chanaft_range", "", nullptr); synth.dispatchMessage(client, 0, "/region4/chanaft_range", "", nullptr);
std::vector<std::string> expected { std::vector<std::string> expected {
"/region0/chanaft_range,ii : { 0, 127 }", "/region0/chanaft_range,ff : { 0, 1 }",
"/region1/chanaft_range,ii : { 34, 60 }", "/region1/chanaft_range,ff : { 0.267717, 0.472441 }",
"/region2/chanaft_range,ii : { 0, 60 }", "/region2/chanaft_range,ff : { 0, 0.472441 }",
"/region3/chanaft_range,ii : { 20, 127 }", "/region3/chanaft_range,ff : { 0.15748, 1 }",
"/region4/chanaft_range,ii : { 10, 10 }", "/region4/chanaft_range,ff : { 0.0787402, 0.0787402 }",
}; };
REQUIRE(messageList == expected); REQUIRE(messageList == expected);
} }