From 27ec95566a28e10b3f213786a2665ce8de0152a3 Mon Sep 17 00:00:00 2001 From: Jean Pierre Cimalando Date: Wed, 3 Feb 2021 14:30:16 +0100 Subject: [PATCH] Notify editor of CC changed by MIDI --- editor/src/editor/Editor.cpp | 12 ++++++++++++ src/sfizz/Synth.cpp | 20 +++++++++++++++++++- src/sfizz/SynthPrivate.h | 8 ++++++++ src/sfizz/utility/BitArray.h | 1 + 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/editor/src/editor/Editor.cpp b/editor/src/editor/Editor.cpp index 21462e79..128dd9df 100644 --- a/editor/src/editor/Editor.cpp +++ b/editor/src/editor/Editor.cpp @@ -420,6 +420,18 @@ void Editor::Impl::uiReceiveMessage(const char* path, const char* sig, const sfi } } } + else if (!strcmp(path, "/cc/changed") && !strcmp(sig, "b")) { + const uint8_t* bitChunks = args[0].b->data; + uint32_t byteSize = args[0].b->size; + for (unsigned cc = 0; cc < 8 * byteSize; ++cc) { + bool changed = bitChunks[cc / 8] & (1u << (cc % 8)); + if (changed) { + char pathBuf[256]; + sprintf(pathBuf, "/cc%u/value", cc); + sendQueuedOSC(pathBuf, "", nullptr); + } + } + } else if (matchMessage("/cc&/value", path, indices) && !strcmp(sig, "f")) { updateCCValue(indices[0], args[0].f); } diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 6e736690..d9ecb85e 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -245,6 +245,8 @@ void Synth::Impl::clear() resources_.filePool.clear(); resources_.filePool.setRamLoading(config::loadInRam); clearCCLabels(); + currentUsedCCs_.clear(); + changedCCsThisCycle_.clear(); keyLabels_.clear(); keyswitchLabels_.clear(); globalOpcodes_.clear(); @@ -855,6 +857,12 @@ void Synth::renderBlock(AudioSpan buffer) noexcept buffer.fill(0.0f); } + const size_t numFrames = buffer.getNumFrames(); + if (numFrames < 1) { + CHECKFALSE; + return; + } + if (impl.resources_.synthConfig.freeWheeling) impl.resources_.filePool.waitForBackgroundLoading(); @@ -867,7 +875,6 @@ void Synth::renderBlock(AudioSpan buffer) noexcept impl.resources_.filePool.triggerGarbageCollection(); } - size_t numFrames = buffer.getNumFrames(); auto tempSpan = impl.resources_.bufferPool.getStereoBuffer(numFrames); auto tempMixSpan = impl.resources_.bufferPool.getStereoBuffer(numFrames); auto rampSpan = impl.resources_.bufferPool.getBuffer(numFrames); @@ -958,6 +965,15 @@ void Synth::renderBlock(AudioSpan buffer) noexcept // Advance the clock to the end of cycle bc.endCycle(); + // Send the set of changed CCs + Client broadcaster = impl.getBroadcaster(); + const BitArray& changedCCs = impl.changedCCsThisCycle_; + if (broadcaster.canReceive()) { + sfizz_blob_t blob { changedCCs.data(), static_cast(changedCCs.byte_size()) }; + broadcaster.receive<'b'>(numFrames - 1, "/cc/changed", &blob); + } + impl.changedCCsThisCycle_.clear(); + { // Clear events and advance midi time ScopedTiming logger { impl.dispatchDuration_, ScopedTiming::Operation::addToDuration }; impl.resources_.midiState.advanceTime(buffer.getNumFrames()); @@ -1137,6 +1153,8 @@ void Synth::Impl::performHdcc(int delay, int ccNumber, float normValue, bool asM ScopedTiming logger { dispatchDuration_, ScopedTiming::Operation::addToDuration }; resources_.midiState.ccEvent(delay, ccNumber, normValue); + changedCCsThisCycle_.set(ccNumber); + if (asMidi) { if (ccNumber == config::resetCC) { resetAllControllers(delay); diff --git a/src/sfizz/SynthPrivate.h b/src/sfizz/SynthPrivate.h index 893e436e..0e251024 100644 --- a/src/sfizz/SynthPrivate.h +++ b/src/sfizz/SynthPrivate.h @@ -285,10 +285,18 @@ struct Synth::Impl final: public Parser::Listener { std::array defaultCCValues_; BitArray currentUsedCCs_; + BitArray changedCCsThisCycle_; // Messaging sfizz_receive_t* broadcastReceiver = nullptr; void* broadcastData = nullptr; + + Client getBroadcaster() const + { + Client client(broadcastData); + client.setReceiveCallback(broadcastReceiver); + return client; + } }; } // namespace sfz diff --git a/src/sfizz/utility/BitArray.h b/src/sfizz/utility/BitArray.h index 020a7433..a55dccaf 100644 --- a/src/sfizz/utility/BitArray.h +++ b/src/sfizz/utility/BitArray.h @@ -67,6 +67,7 @@ public: static constexpr size_t byte_size() noexcept { return (N + 7) / 8; } BitSpan span() noexcept { return BitSpan(data_, N); }; ConstBitSpan span() const noexcept { return ConstBitSpan(data_, N); }; + void clear() { span().clear(); } bool test(size_t i) const noexcept { return span().test(i); } void set(size_t i) noexcept { span().set(i); } void set(size_t i, bool b) noexcept { span().set(i, b); }