From 1057ccdeff59b19e325a886876845c9efa180055 Mon Sep 17 00:00:00 2001 From: tremblap Date: Mon, 27 Feb 2023 20:31:06 +0000 Subject: [PATCH 01/12] almost working class def and no difference to the wrapper --- .../Classes/FluidVoiceAllocator.sc | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 release-packaging/Classes/FluidVoiceAllocator.sc diff --git a/release-packaging/Classes/FluidVoiceAllocator.sc b/release-packaging/Classes/FluidVoiceAllocator.sc new file mode 100644 index 00000000..17355e95 --- /dev/null +++ b/release-packaging/Classes/FluidVoiceAllocator.sc @@ -0,0 +1,33 @@ +FluidVoiceAllocator : MultiOutUGen { + + *kr { arg in, in2, in3, history = 1; + ^this.multiNew('control',*(in.asArray++in2.asArray++in3.asArray++history)).reshape(4,in.asArray.size).postln; + } + + init {arg ...theInputs; + inputs = theInputs; + inputs.postln; + inputs.size.postln; + this.specialIndex = (inputs.size - 2).max(0); + ^this.initOutputs(inputs.size - 1,rate) + } + + checkInputs { + ^this.checkValidInputs; + } + + initOutputs{|numChans,rate| + if(numChans.isNil or: {numChans < 1}) + { + Error("No input channels").throw + }; + + channels = Array.fill(numChans, { |i| + OutputProxy('control',this,i); + }); + ^channels + } + + numOutputs { ^(channels.size); } +} + From f7f6d7c84c0048e0cdf19a51d0e79e0f626be3d7 Mon Sep 17 00:00:00 2001 From: tremblap Date: Tue, 28 Feb 2023 11:25:34 +0000 Subject: [PATCH 02/12] removed the print outs and added size check of the inputs - still not sure how I get that shape of output when it should be 3 of in.asArray.size --- release-packaging/Classes/FluidVoiceAllocator.sc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/release-packaging/Classes/FluidVoiceAllocator.sc b/release-packaging/Classes/FluidVoiceAllocator.sc index 17355e95..753b2b03 100644 --- a/release-packaging/Classes/FluidVoiceAllocator.sc +++ b/release-packaging/Classes/FluidVoiceAllocator.sc @@ -1,18 +1,19 @@ FluidVoiceAllocator : MultiOutUGen { *kr { arg in, in2, in3, history = 1; - ^this.multiNew('control',*(in.asArray++in2.asArray++in3.asArray++history)).reshape(4,in.asArray.size).postln; + ^this.multiNew('control',*(in.asArray++in2.asArray++in3.asArray++history)).reshape(4,in.asArray.size); } init {arg ...theInputs; inputs = theInputs; - inputs.postln; - inputs.size.postln; this.specialIndex = (inputs.size - 2).max(0); ^this.initOutputs(inputs.size - 1,rate) } checkInputs { + if(((inputs.size - 1).mod(3)) != 0) { + ^(": the 3 array inputs must be of equal length."); + }; ^this.checkValidInputs; } @@ -31,3 +32,4 @@ FluidVoiceAllocator : MultiOutUGen { numOutputs { ^(channels.size); } } + From 3ec4d1879c31aa89afbbd379e01500297a096fbc Mon Sep 17 00:00:00 2001 From: tremblap Date: Tue, 28 Feb 2023 14:57:26 +0000 Subject: [PATCH 03/12] input shape now working --- include/wrapper/RealTimeBase.hpp | 41 ++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index ffeb5c78..3122c3a9 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -101,23 +101,23 @@ struct RealTimeBase return; } - if (client.audioChannelsIn()) - { + if (client.audioChannelsIn()) { mAudioInputs.reserve(asUnsigned(client.audioChannelsIn())); - for (index i = 0; i < client.audioChannelsIn(); ++i) - { + for (index i = 0; i < client.audioChannelsIn(); ++i) { mInputConnections.emplace_back(unit.isAudioRateIn(static_cast(i))); mAudioInputs.emplace_back(nullptr, 0, 0); } mInputMapper = &RealTimeBase::mapAudioInputs; - } - else if (client.controlChannelsIn()) - { - mControlInputBuffer.resize(unit.mSpecialIndex + 1); - mAudioInputs.emplace_back(mControlInputBuffer); + } else if (client.controlChannelsIn()) { + mControlInputBuffer.resize(client.controlChannelsIn(), + (unit.mSpecialIndex + 1) / + client.controlChannelsIn()); + for (index i = 0; i < client.controlChannelsIn(); ++i) { + mAudioInputs.emplace_back(mControlInputBuffer.row(i)); + } mInputMapper = &RealTimeBase::mapControlInputs; - } - else mInputMapper = &RealTimeBase::mapNoOp; + } else + mInputMapper = &RealTimeBase::mapNoOp; index outputSize = client.controlChannelsOut().size > 0 ? std::max(client.audioChannelsOut(), @@ -177,12 +177,17 @@ struct RealTimeBase } } - void mapControlInputs(SCUnit& unit, Client&) - { - for (index i = 0; i < unit.mSpecialIndex + 1; ++i) - { - assert(i <= std::numeric_limits::max()); - mControlInputBuffer[i] = unit.in0(static_cast(i)); + void mapControlInputs(SCUnit &unit, Client &client) { + assert((unit.mSpecialIndex + 1) % client.controlChannelsIn() == 0 && + "Control channels can't be mapped"); + index itemsPerChannel = + client.controlChannelsIn() / (unit.mSpecialIndex + 1); + for (index i = 0, offset = 0; i < client.controlChannelsIn(); + ++i, offset += itemsPerChannel) { + for (index j = 0; j < itemsPerChannel; ++j) { + assert(j <= std::numeric_limits::max()); + mControlInputBuffer(i, j) = unit.in0(static_cast(offset + j)); + } } } @@ -228,7 +233,7 @@ struct RealTimeBase std::vector mOutputConnections; std::vector mAudioInputs; std::vector mOutputs; - FluidTensor mControlInputBuffer; + FluidTensor mControlInputBuffer; FluidTensor mControlOutputBuffer; bool mPrevTrig; IOMapFn mInputMapper; From 0b44c2377f1c4f34a459ca339c9458915a792ba1 Mon Sep 17 00:00:00 2001 From: tremblap Date: Tue, 28 Feb 2023 23:34:21 +0000 Subject: [PATCH 04/12] correct input count division (was the wrong way round) --- include/wrapper/RealTimeBase.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index 3122c3a9..7266f609 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -181,7 +181,7 @@ struct RealTimeBase assert((unit.mSpecialIndex + 1) % client.controlChannelsIn() == 0 && "Control channels can't be mapped"); index itemsPerChannel = - client.controlChannelsIn() / (unit.mSpecialIndex + 1); + (unit.mSpecialIndex + 1) / client.controlChannelsIn(); for (index i = 0, offset = 0; i < client.controlChannelsIn(); ++i, offset += itemsPerChannel) { for (index j = 0; j < itemsPerChannel; ++j) { From b8c24876eb012ec7dfc9a982cba0041e8bcb1ff9 Mon Sep 17 00:00:00 2001 From: tremblap Date: Tue, 28 Feb 2023 23:35:02 +0000 Subject: [PATCH 05/12] computes the real size of the input to decline the output size --- include/wrapper/RealTimeBase.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index 7266f609..476d0e88 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -122,7 +122,7 @@ struct RealTimeBase index outputSize = client.controlChannelsOut().size > 0 ? std::max(client.audioChannelsOut(), client.maxControlChannelsOut()) - : unit.mSpecialIndex + 1; + : ((unit.mSpecialIndex + 1) / client.controlChannelsIn()); mOutputs.reserve(asUnsigned(outputSize)); if (client.audioChannelsOut()) From 1443339c0c920956ca203de31e8ffe7859ee86b5 Mon Sep 17 00:00:00 2001 From: tremblap Date: Tue, 28 Feb 2023 23:47:05 +0000 Subject: [PATCH 06/12] and finally a working class. We're all set! --- release-packaging/Classes/FluidVoiceAllocator.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-packaging/Classes/FluidVoiceAllocator.sc b/release-packaging/Classes/FluidVoiceAllocator.sc index 753b2b03..43b70924 100644 --- a/release-packaging/Classes/FluidVoiceAllocator.sc +++ b/release-packaging/Classes/FluidVoiceAllocator.sc @@ -1,7 +1,7 @@ FluidVoiceAllocator : MultiOutUGen { *kr { arg in, in2, in3, history = 1; - ^this.multiNew('control',*(in.asArray++in2.asArray++in3.asArray++history)).reshape(4,in.asArray.size); + ^this.multiNew('control',*(in.asArray++in2.asArray++in3.asArray++history)).reshape(3,in.asArray.size); } init {arg ...theInputs; From 8d37bb5e62a9616a43ebd9b22408eb2e046edc0f Mon Sep 17 00:00:00 2001 From: tremblap Date: Sun, 3 Sep 2023 13:45:30 +0100 Subject: [PATCH 07/12] troubleshooting prints all over --- include/FluidSCWrapper.hpp | 8 +------- include/wrapper/RealTimeBase.hpp | 19 ++++++++++++++++--- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index b7285127..ae93c516 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -73,7 +73,7 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase ft->fDefinePlugInCmd(commandName.c_str(), [](World*, void*, sc_msg_iter*, void*){ doVersion(nullptr,nullptr); }, nullptr); - + std::cout << "done settup " << name << "\n"; } static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs, @@ -99,12 +99,6 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase if(!initialized) delete reportage; return p; } - -// static void printResult(SharedState& x, Result& r) -// { -// if (!x.get() || !x->mNodeAlive) return; -// FluidSCWrapper::printResult(x->mNode->mWorld, r); -// } static void printResult(World* w,Result& r) { diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index 476d0e88..1bc867ff 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -102,6 +102,7 @@ struct RealTimeBase } if (client.audioChannelsIn()) { + std::cout << "aci " << client.audioChannelsIn() << "\n"; mAudioInputs.reserve(asUnsigned(client.audioChannelsIn())); for (index i = 0; i < client.audioChannelsIn(); ++i) { mInputConnections.emplace_back(unit.isAudioRateIn(static_cast(i))); @@ -109,6 +110,7 @@ struct RealTimeBase } mInputMapper = &RealTimeBase::mapAudioInputs; } else if (client.controlChannelsIn()) { + std::cout << "cci\n"; mControlInputBuffer.resize(client.controlChannelsIn(), (unit.mSpecialIndex + 1) / client.controlChannelsIn()); @@ -116,13 +118,24 @@ struct RealTimeBase mAudioInputs.emplace_back(mControlInputBuffer.row(i)); } mInputMapper = &RealTimeBase::mapControlInputs; - } else - mInputMapper = &RealTimeBase::mapNoOp; + } else { + mInputMapper = &RealTimeBase::mapNoOp; + std::cout << "else\n"; + } + + std::cout << "controlChannelsOut " << client.controlChannelsOut().size << "\n"; + std::cout << "audioChannelsOut " << client.audioChannelsOut() << "\n"; + std::cout << "maxControlChannelsOut " << client.maxControlChannelsOut() << "\n"; + std::cout << "controlChannelsIn " << client.controlChannelsIn() << "\n"; + index outputSize = client.controlChannelsOut().size > 0 ? std::max(client.audioChannelsOut(), client.maxControlChannelsOut()) - : ((unit.mSpecialIndex + 1) / client.controlChannelsIn()); + : (unit.mSpecialIndex + 1);//((unit.mSpecialIndex + 1) / client.controlChannelsIn()); + + std::cout << "outputSize " << outputSize << "\n"; + mOutputs.reserve(asUnsigned(outputSize)); if (client.audioChannelsOut()) From 288e6eb0da5a6d39c37e20147049f2fbea909a12 Mon Sep 17 00:00:00 2001 From: tremblap Date: Sun, 3 Sep 2023 13:45:41 +0100 Subject: [PATCH 08/12] new proper class for proper algo --- release-packaging/Classes/FluidVoiceAllocator.sc | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/release-packaging/Classes/FluidVoiceAllocator.sc b/release-packaging/Classes/FluidVoiceAllocator.sc index 43b70924..9496f6df 100644 --- a/release-packaging/Classes/FluidVoiceAllocator.sc +++ b/release-packaging/Classes/FluidVoiceAllocator.sc @@ -1,18 +1,21 @@ FluidVoiceAllocator : MultiOutUGen { - *kr { arg in, in2, in3, history = 1; - ^this.multiNew('control',*(in.asArray++in2.asArray++in3.asArray++history)).reshape(3,in.asArray.size); + *kr { arg in, in2, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, maxNumVoices; + + maxNumVoices = maxNumVoices ? numVoices; + + ^this.multiNew('control',*(in.asArray ++ in2.asArray ++ numVoices ++ maxNumVoices ++ prioritisedVoices ++ birthLowThreshold ++ birthHighThreshold ++ minTrackLen ++ trackMagRange ++ trackFreqRange ++ trackProb)).reshape(3,maxNumVoices); } init {arg ...theInputs; inputs = theInputs; - this.specialIndex = (inputs.size - 2).max(0); - ^this.initOutputs(inputs.size - 1,rate) + this.specialIndex = (inputs.size - 10).max(0); + ^this.initOutputs(inputs[inputs.size - 8] * 3,rate); } checkInputs { - if(((inputs.size - 1).mod(3)) != 0) { - ^(": the 3 array inputs must be of equal length."); + if(((inputs.size - 9).mod(2)) != 0) { + ^(": the 2 input arrays must be of equal length."); }; ^this.checkValidInputs; } @@ -32,4 +35,3 @@ FluidVoiceAllocator : MultiOutUGen { numOutputs { ^(channels.size); } } - From 8c0c6f292e93a33215a0e804a82cbd7d4b8a17fd Mon Sep 17 00:00:00 2001 From: tremblap Date: Sun, 3 Sep 2023 14:04:08 +0100 Subject: [PATCH 09/12] remove the debugging pritns --- include/FluidSCWrapper.hpp | 1 - include/wrapper/RealTimeBase.hpp | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index ae93c516..ef31a289 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -73,7 +73,6 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase ft->fDefinePlugInCmd(commandName.c_str(), [](World*, void*, sc_msg_iter*, void*){ doVersion(nullptr,nullptr); }, nullptr); - std::cout << "done settup " << name << "\n"; } static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs, diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index 1bc867ff..d69e0744 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -102,7 +102,6 @@ struct RealTimeBase } if (client.audioChannelsIn()) { - std::cout << "aci " << client.audioChannelsIn() << "\n"; mAudioInputs.reserve(asUnsigned(client.audioChannelsIn())); for (index i = 0; i < client.audioChannelsIn(); ++i) { mInputConnections.emplace_back(unit.isAudioRateIn(static_cast(i))); @@ -110,7 +109,6 @@ struct RealTimeBase } mInputMapper = &RealTimeBase::mapAudioInputs; } else if (client.controlChannelsIn()) { - std::cout << "cci\n"; mControlInputBuffer.resize(client.controlChannelsIn(), (unit.mSpecialIndex + 1) / client.controlChannelsIn()); @@ -120,22 +118,13 @@ struct RealTimeBase mInputMapper = &RealTimeBase::mapControlInputs; } else { mInputMapper = &RealTimeBase::mapNoOp; - std::cout << "else\n"; } - - std::cout << "controlChannelsOut " << client.controlChannelsOut().size << "\n"; - std::cout << "audioChannelsOut " << client.audioChannelsOut() << "\n"; - std::cout << "maxControlChannelsOut " << client.maxControlChannelsOut() << "\n"; - std::cout << "controlChannelsIn " << client.controlChannelsIn() << "\n"; - index outputSize = client.controlChannelsOut().size > 0 ? std::max(client.audioChannelsOut(), client.maxControlChannelsOut()) - : (unit.mSpecialIndex + 1);//((unit.mSpecialIndex + 1) / client.controlChannelsIn()); + : (unit.mSpecialIndex + 1); - std::cout << "outputSize " << outputSize << "\n"; - mOutputs.reserve(asUnsigned(outputSize)); if (client.audioChannelsOut()) From 15d013533604711a64f8989f9b7649110c533ff4 Mon Sep 17 00:00:00 2001 From: tremblap Date: Sun, 3 Sep 2023 14:14:39 +0100 Subject: [PATCH 10/12] clang-format-ed --- include/FluidSCWrapper.hpp | 131 ++++++++++++------------ include/wrapper/RealTimeBase.hpp | 165 +++++++++++++------------------ 2 files changed, 133 insertions(+), 163 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index ef31a289..c5826603 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -21,16 +21,14 @@ namespace client { /// The main wrapper template -class FluidSCWrapper : public impl::FluidSCWrapperBase -{ +class FluidSCWrapper : public impl::FluidSCWrapperBase { using FloatControlsIter = impl::FloatControlsIter; - - //I would like to template these to something more scaleable, but baby steps - friend class impl::RealTime; - friend class impl::NonRealTime; - static void doVersion(Unit*, sc_msg_iter*) - { + // I would like to template these to something more scaleable, but baby steps + friend class impl::RealTime; + friend class impl::NonRealTime; + + static void doVersion(Unit *, sc_msg_iter *) { std::cout << "Fluid Corpus Manipulation Toolkit: version " << fluidVersion() << std::endl; } @@ -38,101 +36,100 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase bool mInit{false}; public: - template - using ArgumentSetter = typename ClientParams::template Setter; + using ArgumentSetter = + typename ClientParams::template Setter; template - using ControlSetter = typename ClientParams::template Setter; + using ControlSetter = + typename ClientParams::template Setter; using Client = C; using ParamSetType = typename C::ParamSetType; - static const char* getName(const char* setName = nullptr) - { - static const char* name = nullptr; + static const char *getName(const char *setName = nullptr) { + static const char *name = nullptr; return (name = setName ? setName : name); } - static InterfaceTable* getInterfaceTable(InterfaceTable* setTable = nullptr) - { - static InterfaceTable* ft = nullptr; + static InterfaceTable *getInterfaceTable(InterfaceTable *setTable = nullptr) { + static InterfaceTable *ft = nullptr; return (ft = setTable ? setTable : ft); } - static void setup(InterfaceTable* ft, const char* name) - { + static void setup(InterfaceTable *ft, const char *name) { getName(name); getInterfaceTable(ft); impl::FluidSCWrapperBase::setup(ft, name); ft->fDefineUnitCmd(name, "version", doVersion); - + std::string commandName("/"); commandName += getName(); commandName += "/version"; - ft->fDefinePlugInCmd(commandName.c_str(), - [](World*, void*, sc_msg_iter*, void*){ doVersion(nullptr,nullptr); }, - nullptr); + ft->fDefinePlugInCmd( + commandName.c_str(), + [](World *, void *, sc_msg_iter *, void *) { + doVersion(nullptr, nullptr); + }, + nullptr); } - static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs, - Allocator& alloc, bool constrain = false, - bool initialized = true) - { + static auto &setParams(Unit *x, ParamSetType &p, FloatControlsIter &inputs, + Allocator &alloc, bool constrain = false, + bool initialized = true) { bool verbose = x->mWorld->mVerbosity > 0; - - using Reportage = decltype(static_cast(x)->mReportage); - - Reportage* reportage = initialized ? &(static_cast(x)->mReportage) : new Reportage(); + + using Reportage = decltype(static_cast(x)->mReportage); + + Reportage *reportage = initialized + ? &(static_cast(x)->mReportage) + : new Reportage(); p.template setParameterValuesRT( verbose ? reportage : nullptr, x, inputs, p, alloc); - if (constrain) p.constrainParameterValuesRT(verbose ? reportage : nullptr); - if(verbose) - { - for(auto& r:*reportage) - { - if(!r.ok()) printResult(x->mParent->mNode.mWorld, r); + if (constrain) + p.constrainParameterValuesRT(verbose ? reportage : nullptr); + if (verbose) { + for (auto &r : *reportage) { + if (!r.ok()) + printResult(x->mParent->mNode.mWorld, r); } } - if(!initialized) delete reportage; + if (!initialized) + delete reportage; return p; } - - static void printResult(World* w,Result& r) - { - - switch (r.status()) - { - case Result::Status::kWarning: - { - if (!w || w->mVerbosity > 0) - std::cout << "WARNING: " << getName() << " - " << r.message().c_str() << '\n'; - break; - } - case Result::Status::kError: - { - std::cout << "ERROR: " << getName() << " - " << r.message().c_str() << '\n'; - break; - } - case Result::Status::kCancelled: - { - std::cout << getName() << ": Task cancelled\n" << '\n'; - break; - } - default: - { - } - } + + static void printResult(World *w, Result &r) { + + switch (r.status()) { + case Result::Status::kWarning: { + if (!w || w->mVerbosity > 0) + std::cout << "WARNING: " << getName() << " - " << r.message().c_str() + << '\n'; + break; + } + case Result::Status::kError: { + std::cout << "ERROR: " << getName() << " - " << r.message().c_str() + << '\n'; + break; + } + case Result::Status::kCancelled: { + std::cout << getName() << ": Task cancelled\n" << '\n'; + break; + } + default: { + } + } } - + private: std::array mReportage; }; template -void makeSCWrapper(const char* name, InterfaceTable* ft) -{ +void makeSCWrapper(const char *name, InterfaceTable *ft) { FluidSCWrapper::setup(ft, name); } diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index d69e0744..923cd8df 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -1,76 +1,63 @@ #pragma once -#include -#include #include +#include +#include namespace fluid { namespace client { namespace impl { - -template -struct RealTimeBase -{ - using IOMapFn = void (RealTimeBase::*)(SCUnit&, Client&); +template struct RealTimeBase { + using IOMapFn = void (RealTimeBase::*)(SCUnit &, Client &); using HostVector = FluidTensorView; using Params = typename Client::ParamSetType; - template - struct doExpectedCount; - - template - struct doExpectedCount - { - static void count(const T& d, FloatControlsIter& c, Result& status) - { - if (!status.ok()) return; - - if (c.remain()) - { + template struct doExpectedCount; + + template struct doExpectedCount { + static void count(const T &d, FloatControlsIter &c, Result &status) { + if (!status.ok()) + return; + + if (c.remain()) { index statedSize = d.fixedSize; if (c.remain() < statedSize) status = {Result::Status::kError, "Ran out of arguments at ", d.name}; // fastforward - for (index i = 0; i < statedSize; ++i) c.next(); + for (index i = 0; i < statedSize; ++i) + c.next(); } } }; - template - struct doExpectedCount - { - static void count(const T& d, FloatControlsIter& c, Result& status) - { - if (!status.ok()) return; + template struct doExpectedCount { + static void count(const T &d, FloatControlsIter &c, Result &status) { + if (!status.ok()) + return; - if (c.remain()) - { + if (c.remain()) { index statedSize = 1; if (c.remain() < statedSize) status = {Result::Status::kError, "Ran out of arguments at ", d.name}; // fastforward - for (index i = 0; i < statedSize; ++i) c.next(); + for (index i = 0; i < statedSize; ++i) + c.next(); } } }; - template - struct ExpectedCount - { - void operator()(const T& descriptor, FloatControlsIter& c, Result& status) - { + template struct ExpectedCount { + void operator()(const T &descriptor, FloatControlsIter &c, Result &status) { doExpectedCount::value>::count( descriptor, c, status); } }; - Result expectedSize(FloatControlsIter& controls) - { - if (controls.size() < Client::getParameterDescriptors().count()) - { + Result expectedSize(FloatControlsIter &controls) { + if (controls.size() < Client::getParameterDescriptors().count()) { return {Result::Status::kError, "Fewer parameters than exepected. Got ", controls.size(), "expect at least", Client::getParameterDescriptors().count()}; @@ -78,24 +65,22 @@ struct RealTimeBase Result countScan; Client::getParameterDescriptors().template iterate( - std::forward(controls), - std::forward(countScan)); + std::forward(controls), + std::forward(countScan)); return countScan; } - - void init(SCUnit& unit, Client& client, FloatControlsIter& controls, Allocator& alloc) - { + void init(SCUnit &unit, Client &client, FloatControlsIter &controls, + Allocator &alloc) { assert(!(client.audioChannelsOut() > 0 && client.controlChannelsOut().count > 0) && "Client can't have both audio and control outputs"); client.sampleRate(unit.fullSampleRate()); mInputConnections.reserve(asUnsigned(client.audioChannelsIn())); mOutputConnections.reserve(asUnsigned(client.audioChannelsOut())); - mContext = FluidContext(unit.fullBufferSize(), alloc); + mContext = FluidContext(unit.fullBufferSize(), alloc); Result r; - if (!(r = expectedSize(controls)).ok()) - { + if (!(r = expectedSize(controls)).ok()) { std::cout << "ERROR: " << Wrapper::getName() << " wrong number of arguments." << r.message() << std::endl; return; @@ -117,34 +102,29 @@ struct RealTimeBase } mInputMapper = &RealTimeBase::mapControlInputs; } else { - mInputMapper = &RealTimeBase::mapNoOp; + mInputMapper = &RealTimeBase::mapNoOp; } - + index outputSize = client.controlChannelsOut().size > 0 ? std::max(client.audioChannelsOut(), client.maxControlChannelsOut()) - : (unit.mSpecialIndex + 1); - + : (unit.mSpecialIndex + 1); + mOutputs.reserve(asUnsigned(outputSize)); - if (client.audioChannelsOut()) - { - for (index i = 0; i < client.audioChannelsOut(); ++i) - { + if (client.audioChannelsOut()) { + for (index i = 0; i < client.audioChannelsOut(); ++i) { mOutputConnections.emplace_back(true); mOutputs.emplace_back(nullptr, 0, 0); } - + mOutMapperPre = &RealTimeBase::mapAudioOutputs; mOutMapperPost = &RealTimeBase::mapNoOp; - } - else - { + } else { index totalControlOutputs = client.controlChannelsOut().count * outputSize; mControlOutputBuffer.resize(totalControlOutputs); - for (index i = 0; i < client.controlChannelsOut().count; ++i) - { + for (index i = 0; i < client.controlChannelsOut().count; ++i) { mOutputs.emplace_back( mControlOutputBuffer(fluid::Slice(i * outputSize, outputSize))); } @@ -154,24 +134,20 @@ struct RealTimeBase } } - void mapNoOp(SCUnit&, Client&) {} + void mapNoOp(SCUnit &, Client &) {} - void mapAudioInputs(SCUnit& unit, Client& client) - { - for (index i = 0; i < client.audioChannelsIn(); ++i) - { + void mapAudioInputs(SCUnit &unit, Client &client) { + for (index i = 0; i < client.audioChannelsIn(); ++i) { assert(i <= std::numeric_limits::max()); if (mInputConnections[asUnsigned(i)]) mAudioInputs[asUnsigned(i)].reset( - const_cast(unit.in(static_cast(i))), 0, + const_cast(unit.in(static_cast(i))), 0, unit.fullBufferSize()); } } - void mapAudioOutputs(SCUnit& unit, Client& client) - { - for (index i = 0; i < client.audioChannelsOut(); ++i) - { + void mapAudioOutputs(SCUnit &unit, Client &client) { + for (index i = 0; i < client.audioChannelsOut(); ++i) { assert(i <= std::numeric_limits::max()); if (mOutputConnections[asUnsigned(i)]) mOutputs[asUnsigned(i)].reset(unit.out(static_cast(i)), 0, @@ -193,30 +169,27 @@ struct RealTimeBase } } - void mapControlOutputs(SCUnit& unit, Client&) - { - index numOuts = std::min(mControlOutputBuffer.size(),unit.mNumOutputs); - - for (index i = 0; i < numOuts; ++i) - { + void mapControlOutputs(SCUnit &unit, Client &) { + index numOuts = + std::min(mControlOutputBuffer.size(), unit.mNumOutputs); + + for (index i = 0; i < numOuts; ++i) { assert(i <= std::numeric_limits::max()); unit.out0(static_cast(i)) = mControlOutputBuffer(i); } } - void next(SCUnit& unit, Client& client, Params& params, - FloatControlsIter& controls, Allocator& alloc, - bool updateParams = true) - { + void next(SCUnit &unit, Client &client, Params ¶ms, + FloatControlsIter &controls, Allocator &alloc, + bool updateParams = true) { bool trig = IsModel_t::value ? !mPrevTrig && unit.in0(0) > 0 : false; mPrevTrig = trig; - #ifdef EIGEN_RUNTIME_NO_MALLOC +#ifdef EIGEN_RUNTIME_NO_MALLOC Eigen::internal::set_is_malloc_allowed(false); - #endif - if (updateParams) - { +#endif + if (updateParams) { Wrapper::setParams(&unit, params, controls, alloc); params.constrainParameterValuesRT(nullptr); } @@ -225,23 +198,23 @@ struct RealTimeBase (this->*mOutMapperPre)(unit, client); client.process(mAudioInputs, mOutputs, mContext); (this->*mOutMapperPost)(unit, client); - #ifdef EIGEN_RUNTIME_NO_MALLOC - Eigen::internal::set_is_malloc_allowed(true); //not really - #endif +#ifdef EIGEN_RUNTIME_NO_MALLOC + Eigen::internal::set_is_malloc_allowed(true); // not really +#endif } private: - std::vector mInputConnections; - std::vector mOutputConnections; + std::vector mInputConnections; + std::vector mOutputConnections; std::vector mAudioInputs; std::vector mOutputs; - FluidTensor mControlInputBuffer; - FluidTensor mControlOutputBuffer; - bool mPrevTrig; - IOMapFn mInputMapper; - IOMapFn mOutMapperPre; - IOMapFn mOutMapperPost; - FluidContext mContext; + FluidTensor mControlInputBuffer; + FluidTensor mControlOutputBuffer; + bool mPrevTrig; + IOMapFn mInputMapper; + IOMapFn mOutMapperPre; + IOMapFn mOutMapperPost; + FluidContext mContext; }; } // namespace impl } // namespace client From e6f7db6f05e926ff463d74b9bb6c9351141071d5 Mon Sep 17 00:00:00 2001 From: tremblap Date: Wed, 17 Jul 2024 15:01:51 +0100 Subject: [PATCH 11/12] sc class def --- .../Classes/FluidBufVoiceAllocator.sc | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 release-packaging/Classes/FluidBufVoiceAllocator.sc diff --git a/release-packaging/Classes/FluidBufVoiceAllocator.sc b/release-packaging/Classes/FluidBufVoiceAllocator.sc new file mode 100644 index 00000000..25d3b3db --- /dev/null +++ b/release-packaging/Classes/FluidBufVoiceAllocator.sc @@ -0,0 +1,45 @@ +FluidBufVoiceAllocator : FluidBufProcessor { + *process { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, freeWhenDone = true, action| + + sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw}; + sourceB.isNil.if {"FluidBufVoiceAllocator: Invalid source 2 buffer".throw}; + sourceA = sourceA.asUGenInput; + sourceB = sourceB.asUGenInput; + + destA.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destB.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destC.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destA = destA.asUGenInput; + destB = destB.asUGenInput; + destC = destC.asUGenInput; + + ^this.new( + server, nil, [destA, destB, destC] + ).processList( + [sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destA, destB, destC, numVoices, numVoices, prioritisedVoices, birthLowThreshold, birthHighThreshold, minTrackLen, trackMagRange, trackFreqRange, trackProb, 0], freeWhenDone, action + ) + } + + *processBlocking { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, freeWhenDone = true, action| + + sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw}; + sourceB.isNil.if {"FluidBufVoiceAllocator: Invalid source 2 buffer".throw}; + sourceA = sourceA.asUGenInput; + sourceB = sourceB.asUGenInput; + + destA.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destB.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destC.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destA = destA.asUGenInput; + destB = destB.asUGenInput; + destC = destC.asUGenInput; + + ^this.new( + server, nil, [destA, destB, destC] + ).processList( + [sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destA, destB, destC, numVoices, numVoices, prioritisedVoices, birthLowThreshold, birthHighThreshold, minTrackLen, trackMagRange, trackFreqRange, trackProb, 1], freeWhenDone, action + ) + } +} + +FluidBufVoiceAllocatorTrigger : FluidProxyUgen {} From 0d53540b763818cdb32d4495f2e72c1d0e668848 Mon Sep 17 00:00:00 2001 From: tremblap Date: Wed, 17 Jul 2024 15:29:01 +0100 Subject: [PATCH 12/12] added the kr --- .../Classes/FluidBufVoiceAllocator.sc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/release-packaging/Classes/FluidBufVoiceAllocator.sc b/release-packaging/Classes/FluidBufVoiceAllocator.sc index 25d3b3db..aab9e38c 100644 --- a/release-packaging/Classes/FluidBufVoiceAllocator.sc +++ b/release-packaging/Classes/FluidBufVoiceAllocator.sc @@ -1,4 +1,21 @@ FluidBufVoiceAllocator : FluidBufProcessor { + *kr { |sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, trig = 1, blocking = 0| + + sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw}; + sourceB.isNil.if {"FluidBufVoiceAllocator: Invalid source 2 buffer".throw}; + sourceA = sourceA.asUGenInput; + sourceB = sourceB.asUGenInput; + + destA.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destB.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destC.isNil.if {"FluidBufVoiceAllocator: Invalid destination buffer".throw}; + destA = destA.asUGenInput; + destB = destB.asUGenInput; + destC = destC.asUGenInput; + + ^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destA, destB, destC, numVoices, numVoices, prioritisedVoices, birthLowThreshold, birthHighThreshold, minTrackLen, trackMagRange, trackFreqRange, trackProb, trig, blocking); + } + *process { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destA, destB, destC, numVoices = 1, prioritisedVoices = 0, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 1, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, freeWhenDone = true, action| sourceA.isNil.if {"FluidBufVoiceAllocator: Invalid source 1 buffer".throw};