Feature/add multiple out support to kr (#164)

* Tag release to correct commit

* release: delete pre-existing

* almost working class def and no difference to the wrapper

* 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

* input shape now working

* correct input count division (was the wrong way round)

* computes the real size of the input to decline the output size

* and finally a working class. We're all set!

* troubleshooting prints all over

* new proper class for proper algo

* remove the debugging pritns

* clang-format-ed

* pre-clang-format

* clang-format-ed with the right style sheet

---------

Co-authored-by: Owen Green <gungwho@gmail.com>
nix
tremblap 2 years ago committed by GitHub
parent 0daeef1466
commit 7fbaf8fdab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -24,10 +24,10 @@ template <typename C>
class FluidSCWrapper : public impl::FluidSCWrapperBase<C> class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
{ {
using FloatControlsIter = impl::FloatControlsIter; using FloatControlsIter = impl::FloatControlsIter;
//I would like to template these to something more scaleable, but baby steps // I would like to template these to something more scaleable, but baby steps
friend class impl::RealTime<C,FluidSCWrapper>; friend class impl::RealTime<C, FluidSCWrapper>;
friend class impl::NonRealTime<C,FluidSCWrapper>; friend class impl::NonRealTime<C, FluidSCWrapper>;
static void doVersion(Unit*, sc_msg_iter*) static void doVersion(Unit*, sc_msg_iter*)
{ {
@ -38,12 +38,14 @@ class FluidSCWrapper : public impl::FluidSCWrapperBase<C>
bool mInit{false}; bool mInit{false};
public: public:
template <size_t N, typename T> template <size_t N, typename T>
using ArgumentSetter = typename ClientParams<FluidSCWrapper>::template Setter<sc_msg_iter, N, T>; using ArgumentSetter =
typename ClientParams<FluidSCWrapper>::template Setter<sc_msg_iter, N, T>;
template <size_t N, typename T> template <size_t N, typename T>
using ControlSetter = typename ClientParams<FluidSCWrapper>::template Setter<FloatControlsIter, N, T>; using ControlSetter =
typename ClientParams<FluidSCWrapper>::template Setter<FloatControlsIter,
N, T>;
using Client = C; using Client = C;
using ParamSetType = typename C::ParamSetType; using ParamSetType = typename C::ParamSetType;
@ -66,14 +68,14 @@ public:
getInterfaceTable(ft); getInterfaceTable(ft);
impl::FluidSCWrapperBase<Client>::setup(ft, name); impl::FluidSCWrapperBase<Client>::setup(ft, name);
ft->fDefineUnitCmd(name, "version", doVersion); ft->fDefineUnitCmd(name, "version", doVersion);
std::string commandName("/"); std::string commandName("/");
commandName += getName(); commandName += getName();
commandName += "/version"; commandName += "/version";
ft->fDefinePlugInCmd(commandName.c_str(), ft->fDefinePlugInCmd(
[](World*, void*, sc_msg_iter*, void*){ doVersion(nullptr,nullptr); }, commandName.c_str(),
nullptr); [](World*, void*, sc_msg_iter*, void*) { doVersion(nullptr, nullptr); },
nullptr);
} }
static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs, static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs,
@ -81,58 +83,52 @@ public:
bool initialized = true) bool initialized = true)
{ {
bool verbose = x->mWorld->mVerbosity > 0; bool verbose = x->mWorld->mVerbosity > 0;
using Reportage = decltype(static_cast<FluidSCWrapper*>(x)->mReportage); using Reportage = decltype(static_cast<FluidSCWrapper*>(x)->mReportage);
Reportage* reportage = initialized ? &(static_cast<FluidSCWrapper*>(x)->mReportage) : new Reportage(); Reportage* reportage = initialized
? &(static_cast<FluidSCWrapper*>(x)->mReportage)
: new Reportage();
p.template setParameterValuesRT<ControlSetter>( p.template setParameterValuesRT<ControlSetter>(
verbose ? reportage : nullptr, x, inputs, p, alloc); verbose ? reportage : nullptr, x, inputs, p, alloc);
if (constrain) p.constrainParameterValuesRT(verbose ? reportage : nullptr); if (constrain) p.constrainParameterValuesRT(verbose ? reportage : nullptr);
if(verbose) if (verbose)
{ {
for(auto& r:*reportage) for (auto& r : *reportage)
{ {
if(!r.ok()) printResult(x->mParent->mNode.mWorld, r); if (!r.ok()) printResult(x->mParent->mNode.mWorld, r);
} }
} }
if(!initialized) delete reportage; if (!initialized) delete reportage;
return p; return p;
} }
// static void printResult(SharedState<C>& x, Result& r) static void printResult(World* w, Result& r)
// {
// if (!x.get() || !x->mNodeAlive) return;
// FluidSCWrapper::printResult(x->mNode->mWorld, r);
// }
static void printResult(World* w,Result& r)
{ {
switch (r.status()) switch (r.status())
{ {
case Result::Status::kWarning: case Result::Status::kWarning: {
{ if (!w || w->mVerbosity > 0)
if (!w || w->mVerbosity > 0) std::cout << "WARNING: " << getName() << " - " << r.message().c_str()
std::cout << "WARNING: " << getName() << " - " << r.message().c_str() << '\n'; << '\n';
break; break;
} }
case Result::Status::kError: case Result::Status::kError: {
{ std::cout << "ERROR: " << getName() << " - " << r.message().c_str()
std::cout << "ERROR: " << getName() << " - " << r.message().c_str() << '\n'; << '\n';
break; break;
} }
case Result::Status::kCancelled: case Result::Status::kCancelled: {
{ std::cout << getName() << ": Task cancelled\n" << '\n';
std::cout << getName() << ": Task cancelled\n" << '\n'; break;
break; }
} default: {
default: }
{ }
}
}
} }
private: private:
std::array<Result, Client::getParameterDescriptors().size()> mReportage; std::array<Result, Client::getParameterDescriptors().size()> mReportage;
}; };

@ -1,8 +1,8 @@
#pragma once #pragma once
#include <Eigen/Core>
#include <data/FluidMemory.hpp> #include <data/FluidMemory.hpp>
#include <SC_PlugIn.hpp> #include <SC_PlugIn.hpp>
#include <Eigen/Core>
namespace fluid { namespace fluid {
namespace client { namespace client {
@ -82,9 +82,10 @@ struct RealTimeBase
std::forward<Result&>(countScan)); std::forward<Result&>(countScan));
return 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 && assert(!(client.audioChannelsOut() > 0 &&
client.controlChannelsOut().count > 0) && client.controlChannelsOut().count > 0) &&
@ -92,7 +93,7 @@ struct RealTimeBase
client.sampleRate(unit.fullSampleRate()); client.sampleRate(unit.fullSampleRate());
mInputConnections.reserve(asUnsigned(client.audioChannelsIn())); mInputConnections.reserve(asUnsigned(client.audioChannelsIn()));
mOutputConnections.reserve(asUnsigned(client.audioChannelsOut())); mOutputConnections.reserve(asUnsigned(client.audioChannelsOut()));
mContext = FluidContext(unit.fullBufferSize(), alloc); mContext = FluidContext(unit.fullBufferSize(), alloc);
Result r; Result r;
if (!(r = expectedSize(controls)).ok()) if (!(r = expectedSize(controls)).ok())
{ {
@ -113,16 +114,22 @@ struct RealTimeBase
} }
else if (client.controlChannelsIn()) else if (client.controlChannelsIn())
{ {
mControlInputBuffer.resize(unit.mSpecialIndex + 1); mControlInputBuffer.resize(client.controlChannelsIn(),
mAudioInputs.emplace_back(mControlInputBuffer); (unit.mSpecialIndex + 1) /
client.controlChannelsIn());
for (index i = 0; i < client.controlChannelsIn(); ++i)
{
mAudioInputs.emplace_back(mControlInputBuffer.row(i));
}
mInputMapper = &RealTimeBase::mapControlInputs; mInputMapper = &RealTimeBase::mapControlInputs;
} }
else mInputMapper = &RealTimeBase::mapNoOp; else { mInputMapper = &RealTimeBase::mapNoOp; }
index outputSize = client.controlChannelsOut().size > 0 index outputSize = client.controlChannelsOut().size > 0
? std::max(client.audioChannelsOut(), ? std::max(client.audioChannelsOut(),
client.maxControlChannelsOut()) client.maxControlChannelsOut())
: unit.mSpecialIndex + 1; : (unit.mSpecialIndex + 1);
mOutputs.reserve(asUnsigned(outputSize)); mOutputs.reserve(asUnsigned(outputSize));
if (client.audioChannelsOut()) if (client.audioChannelsOut())
@ -132,7 +139,7 @@ struct RealTimeBase
mOutputConnections.emplace_back(true); mOutputConnections.emplace_back(true);
mOutputs.emplace_back(nullptr, 0, 0); mOutputs.emplace_back(nullptr, 0, 0);
} }
mOutMapperPre = &RealTimeBase::mapAudioOutputs; mOutMapperPre = &RealTimeBase::mapAudioOutputs;
mOutMapperPost = &RealTimeBase::mapNoOp; mOutMapperPost = &RealTimeBase::mapNoOp;
} }
@ -177,19 +184,28 @@ struct RealTimeBase
} }
} }
void mapControlInputs(SCUnit& unit, Client&) void mapControlInputs(SCUnit& unit, Client& client)
{ {
for (index i = 0; i < unit.mSpecialIndex + 1; ++i) assert((unit.mSpecialIndex + 1) % client.controlChannelsIn() == 0 &&
"Control channels can't be mapped");
index itemsPerChannel =
(unit.mSpecialIndex + 1) / client.controlChannelsIn();
for (index i = 0, offset = 0; i < client.controlChannelsIn();
++i, offset += itemsPerChannel)
{ {
assert(i <= std::numeric_limits<int>::max()); for (index j = 0; j < itemsPerChannel; ++j)
mControlInputBuffer[i] = unit.in0(static_cast<int>(i)); {
assert(j <= std::numeric_limits<int>::max());
mControlInputBuffer(i, j) = unit.in0(static_cast<int>(offset + j));
}
} }
} }
void mapControlOutputs(SCUnit& unit, Client&) void mapControlOutputs(SCUnit& unit, Client&)
{ {
index numOuts = std::min<index>(mControlOutputBuffer.size(),unit.mNumOutputs); index numOuts =
std::min<index>(mControlOutputBuffer.size(), unit.mNumOutputs);
for (index i = 0; i < numOuts; ++i) for (index i = 0; i < numOuts; ++i)
{ {
assert(i <= std::numeric_limits<int>::max()); assert(i <= std::numeric_limits<int>::max());
@ -205,9 +221,9 @@ struct RealTimeBase
IsModel_t<Client>::value ? !mPrevTrig && unit.in0(0) > 0 : false; IsModel_t<Client>::value ? !mPrevTrig && unit.in0(0) > 0 : false;
mPrevTrig = trig; mPrevTrig = trig;
#ifdef EIGEN_RUNTIME_NO_MALLOC #ifdef EIGEN_RUNTIME_NO_MALLOC
Eigen::internal::set_is_malloc_allowed(false); Eigen::internal::set_is_malloc_allowed(false);
#endif #endif
if (updateParams) if (updateParams)
{ {
Wrapper::setParams(&unit, params, controls, alloc); Wrapper::setParams(&unit, params, controls, alloc);
@ -218,9 +234,9 @@ struct RealTimeBase
(this->*mOutMapperPre)(unit, client); (this->*mOutMapperPre)(unit, client);
client.process(mAudioInputs, mOutputs, mContext); client.process(mAudioInputs, mOutputs, mContext);
(this->*mOutMapperPost)(unit, client); (this->*mOutMapperPost)(unit, client);
#ifdef EIGEN_RUNTIME_NO_MALLOC #ifdef EIGEN_RUNTIME_NO_MALLOC
Eigen::internal::set_is_malloc_allowed(true); //not really Eigen::internal::set_is_malloc_allowed(true); // not really
#endif #endif
} }
private: private:
@ -228,7 +244,7 @@ private:
std::vector<bool> mOutputConnections; std::vector<bool> mOutputConnections;
std::vector<HostVector> mAudioInputs; std::vector<HostVector> mAudioInputs;
std::vector<HostVector> mOutputs; std::vector<HostVector> mOutputs;
FluidTensor<float, 1> mControlInputBuffer; FluidTensor<float, 2> mControlInputBuffer;
FluidTensor<float, 1> mControlOutputBuffer; FluidTensor<float, 1> mControlOutputBuffer;
bool mPrevTrig; bool mPrevTrig;
IOMapFn mInputMapper; IOMapFn mInputMapper;

Loading…
Cancel
Save