Make client factory, attempts to initialise client with constructor args from istantiation params.Add NMF wrapper

include/FluidSCWrapper.hpp
include/SCBufferAdaptor.hpp
src/FluidNMFMatch/FluidNMFMatch.cpp
nix
Owen Green 7 years ago
parent 5496a72a18
commit 9ab5dc3d56

@ -29,7 +29,7 @@ template <size_t N, typename T, msg_iter_method<T> Method> struct GetArgument
{ {
T operator()(World* w, sc_msg_iter *args) T operator()(World* w, sc_msg_iter *args)
{ {
T r = (args->*Method)(0); T r = (args->*Method)(T{0});
return r; return r;
} }
}; };
@ -63,22 +63,29 @@ template <size_t N, typename T> struct GetControl
}; };
template <size_t N> struct ArgumentGetter<N, FloatT> : public GetArgument<N, float, &sc_msg_iter::getf> template <size_t N> struct ArgumentGetter<N, FloatT> : public GetArgument<N, float, &sc_msg_iter::getf>
{}; {
// ArgumentGetter() { std::cout << "FloatT @ " << N << '\n'; }
};
template <size_t N> struct ArgumentGetter<N, LongT> : public GetArgument<N, int32, &sc_msg_iter::geti> template <size_t N> struct ArgumentGetter<N, LongT> : public GetArgument<N, int32, &sc_msg_iter::geti>
{}; {
// ArgumentGetter() { std::cout << "LongT @ " << N << '\n'; }
};
template <size_t N> struct ArgumentGetter<N, EnumT> : public GetArgument<N, int32, &sc_msg_iter::geti> template <size_t N> struct ArgumentGetter<N, EnumT> : public GetArgument<N, int32, &sc_msg_iter::geti>
{}; {
// ArgumentGetter() { std::cout << "Enum @ " << N << '\n'; }
};
template <size_t N> struct ArgumentGetter<N, BufferT> template <size_t N> struct ArgumentGetter<N, BufferT>
{ {
auto operator()(World* w, sc_msg_iter *args) // ArgumentGetter() { std::cout << "Buffer @ " << N << '\n'; }
auto operator() (World* w, sc_msg_iter *args)
{ {
typename LongT::type bufnum = args->geti(-1);
long bufnum = args->geti(-1); return std::unique_ptr<BufferAdaptor>(bufnum >= 0 ? new SCBufferAdaptor(bufnum,w) : nullptr);
return std::unique_ptr<BufferAdaptor>(new SCBufferAdaptor(bufnum,w));
} }
}; };
@ -98,10 +105,10 @@ template <size_t N, typename T> struct ControlGetter : public GetControl<N, type
template <size_t N> struct ControlGetter<N, BufferT> template <size_t N> struct ControlGetter<N, BufferT>
{ {
auto operator()(World* w, FloatControlsIter& iter) auto operator() (World* w, FloatControlsIter& iter)
{ {
long bufnum = iter.next(); typename LongT::type bufnum = iter.next();
return std::unique_ptr<BufferAdaptor>(new SCBufferAdaptor(bufnum,w)); return std::unique_ptr<BufferAdaptor>(bufnum >= 0 ? new SCBufferAdaptor(bufnum,w): nullptr);
} }
}; };
@ -114,9 +121,30 @@ struct ControlGetter<N,FloatPairsArrayT>
} }
}; };
template<typename Client, typename Args, template <size_t,typename> class Fetcher>
struct ClientFactory
{
static Client create(World* world, Args* args)
{
return createImpl(world, args, FixedParamIndices{});
}
private:
using FixedParamIndices = typename Client::FixedParams;
template<size_t N>
using ThisParamType = typename Client::template ParamDescriptorTypeAt<N>;
template<size_t...Is>
static Client createImpl(World* world, Args* args, std::index_sequence<Is...>)
{
return Client{Fetcher<Is, ThisParamType<Is>>{}(world,*args)...};
}
};
//template <size_t N, typename //template <size_t N, typename
template <class Wrapper> class RealTime : public SCUnit template <typename Client,class Wrapper> class RealTime : public SCUnit
{ {
using HostVector = FluidTensorView<float, 1>; using HostVector = FluidTensorView<float, 1>;
// using Client = typename Wrapper::ClientType; // using Client = typename Wrapper::ClientType;
@ -124,18 +152,22 @@ template <class Wrapper> class RealTime : public SCUnit
public: public:
static void setup(InterfaceTable *ft, const char *name) { registerUnit<Wrapper>(ft, name); } static void setup(InterfaceTable *ft, const char *name) { registerUnit<Wrapper>(ft, name); }
RealTime():mControlsIterator{nullptr,0} {} RealTime():
SCUnit{},
mControlsIterator{mInBuf + mSpecialIndex + 1,mNumInputs - mSpecialIndex - 1},
mClient{ClientFactory<Client,FloatControlsIter,ControlGetter>::create(mWorld,&mControlsIterator)}
{}
void init() void init()
{ {
Wrapper *w = static_cast<Wrapper *>(this); assert(!(mClient.audioChannelsOut() > 0 && mClient.controlChannelsOut() > 0) && "Client can't have both audio and control outputs");
auto &mClient = w->client();
mInputConnections.reserve(mClient.audioChannelsIn()); mInputConnections.reserve(mClient.audioChannelsIn());
mOutputConnections.reserve(mClient.audioChannelsOut()); mOutputConnections.reserve(mClient.audioChannelsOut());
mAudioInputs.reserve(mClient.audioChannelsIn()); mAudioInputs.reserve(mClient.audioChannelsIn());
mAudioOutputs.reserve(mClient.audioChannelsOut()); mAudioOutputs.reserve(mClient.audioChannelsOut());
mControlOutputs.reserve(mClient.controlChannelsOut());
// mControlOutputData.resize(mClient.controlChannelsOut(),)
for (int i = 0; i < mClient.audioChannelsIn(); ++i) for (int i = 0; i < mClient.audioChannelsIn(); ++i)
{ {
@ -149,6 +181,11 @@ public:
mAudioOutputs.emplace_back(nullptr, 0, 0); mAudioOutputs.emplace_back(nullptr, 0, 0);
} }
// for (int i = 0; i < mClient.controlChannelsOut(); ++i)
// {
// mControlOutputs.emplace_back()
// }
set_calc_function<RealTime, &RealTime::next>(); set_calc_function<RealTime, &RealTime::next>();
Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1); Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1);
} }
@ -156,43 +193,53 @@ public:
void next(int n) void next(int n)
{ {
Wrapper *w = static_cast<Wrapper *>(this); Wrapper *w = static_cast<Wrapper *>(this);
auto &client = w->client(); // auto &client = w->client();
mControlsIterator.reset(mInBuf + client.audioChannelsIn()); mControlsIterator.reset(mInBuf + mClient.audioChannelsIn());
w->setParams( mWorld->mVerbosity > 0, mWorld,mControlsIterator); // forward on inputs N + audio inputs as params w->setParams( mWorld->mVerbosity > 0, mWorld,mControlsIterator); // forward on inputs N + audio inputs as params
const Unit *unit = this; 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()); 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()); 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: private:
std::vector<bool> mInputConnections; std::vector<bool> mInputConnections;
std::vector<bool> mOutputConnections; std::vector<bool> mOutputConnections;
std::vector<HostVector> mAudioInputs; std::vector<HostVector> mAudioInputs;
std::vector<HostVector> mAudioOutputs; std::vector<HostVector> mAudioOutputs;
std::vector<HostVector> mControlOutputs;
FloatControlsIter mControlsIterator; FloatControlsIter mControlsIterator;
protected:
Client mClient;
}; };
template <class Wrapper> class NonRealTime template <typename Client, typename Wrapper> class NonRealTime
{ {
public: public:
static void setup(InterfaceTable *ft, const char *name) { DefinePlugInCmd(name, launch, nullptr); } static void setup(InterfaceTable *ft, const char *name) { DefinePlugInCmd(name, launch, nullptr); }
NonRealTime() {} NonRealTime(World *world,sc_msg_iter *args):
mClient{ClientFactory<Client, sc_msg_iter, ArgumentGetter>::create(world,args)}
{}
void init(){}; void init(){};
static void launch(World *world, void *inUserData, struct sc_msg_iter *args, void *replyAddr) 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); w->parseBuffers(w, world, args);
int argsPosition = args->count; int argsPosition = args->count;
auto argsRdPos = args->rdpos;
Result result = validateParameters(w, world, args); Result result = validateParameters(w, world, args);
if (!result.ok()) if (!result.ok())
{ {
@ -200,6 +247,7 @@ public:
return; return;
} }
args->count = argsPosition; args->count = argsPosition;
args->rdpos = argsRdPos;
w->setParams(false, world, args); w->setParams(false, world, args);
size_t msgSize = args->getbsize(); size_t msgSize = args->getbsize();
@ -218,10 +266,13 @@ public:
static bool tidyUp(World *world, void *data) { return static_cast<Wrapper *>(data)->tidyUp(world); } static bool tidyUp(World *world, void *data) { return static_cast<Wrapper *>(data)->tidyUp(world); }
static void destroy(World *world, void *data) { delete static_cast<Wrapper *>(data); } static void destroy(World *world, void *data) { delete static_cast<Wrapper *>(data); }
protected:
Client mClient;
private: 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<ArgumentGetter>(world, args); auto results = c.template checkParameterValues<ArgumentGetter>(world, args);
for (auto &r : results) for (auto &r : results)
{ {
@ -233,7 +284,7 @@ private:
void parseBuffers(Wrapper *w, World *world, sc_msg_iter *args) void parseBuffers(Wrapper *w, World *world, sc_msg_iter *args)
{ {
auto &c = w->client(); auto &c = mClient;
mBuffersIn.reserve(c.audioBuffersIn()); mBuffersIn.reserve(c.audioBuffersIn());
mInputs.reserve(c.audioBuffersIn()); mInputs.reserve(c.audioBuffersIn());
@ -261,8 +312,7 @@ private:
bool process(World *world) bool process(World *world)
{ {
Wrapper *wrapper = static_cast<Wrapper *>(this); Result r = mClient.process(mInputs, mOutputs);
Result r = wrapper->client().process(mInputs, mOutputs);
if(!r.ok()) if(!r.ok())
{ {
@ -275,6 +325,8 @@ private:
bool exchangeBuffers(World *world) bool exchangeBuffers(World *world)
{ {
mClient.template forEachParamType<BufferT,AssignBuffer>(world);
for (auto &b : mBuffersOut) b.assignToRT(world); for (auto &b : mBuffersOut) b.assignToRT(world);
return true; return true;
} }
@ -286,6 +338,16 @@ private:
return true; return true;
} }
template<size_t N,typename T>
struct AssignBuffer
{
void operator()(typename BufferT::type& p, World* w)
{
if(auto b = static_cast<SCBufferAdaptor*>(p.get()))
b->assignToRT(w);
}
};
std::vector<SCBufferAdaptor> mBuffersIn; std::vector<SCBufferAdaptor> mBuffersIn;
std::vector<SCBufferAdaptor> mBuffersOut; std::vector<SCBufferAdaptor> mBuffersOut;
std::vector<BufferProcessSpec> mInputs; std::vector<BufferProcessSpec> mInputs;
@ -294,28 +356,31 @@ private:
const char * mName; const char * mName;
}; };
template <typename Wrapper> class NonRealTimeAndRealTime : public RealTime<Wrapper>, public NonRealTime<Wrapper> template <typename Client, typename Wrapper> class NonRealTimeAndRealTime : public RealTime<Client,Wrapper>, public NonRealTime<Client,Wrapper>
{ {
static void setup(InterfaceTable *ft, const char *name) static void setup(InterfaceTable *ft, const char *name)
{ {
RealTime<Wrapper>::setup(ft, name); RealTime<Client,Wrapper>::setup(ft, name);
NonRealTime<Wrapper>::setup(ft, name); NonRealTime<Client,Wrapper>::setup(ft, name);
} }
}; };
// Template Specialisations for NRT/RT // Template Specialisations for NRT/RT
template <typename Wrapper, typename NRT, typename RT> class FluidSCWrapperImpl; template <typename Client, typename Wrapper, typename NRT, typename RT> class FluidSCWrapperImpl;
template <typename Wrapper> class FluidSCWrapperImpl<Wrapper, std::true_type, std::false_type> : public NonRealTime<Wrapper> template <typename Client, typename Wrapper> class FluidSCWrapperImpl<Client, Wrapper, std::true_type, std::false_type> : public NonRealTime<Client, Wrapper>
{}; {
public:
FluidSCWrapperImpl(World* w, sc_msg_iter *args): NonRealTime<Client, Wrapper>(w,args){};
};
template <typename Wrapper> class FluidSCWrapperImpl<Wrapper, std::false_type, std::true_type> : public RealTime<Wrapper> template <typename Client, typename Wrapper> class FluidSCWrapperImpl<Client, Wrapper, std::false_type, std::true_type> : public RealTime<Client, Wrapper>
{}; {};
// Make base class(es), full of CRTP mixin goodness // Make base class(es), full of CRTP mixin goodness
template <typename Client> template <typename Client>
using FluidSCWrapperBase = FluidSCWrapperImpl<FluidSCWrapper<Client>, isNonRealTime<Client>, isRealTime<Client>>; using FluidSCWrapperBase = FluidSCWrapperImpl<Client, FluidSCWrapper<Client>, isNonRealTime<Client>, isRealTime<Client>>;
} // namespace impl } // namespace impl
@ -327,6 +392,10 @@ public:
FluidSCWrapper() { impl::FluidSCWrapperBase<Client>::init(); } FluidSCWrapper() { impl::FluidSCWrapperBase<Client>::init(); }
FluidSCWrapper(World* w, sc_msg_iter *args): impl::FluidSCWrapperBase<Client>(w,args)
{ impl::FluidSCWrapperBase<Client>::init(); }
static const char *getName(const char *setName = nullptr) static const char *getName(const char *setName = nullptr)
{ {
static const char *name = nullptr; static const char *name = nullptr;
@ -348,18 +417,18 @@ public:
auto setParams(bool verbose, World* world, impl::FloatControlsIter& inputs) auto setParams(bool verbose, World* world, impl::FloatControlsIter& inputs)
{ {
return mClient.template setParameterValues<impl::ControlGetter>(verbose, world, inputs); return impl::FluidSCWrapperBase<Client>::mClient.template setParameterValues<impl::ControlGetter>(verbose, world, inputs);
} }
auto setParams(bool verbose, World* world, sc_msg_iter *args) auto setParams(bool verbose, World* world, sc_msg_iter *args)
{ {
return mClient.template setParameterValues<impl::ArgumentGetter>(verbose,world, args); return impl::FluidSCWrapperBase<Client>::mClient.template setParameterValues<impl::ArgumentGetter>(verbose,world, args);
} }
Client &client() { return mClient; } // Client &client() { return mClient; }
private: //private:
Client mClient; // Client mClient;
}; };
template <typename Client> void makeSCWrapper(InterfaceTable *ft, const char *name) template <typename Client> void makeSCWrapper(InterfaceTable *ft, const char *name)

@ -66,15 +66,18 @@ public:
SCBufferAdaptor& operator=(SCBufferAdaptor&&) = default; SCBufferAdaptor& operator=(SCBufferAdaptor&&) = default;
SCBufferAdaptor(long bufnum, World *world, bool rt = false) SCBufferAdaptor(long bufnum,World *world, bool rt = false)
: NRTBuf(world, bufnum, rt) : NRTBuf(world, bufnum, rt)
, mBufnum(bufnum) , mBufnum(bufnum)
, mWorld(world) , mWorld(world)
{ {
} }
SCBufferAdaptor() = default; SCBufferAdaptor() = default;
~SCBufferAdaptor(){ cleanUp(); }
void assignToRT(World *rtWorld) void assignToRT(World *rtWorld)
{ {
SndBuf *rtBuf = World_GetBuf(rtWorld, mBufnum); SndBuf *rtBuf = World_GetBuf(rtWorld, mBufnum);

@ -1,134 +1,15 @@
// A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Unions Horizon 2020 research and innovation programme (grant agreement No 725899) // A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Unions Horizon 2020 research and innovation programme (grant agreement No 725899)
#include "SC_PlugIn.hpp" #include <clients/rt/NMFMatch.hpp>
#include "data/FluidTensor.hpp" #include <FluidSCWrapper.hpp>
#include "fdNRTBase.hpp"
#include "clients/rt/NMFMatch.hpp"
static InterfaceTable *ft; static InterfaceTable *ft;
namespace fluid {
namespace nmf{
class FDNMFMatch: public SCUnit
{
using Client = client::NMFMatch<double,float>;
using AudioSignalWrapper = Client::AudioSignal;
using SignalWrapper = Client::Signal<float>;
using SignalPointer = std::unique_ptr<SignalWrapper>;
using ClientPointer = std::unique_ptr<Client>;
template <size_t N>
using SignalArray = std::array<SignalPointer,N>;
using SignalVector = std::vector<SignalPointer>;
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<FDNMFMatch,&FDNMFMatch::next>();
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<long>(in0(i+1));
wrapper::RTBufferView* currentBuf = static_cast<wrapper::RTBufferView*>(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<float*>(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) { PluginLoad(FluidSTFTUGen) {
ft = inTable; ft = inTable;
registerUnit<fluid::nmf::FDNMFMatch>(ft, "FluidNMFMatch"); using namespace fluid::client;
makeSCWrapper<NMFMatch<double, float>>(ft, "FluidNMFMatch");
} }

Loading…
Cancel
Save