From 49fa74628664bca5cf7818dbdfa3ce51f0f02ba4 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Thu, 25 Feb 2021 09:50:17 +0100 Subject: [PATCH] Keyswitch label and value messaging --- src/sfizz/Synth.cpp | 44 +++++++++++++++++++++++++++++++++--- src/sfizz/SynthMessaging.cpp | 14 ++++++++++++ src/sfizz/SynthPrivate.h | 5 ++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 3ca0beab..f292875d 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -241,6 +241,7 @@ void Synth::Impl::clear() numGroups_ = 0; numMasters_ = 0; currentSwitch_ = absl::nullopt; + currentSwitchChanged_ = true; defaultPath_ = ""; resources_.midiState.reset(); resources_.filePool.clear(); @@ -251,7 +252,7 @@ void Synth::Impl::clear() keyLabels_.clear(); keySlots_.clear(); swLastSlots_.clear(); - keyswitchLabels_.clear(); + clearKeyswitchLabels(); globalOpcodes_.clear(); masterOpcodes_.clear(); groupOpcodes_.clear(); @@ -623,7 +624,7 @@ void Synth::Impl::finalizeSfzLoad() region->keySwitched = (*currentSwitch_ == *region->lastKeyswitch); if (region->keyswitchLabel) - insertPairUniquely(keyswitchLabels_, *region->lastKeyswitch, *region->keyswitchLabel); + setKeyswitchLabel(*region->lastKeyswitch, *region->keyswitchLabel); } if (region->lastKeyswitchRange) { @@ -633,7 +634,7 @@ void Synth::Impl::finalizeSfzLoad() if (region->keyswitchLabel) { for (uint8_t note = range.getStart(), end = range.getEnd(); note <= end; note++) - insertPairUniquely(keyswitchLabels_, note, *region->keyswitchLabel); + setKeyswitchLabel(note, *region->keyswitchLabel); } } @@ -758,6 +759,8 @@ void Synth::Impl::finalizeSfzLoad() swLastSlots_.set(key); } } + // resend current keyswitch + currentSwitchChanged_ = true; } bool Synth::loadScalaFile(const fs::path& path) @@ -985,6 +988,16 @@ void Synth::renderBlock(AudioSpan buffer) noexcept broadcaster.receive<'b'>(numFrames - 1, "/cc/changed", &blob); } impl.changedCCsThisCycle_.clear(); + // Send the changed keyswitch + if (impl.currentSwitchChanged_) { + if (broadcaster.canReceive()) { + int32_t value = -1; + if (impl.currentSwitch_) + value = *impl.currentSwitch_; + broadcaster.receive<'i'>(numFrames - 1, "/sw/last/current", value); + } + impl.currentSwitchChanged_ = false; + } { // Clear events and advance midi time ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration }; @@ -1081,6 +1094,7 @@ void Synth::Impl::noteOnDispatch(int delay, int noteNumber, float velocity) noex region->keySwitched = false; } currentSwitch_ = noteNumber; + currentSwitchChanged_ = true; } for (auto& region : lastKeyswitchLists_[noteNumber]) @@ -1869,12 +1883,36 @@ void Synth::Impl::setCCLabel(int ccNumber, std::string name) } } +const std::string* Synth::Impl::getKeyswitchLabel(int swNumber) +{ + auto it = keyswitchLabelsMap_.find(swNumber); + return (it == keyswitchLabelsMap_.end()) ? nullptr : &keyswitchLabels_[it->second].second; +} + +void Synth::Impl::setKeyswitchLabel(int swNumber, std::string name) +{ + auto it = keyswitchLabelsMap_.find(swNumber); + if (it != keyswitchLabelsMap_.end()) + keyswitchLabels_[it->second].second = std::move(name); + else { + size_t index = keyswitchLabels_.size(); + keyswitchLabels_.emplace_back(swNumber, std::move(name)); + keyswitchLabelsMap_[swNumber] = index; + } +} + void Synth::Impl::clearCCLabels() { ccLabels_.clear(); ccLabelsMap_.clear(); } +void Synth::Impl::clearKeyswitchLabels() +{ + keyswitchLabels_.clear(); + keyswitchLabelsMap_.clear(); +} + Parser& Synth::getParser() noexcept { Impl& impl = *impl_; diff --git a/src/sfizz/SynthMessaging.cpp b/src/sfizz/SynthMessaging.cpp index 6dd2d9eb..67407e3c 100644 --- a/src/sfizz/SynthMessaging.cpp +++ b/src/sfizz/SynthMessaging.cpp @@ -52,6 +52,20 @@ void sfz::Synth::dispatchMessage(Client& client, int delay, const char* path, co client.receive<'b'>(delay, path, &blob); } break; + MATCH("/sw/last/current", "") { + int32_t value = -1; + if (impl.currentSwitch_) + value = *impl.currentSwitch_; + client.receive<'i'>(delay, path, value); + } break; + + MATCH("/sw/last/&/label", "") { + if (indices[0] >= 128) + break; + const std::string* label = impl.getKeyswitchLabel(indices[0]); + client.receive<'s'>(delay, path, label ? label->c_str() : ""); + } break; + //---------------------------------------------------------------------- MATCH("/cc/slots", "") { diff --git a/src/sfizz/SynthPrivate.h b/src/sfizz/SynthPrivate.h index da41a89f..bb69fdc7 100644 --- a/src/sfizz/SynthPrivate.h +++ b/src/sfizz/SynthPrivate.h @@ -184,6 +184,9 @@ struct Synth::Impl final: public Parser::Listener { const std::string* getCCLabel(int ccNumber); void setCCLabel(int ccNumber, std::string name); void clearCCLabels(); + const std::string* getKeyswitchLabel(int swNumber); + void setKeyswitchLabel(int swNumber, std::string name); + void clearKeyswitchLabels(); /** * @brief Perform a CC event @@ -219,9 +222,11 @@ struct Synth::Impl final: public Parser::Listener { BitArray<128> keySlots_; BitArray<128> swLastSlots_; std::vector keyswitchLabels_; + std::map keyswitchLabelsMap_; // Set as sw_default if present in the file absl::optional currentSwitch_; + bool currentSwitchChanged_ = true; std::vector unknownOpcodes_; using RegionViewVector = std::vector; using VoiceViewVector = std::vector;