diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index b7ef1f5..4551eba 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -29,7 +29,7 @@ template Method> struct GetArgument { T operator()(World* w, sc_msg_iter *args) { - T r = (args->*Method)(0); + T r = (args->*Method)(T{0}); return r; } }; @@ -63,22 +63,29 @@ template struct GetControl }; template struct ArgumentGetter : public GetArgument -{}; +{ +// ArgumentGetter() { std::cout << "FloatT @ " << N << '\n'; } +}; template struct ArgumentGetter : public GetArgument -{}; +{ +// ArgumentGetter() { std::cout << "LongT @ " << N << '\n'; } + +}; template struct ArgumentGetter : public GetArgument -{}; +{ +// ArgumentGetter() { std::cout << "Enum @ " << N << '\n'; } + +}; template struct ArgumentGetter { - auto operator()(World* w, sc_msg_iter *args) +// ArgumentGetter() { std::cout << "Buffer @ " << N << '\n'; } + auto operator() (World* w, sc_msg_iter *args) { - - long bufnum = args->geti(-1); - - return std::unique_ptr(new SCBufferAdaptor(bufnum,w)); + typename LongT::type bufnum = args->geti(-1); + return std::unique_ptr(bufnum >= 0 ? new SCBufferAdaptor(bufnum,w) : nullptr); } }; @@ -98,10 +105,10 @@ template struct ControlGetter : public GetControl struct ControlGetter { - auto operator()(World* w, FloatControlsIter& iter) + auto operator() (World* w, FloatControlsIter& iter) { - long bufnum = iter.next(); - return std::unique_ptr(new SCBufferAdaptor(bufnum,w)); + typename LongT::type bufnum = iter.next(); + return std::unique_ptr(bufnum >= 0 ? new SCBufferAdaptor(bufnum,w): nullptr); } }; @@ -114,29 +121,54 @@ struct ControlGetter } }; + +template class Fetcher> +struct ClientFactory +{ + static Client create(World* world, Args* args) + { + return createImpl(world, args, FixedParamIndices{}); + } + +private: + using FixedParamIndices = typename Client::FixedParams; + template + using ThisParamType = typename Client::template ParamDescriptorTypeAt; + + template + static Client createImpl(World* world, Args* args, std::index_sequence) + { + return Client{Fetcher>{}(world,*args)...}; + } +}; + //template class RealTime : public SCUnit +template class RealTime : public SCUnit { using HostVector = FluidTensorView; // using Client = typename Wrapper::ClientType; public: static void setup(InterfaceTable *ft, const char *name) { registerUnit(ft, name); } - - RealTime():mControlsIterator{nullptr,0} {} + + RealTime(): + SCUnit{}, + mControlsIterator{mInBuf + mSpecialIndex + 1,mNumInputs - mSpecialIndex - 1}, + mClient{ClientFactory::create(mWorld,&mControlsIterator)} + {} void init() { - Wrapper *w = static_cast(this); - - auto &mClient = w->client(); + assert(!(mClient.audioChannelsOut() > 0 && mClient.controlChannelsOut() > 0) && "Client can't have both audio and control outputs"); mInputConnections.reserve(mClient.audioChannelsIn()); mOutputConnections.reserve(mClient.audioChannelsOut()); mAudioInputs.reserve(mClient.audioChannelsIn()); mAudioOutputs.reserve(mClient.audioChannelsOut()); - + mControlOutputs.reserve(mClient.controlChannelsOut()); +// mControlOutputData.resize(mClient.controlChannelsOut(),) + for (int i = 0; i < mClient.audioChannelsIn(); ++i) { mInputConnections.emplace_back(isAudioRateIn(i)); @@ -149,6 +181,11 @@ public: mAudioOutputs.emplace_back(nullptr, 0, 0); } +// for (int i = 0; i < mClient.controlChannelsOut(); ++i) +// { +// mControlOutputs.emplace_back() +// } + set_calc_function(); Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1); } @@ -156,50 +193,61 @@ public: void next(int n) { Wrapper *w = static_cast(this); - auto &client = w->client(); - mControlsIterator.reset(mInBuf + client.audioChannelsIn()); +// auto &client = w->client(); + mControlsIterator.reset(mInBuf + mClient.audioChannelsIn()); w->setParams( mWorld->mVerbosity > 0, mWorld,mControlsIterator); // forward on inputs N + audio inputs as params const Unit *unit = this; - for (int i = 0; i < client.audioChannelsIn(); ++i) + for (int i = 0; i < mClient.audioChannelsIn(); ++i) { if (mInputConnections[i]) mAudioInputs[i].reset(IN(i), 0, fullBufferSize()); } - for (int i = 0; i < client.audioChannelsOut(); ++i) + for (int i = 0; i < mClient.audioChannelsOut(); ++i) { if (mOutputConnections[i]) mAudioOutputs[i].reset(out(i), 0, fullBufferSize()); } - client.process(mAudioInputs, mAudioOutputs); + for(int i = 0; i < mClient.controlChannelsOut();++i) + { + if(mOutputConnections[i]) mControlOutputs[i].reset(out(i),0,1); + } + mClient.process(mAudioInputs, mAudioOutputs); } - private: std::vector mInputConnections; std::vector mOutputConnections; std::vector mAudioInputs; std::vector mAudioOutputs; + std::vector mControlOutputs; FloatControlsIter mControlsIterator; +protected: + Client mClient; + }; -template class NonRealTime +template class NonRealTime { public: static void setup(InterfaceTable *ft, const char *name) { DefinePlugInCmd(name, launch, nullptr); } - NonRealTime() {} + NonRealTime(World *world,sc_msg_iter *args): + mClient{ClientFactory::create(world,args)} + {} void init(){}; static void launch(World *world, void *inUserData, struct sc_msg_iter *args, void *replyAddr) { - Wrapper *w = new Wrapper(); //this has to be on the heap, because it doesn't get destoryed until the async command is done + Wrapper *w = new Wrapper(world,args); //this has to be on the heap, because it doesn't get destoryed until the async command is done w->parseBuffers(w, world, args); int argsPosition = args->count; + auto argsRdPos = args->rdpos; Result result = validateParameters(w, world, args); if (!result.ok()) { std::cout << "FluCoMa Error " << Wrapper::getName() << ": " << result.message().c_str(); return; } - args->count = argsPosition; + args->count = argsPosition; + args->rdpos = argsRdPos; w->setParams(false, world, args); size_t msgSize = args->getbsize(); @@ -218,10 +266,13 @@ public: static bool tidyUp(World *world, void *data) { return static_cast(data)->tidyUp(world); } static void destroy(World *world, void *data) { delete static_cast(data); } +protected: + Client mClient; + private: - static Result validateParameters(Wrapper *w, World* world, sc_msg_iter *args) + static Result validateParameters(NonRealTime *w, World* world, sc_msg_iter *args) { - auto &c = w->client(); + auto &c = w->mClient; auto results = c.template checkParameterValues(world, args); for (auto &r : results) { @@ -233,7 +284,7 @@ private: void parseBuffers(Wrapper *w, World *world, sc_msg_iter *args) { - auto &c = w->client(); + auto &c = mClient; mBuffersIn.reserve(c.audioBuffersIn()); mInputs.reserve(c.audioBuffersIn()); @@ -261,8 +312,7 @@ private: bool process(World *world) { - Wrapper *wrapper = static_cast(this); - Result r = wrapper->client().process(mInputs, mOutputs); + Result r = mClient.process(mInputs, mOutputs); if(!r.ok()) { @@ -275,6 +325,8 @@ private: bool exchangeBuffers(World *world) { + + mClient.template forEachParamType(world); for (auto &b : mBuffersOut) b.assignToRT(world); return true; } @@ -286,6 +338,16 @@ private: return true; } + template + struct AssignBuffer + { + void operator()(typename BufferT::type& p, World* w) + { + if(auto b = static_cast(p.get())) + b->assignToRT(w); + } + }; + std::vector mBuffersIn; std::vector mBuffersOut; std::vector mInputs; @@ -294,28 +356,31 @@ private: const char * mName; }; -template class NonRealTimeAndRealTime : public RealTime, public NonRealTime +template class NonRealTimeAndRealTime : public RealTime, public NonRealTime { static void setup(InterfaceTable *ft, const char *name) { - RealTime::setup(ft, name); - NonRealTime::setup(ft, name); + RealTime::setup(ft, name); + NonRealTime::setup(ft, name); } }; // Template Specialisations for NRT/RT -template class FluidSCWrapperImpl; +template class FluidSCWrapperImpl; -template class FluidSCWrapperImpl : public NonRealTime -{}; +template class FluidSCWrapperImpl : public NonRealTime +{ +public: + FluidSCWrapperImpl(World* w, sc_msg_iter *args): NonRealTime(w,args){}; +}; -template class FluidSCWrapperImpl : public RealTime +template class FluidSCWrapperImpl : public RealTime {}; // Make base class(es), full of CRTP mixin goodness template -using FluidSCWrapperBase = FluidSCWrapperImpl, isNonRealTime, isRealTime>; +using FluidSCWrapperBase = FluidSCWrapperImpl, isNonRealTime, isRealTime>; } // namespace impl @@ -327,6 +392,10 @@ public: FluidSCWrapper() { impl::FluidSCWrapperBase::init(); } + FluidSCWrapper(World* w, sc_msg_iter *args): impl::FluidSCWrapperBase(w,args) + { impl::FluidSCWrapperBase::init(); } + + static const char *getName(const char *setName = nullptr) { static const char *name = nullptr; @@ -348,18 +417,18 @@ public: auto setParams(bool verbose, World* world, impl::FloatControlsIter& inputs) { - return mClient.template setParameterValues(verbose, world, inputs); + return impl::FluidSCWrapperBase::mClient.template setParameterValues(verbose, world, inputs); } auto setParams(bool verbose, World* world, sc_msg_iter *args) { - return mClient.template setParameterValues(verbose,world, args); + return impl::FluidSCWrapperBase::mClient.template setParameterValues(verbose,world, args); } - Client &client() { return mClient; } +// Client &client() { return mClient; } -private: - Client mClient; +//private: +// Client mClient; }; template void makeSCWrapper(InterfaceTable *ft, const char *name) diff --git a/include/SCBufferAdaptor.hpp b/include/SCBufferAdaptor.hpp index 2819c11..b753a15 100644 --- a/include/SCBufferAdaptor.hpp +++ b/include/SCBufferAdaptor.hpp @@ -66,15 +66,18 @@ public: SCBufferAdaptor& operator=(SCBufferAdaptor&&) = default; - SCBufferAdaptor(long bufnum, World *world, bool rt = false) + SCBufferAdaptor(long bufnum,World *world, bool rt = false) : NRTBuf(world, bufnum, rt) , mBufnum(bufnum) , mWorld(world) { } + SCBufferAdaptor() = default; + ~SCBufferAdaptor(){ cleanUp(); } + void assignToRT(World *rtWorld) { SndBuf *rtBuf = World_GetBuf(rtWorld, mBufnum); diff --git a/src/FluidNMFMatch/FluidNMFMatch.cpp b/src/FluidNMFMatch/FluidNMFMatch.cpp index 60f0a13..6eec74e 100644 --- a/src/FluidNMFMatch/FluidNMFMatch.cpp +++ b/src/FluidNMFMatch/FluidNMFMatch.cpp @@ -1,134 +1,15 @@ // A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899) -#include "SC_PlugIn.hpp" -#include "data/FluidTensor.hpp" -#include "fdNRTBase.hpp" -#include "clients/rt/NMFMatch.hpp" - - +#include +#include static InterfaceTable *ft; -namespace fluid { -namespace nmf{ - class FDNMFMatch: public SCUnit - { - using Client = client::NMFMatch; - using AudioSignalWrapper = Client::AudioSignal; - using SignalWrapper = Client::Signal; - using SignalPointer = std::unique_ptr; - using ClientPointer = std::unique_ptr; - template - using SignalArray = std::array; - using SignalVector = std::vector; - - public: - FDNMFMatch() - { - //Order of args - //psize hszie pthresh hthresh Window size, Hop size, FFT Size - - mClient = ClientPointer(new Client(65536)); - - setParams(true); - - bool isOK; - std::string feedback; - - std::tie(isOK, feedback) = mClient->sanityCheck(); - if(!isOK) - { - std::cout << "FluidNMFMatch Error: " << feedback << '\n'; - - mCalcFunc = ClearUnitOutputs; - - return; - } - - mRank = client::lookupParam("rank", mClient->getParams()).getLong(); - - - mClient->setHostBufferSize(bufferSize()); - mClient->reset(); - - inputSignals[0] = SignalPointer(new AudioSignalWrapper()); - - outputSignals.resize(mRank); - for(size_t i = 0; i < mRank; ++i) - outputSignals[i].reset(new Client::ScalarSignal()); - - mCalcFunc = make_calc_function(); - Unit* unit = this; - ClearUnitOutputs(unit,1); - } - - ~FDNMFMatch() {} - - private: - - void setParams(bool instantiation) - { - assert(mClient); - for(size_t i = 0; i < mClient->getParams().size(); ++i) - { - client::Instance& p = mClient->getParams()[i]; - if(!instantiation && p.getDescriptor().instantiation()) - continue; - switch(p.getDescriptor().getType()) - { - case client::Type::kLong: - p.setLong(in0(i + 1)); - p.checkRange(); - break; - case client::Type::kFloat: { - p.setFloat(in0(i + 1)); - p.checkRange(); - } - break; - case client::Type::kBuffer: { - long bufnum = static_cast(in0(i+1)); - wrapper::RTBufferView* currentBuf = static_cast(p.getBuffer()); - - - if(bufnum >= 0 && (currentBuf? (currentBuf->bufnum() != bufnum) : true)){ - wrapper::RTBufferView* buf = new wrapper::RTBufferView(mWorld,bufnum); - p.setBuffer(buf); - } - break; - } - default: - break; - } - } - } - - void next(int numsamples) - { - setParams(false); - const float* input = zin(0); - const float inscalar = in0(0); - inputSignals[0]->set(const_cast(input), inscalar); - for(size_t i = 0; i < mRank; ++i) - outputSignals[i]->set(out(i),out0(i)); - - mClient->doProcessNoOla(inputSignals.begin(),inputSignals.end(), outputSignals.begin(), outputSignals.end(), mWorld->mFullRate.mBufLength ,1,mRank); - for(size_t i = 0; i < mRank; ++i) - out0(i) = outputSignals[i]->next(); - } - - - - size_t mRank; - ClientPointer mClient; - SignalArray<1> inputSignals; - SignalVector outputSignals; - }; -} -} PluginLoad(FluidSTFTUGen) { ft = inTable; - registerUnit(ft, "FluidNMFMatch"); + using namespace fluid::client; + makeSCWrapper>(ft, "FluidNMFMatch"); }