Enable control inputs, change control output layout

nix
Owen Green 4 years ago
parent 78a7418fef
commit 120dd3e722

@ -1,169 +1,229 @@
#pragma once #pragma once
#include <SC_PlugIn.hpp> #include <SC_PlugIn.hpp>
namespace fluid{ namespace fluid {
namespace client{ namespace client {
namespace impl{ namespace impl {
template <typename Client, class Wrapper>
struct RealTimeBase
{ template <typename Client, class Wrapper>
using HostVector = FluidTensorView<float, 1>; struct RealTimeBase
using Params = typename Client::ParamSetType; {
template<typename T, bool> using IOMapFn = void (RealTimeBase::*)(SCUnit&, Client&);
struct doExpectedCount; using HostVector = FluidTensorView<float, 1>;
using Params = typename Client::ParamSetType;
template<typename T> template <typename T, bool>
struct doExpectedCount<T, false> struct doExpectedCount;
{
static void count(const T& d,FloatControlsIter& c,Result& status) template <typename T>
{ struct doExpectedCount<T, false>
if(!status.ok()) return; {
static void count(const T& d, FloatControlsIter& c, Result& status)
if(c.remain()) {
{ if (!status.ok()) return;
index statedSize = d.fixedSize;
if (c.remain())
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();
}
}
};
template<typename T>
struct doExpectedCount<T, true>
{
static void count(const T& d,FloatControlsIter& c,Result& status)
{
if(!status.ok()) return;
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();
}
}
};
template<size_t N, typename T>
struct ExpectedCount{
void operator ()(const T& descriptor,FloatControlsIter& c, Result& status)
{ {
doExpectedCount<T,IsSharedClientRef<typename T::type>::value>::count(descriptor,c,status); 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();
} }
}; }
};
Result expectedSize(FloatControlsIter& controls) template <typename T>
struct doExpectedCount<T, true>
{
static void count(const T& d, FloatControlsIter& c, Result& status)
{ {
if(controls.size() < Client::getParameterDescriptors().count()) if (!status.ok()) return;
if (c.remain())
{ {
return {Result::Status::kError,"Fewer parameters than exepected. Got ", controls.size(), "expect at least", Client::getParameterDescriptors().count()}; 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();
} }
Result countScan;
Client::getParameterDescriptors().template iterate<ExpectedCount>(
std::forward<FloatControlsIter&>(controls),
std::forward<Result&>(countScan));
return countScan;
} }
};
template <size_t N, typename T>
struct ExpectedCount
{
void operator()(const T& descriptor, FloatControlsIter& c, Result& status)
{
doExpectedCount<T, IsSharedClientRef<typename T::type>::value>::count(
descriptor, c, status);
}
};
// static index ControlOffset(Unit* unit) { return unit->mSpecialIndex + 1; } Result expectedSize(FloatControlsIter& controls)
// static index ControlSize(Unit* unit) { return static_cast<index>(unit->mNumInputs) - unit->mSpecialIndex - 1 -(IsModel_t<Client>::value ? 1 : 0); } {
if (controls.size() < Client::getParameterDescriptors().count())
void init(SCUnit& unit, Client& client, FloatControlsIter& controls)
{ {
assert(!(client.audioChannelsOut() > 0 && client.controlChannelsOut() > 0) &&"Client can't have both audio and control outputs"); return {Result::Status::kError, "Fewer parameters than exepected. Got ",
// consoltr.reset(unit.mInBuf + unit.mSpecialIndex + 1); controls.size(), "expect at least",
client.sampleRate(unit.fullSampleRate()); Client::getParameterDescriptors().count()};
mInputConnections.reserve(asUnsigned(client.audioChannelsIn())); }
mOutputConnections.reserve(asUnsigned(client.audioChannelsOut()));
mAudioInputs.reserve(asUnsigned(client.audioChannelsIn()));
mOutputs.reserve(asUnsigned(
std::max(client.audioChannelsOut(), client.controlChannelsOut())));
Result countScan;
Client::getParameterDescriptors().template iterate<ExpectedCount>(
std::forward<FloatControlsIter&>(controls),
std::forward<Result&>(countScan));
return countScan;
}
Result r; void init(SCUnit& unit, Client& client, FloatControlsIter& controls)
if(!(r = expectedSize(controls)).ok()) {
{ assert(!(client.audioChannelsOut() > 0 &&
// mCalcFunc = Wrapper::getInterfaceTable()->fClearUnitOutputs; client.controlChannelsOut().count > 0) &&
std::cout "Client can't have both audio and control outputs");
<< "ERROR: " << Wrapper::getName() client.sampleRate(unit.fullSampleRate());
<< " wrong number of arguments." mInputConnections.reserve(asUnsigned(client.audioChannelsIn()));
<< r.message() mOutputConnections.reserve(asUnsigned(client.audioChannelsOut()));
<< std::endl;
return;
}
Result r;
if (!(r = expectedSize(controls)).ok())
{
std::cout << "ERROR: " << Wrapper::getName()
<< " wrong number of arguments." << r.message() << std::endl;
return;
}
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<int>(i))); mInputConnections.emplace_back(unit.isAudioRateIn(static_cast<int>(i)));
mAudioInputs.emplace_back(nullptr, 0, 0); mAudioInputs.emplace_back(nullptr, 0, 0);
} }
mInputMapper = &RealTimeBase::mapAudioInputs;
}
else if (client.controlChannelsIn())
{
mControlInputBuffer.resize(unit.mSpecialIndex + 1);
mAudioInputs.emplace_back(mControlInputBuffer);
mInputMapper = &RealTimeBase::mapControlInputs;
}
index outputSize = client.controlChannelsOut().size > 0
? std::max(client.audioChannelsOut(),
client.controlChannelsOut().size)
: unit.mSpecialIndex + 1;
mOutputs.reserve(asUnsigned(outputSize));
if (client.audioChannelsOut())
{
for (index i = 0; i < client.audioChannelsOut(); ++i) for (index i = 0; i < client.audioChannelsOut(); ++i)
{ {
mOutputConnections.emplace_back(true); mOutputConnections.emplace_back(true);
mOutputs.emplace_back(nullptr, 0, 0); mOutputs.emplace_back(nullptr, 0, 0);
} }
for (index i = 0; i < client.controlChannelsOut(); ++i) mOutMapperPre = &RealTimeBase::mapAudioOutputs;
{ mOutMapperPost = &RealTimeBase::mapNoOp;
mOutputs.emplace_back(nullptr, 0, 0); }
else
{
index totalControlOutputs =
client.controlChannelsOut().count * outputSize;
mControlOutputBuffer.resize(totalControlOutputs);
for (index i = 0; i < client.controlChannelsOut().count; ++i)
{
mOutputs.emplace_back(
mControlOutputBuffer(fluid::Slice(i * outputSize, outputSize)));
} }
}
mOutMapperPre = &RealTimeBase::mapNoOp;
void next(SCUnit& unit, Client& client,Params& params,FloatControlsIter& controls,bool updateParams = true) mOutMapperPost = &RealTimeBase::mapControlOutputs;
{ }
bool trig = IsModel_t<Client>::value ? !mPrevTrig && unit.in0(0) > 0 : false; }
mPrevTrig = trig; void mapNoOp(SCUnit&, Client&) {}
if(updateParams) void mapAudioInputs(SCUnit& unit, Client& client)
{ {
for (index i = 0; i < client.audioChannelsIn(); ++i)
{
assert(i <= std::numeric_limits<int>::max());
if (mInputConnections[asUnsigned(i)])
mAudioInputs[asUnsigned(i)].reset(
const_cast<float*>(unit.in(static_cast<int>(i))), 0,
unit.fullBufferSize());
}
}
void mapAudioOutputs(SCUnit& unit, Client& client)
{
for (index i = 0; i < client.audioChannelsOut(); ++i)
{
assert(i <= std::numeric_limits<int>::max());
if (mOutputConnections[asUnsigned(i)])
mOutputs[asUnsigned(i)].reset(unit.out(static_cast<int>(i)), 0,
unit.fullBufferSize());
}
}
void mapControlInputs(SCUnit& unit, Client& client)
{
for (index i = 0; i < unit.mSpecialIndex + 1; ++i)
{
assert(i <= std::numeric_limits<int>::max());
mControlInputBuffer[asUnsigned(i)] = unit.in0(static_cast<int>(i));
}
}
void mapControlOutputs(SCUnit& unit, Client& client)
{
for (index i = 0; i < mControlOutputBuffer.size(); ++i)
{
assert(i <= std::numeric_limits<int>::max());
unit.out0(static_cast<int>(i)) = mControlOutputBuffer(i);
}
}
void next(SCUnit& unit, Client& client, Params& params,
FloatControlsIter& controls, bool updateParams = true)
{
bool trig =
IsModel_t<Client>::value ? !mPrevTrig && unit.in0(0) > 0 : false;
mPrevTrig = trig;
if (updateParams)
{
Wrapper::setParams(&unit, params, controls); Wrapper::setParams(&unit, params, controls);
params.constrainParameterValuesRT(nullptr); params.constrainParameterValuesRT(nullptr);
} }
for (index i = 0; i < client.audioChannelsIn(); ++i) (this->*mInputMapper)(unit, client);
{ (this->*mOutMapperPre)(unit, client);
assert(i <= std::numeric_limits<int>::max()); client.process(mAudioInputs, mOutputs, mContext);
if (mInputConnections[asUnsigned(i)]) (this->*mOutMapperPost)(unit, client);
mAudioInputs[asUnsigned(i)].reset(const_cast<float*>(unit.in(static_cast<int>(i))), 0,unit.fullBufferSize()); }
}
private:
for (index i = 0; i < client.audioChannelsOut(); ++i) std::vector<bool> mInputConnections;
{ std::vector<bool> mOutputConnections;
assert(i <= std::numeric_limits<int>::max()); std::vector<HostVector> mAudioInputs;
if (mOutputConnections[asUnsigned(i)]) std::vector<HostVector> mOutputs;
mOutputs[asUnsigned(i)].reset(unit.out(static_cast<int>(i)), 0, FluidTensor<float, 1> mControlInputBuffer;
unit.fullBufferSize()); FluidTensor<float, 1> mControlOutputBuffer;
} FluidContext mContext;
bool mPrevTrig;
for (index i = 0; i < client.controlChannelsOut(); ++i) IOMapFn mInputMapper;
{ IOMapFn mOutMapperPre;
assert(i <= std::numeric_limits<int>::max()); IOMapFn mOutMapperPost;
mOutputs[asUnsigned(i)].reset(unit.out(static_cast<int>(i)), 0, 1); };
} } // namespace impl
client.process(mAudioInputs, mOutputs, mContext); } // namespace client
} } // namespace fluid
private:
std::vector<bool> mInputConnections;
std::vector<bool> mOutputConnections;
std::vector<HostVector> mAudioInputs;
std::vector<HostVector> mOutputs;
FluidContext mContext;
bool mPrevTrig;
};
}
}
}

Loading…
Cancel
Save