nix
weefuzzy 3 years ago
commit 2461167499

@ -11,7 +11,7 @@ set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>") set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
################################################################################ ################################################################################
# Paths # Paths
set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/install" CACHE PATH "") set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/install" CACHE PATH "")
@ -89,7 +89,7 @@ include(flucoma-buildtools)
include(flucoma-buildtype) include(flucoma-buildtype)
# endif() # endif()
option(DOCS "Generate scdocs" OFF) option(DOCS "Generate scdocs" ON)
set(FLUID_DOCS_PATH "" CACHE PATH "Optional path to flucoma-docs (needed for docs); will download if absent") set(FLUID_DOCS_PATH "" CACHE PATH "Optional path to flucoma-docs (needed for docs); will download if absent")
if(DOCS) if(DOCS)

@ -76,8 +76,9 @@ public:
} }
static auto& setParams(Unit* x, ParamSetType& p, static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs,
FloatControlsIter& inputs, bool constrain = false, bool initialized = true) Allocator& alloc, bool constrain = false,
bool initialized = true)
{ {
bool verbose = x->mWorld->mVerbosity > 0; bool verbose = x->mWorld->mVerbosity > 0;
@ -85,7 +86,7 @@ public:
Reportage* reportage = initialized ? &(static_cast<FluidSCWrapper*>(x)->mReportage) : new Reportage(); Reportage* reportage = initialized ? &(static_cast<FluidSCWrapper*>(x)->mReportage) : new Reportage();
p.template setParameterValuesRT<ControlSetter>(verbose ? reportage: nullptr , x, inputs); p.template setParameterValuesRT<ControlSetter>(verbose ? reportage: nullptr , x, inputs, alloc);
if (constrain) p.constrainParameterValuesRT(verbose ? reportage : nullptr); if (constrain) p.constrainParameterValuesRT(verbose ? reportage : nullptr);
if(verbose) if(verbose)
{ {

@ -46,12 +46,12 @@ public:
static constexpr auto &getParameterDescriptors() { return DataSetWrParams; } static constexpr auto &getParameterDescriptors() { return DataSetWrParams; }
DataSetWriterClient(ParamSetViewType &p) : mParams(p) {} DataSetWriterClient(ParamSetViewType &p, FluidContext&) : mParams(p) {}
template <typename T> Result process(FluidContext &) { template <typename T> Result process(FluidContext &) {
auto dataset = get<kDataSet>().get(); auto dataset = get<kDataSet>().get();
if (auto datasetPtr = dataset.lock()) { if (auto datasetPtr = dataset.lock()) {
std::string &idPrefix = get<kIDPrefix>(); std::string idPrefix = std::string(get<kIDPrefix>());
auto &idNumberArr = get<kIDNumber>(); auto &idNumberArr = get<kIDNumber>();
if (idNumberArr.size() != 2) if (idNumberArr.size() != 2)
return {Result::Status::kError, "ID number malformed"}; return {Result::Status::kError, "ID number malformed"};

@ -1,6 +1,8 @@
#pragma once #pragma once
#include "Meta.hpp" #include "Meta.hpp"
#include <data/FluidMemory.hpp>
#include <fmt/format.h>
namespace fluid { namespace fluid {
namespace client { namespace client {
@ -40,7 +42,11 @@ struct ParamReader<impl::FloatControlsIter>
using Controls = impl::FloatControlsIter; using Controls = impl::FloatControlsIter;
static auto fromArgs(Unit* /*x*/, Controls& args, std::string, int) /// todo: fix std::string to use a specialisation with RT alloc
template <typename Alloc>
static auto
fromArgs(Unit* /*x*/, Controls& args,
std::basic_string<char, std::char_traits<char>, Alloc> const&, int)
{ {
// first is string size, then chars // first is string size, then chars
index size = static_cast<index>(args.next()); index size = static_cast<index>(args.next());
@ -57,7 +63,8 @@ struct ParamReader<impl::FloatControlsIter>
using Container = typename LongArrayT::type; using Container = typename LongArrayT::type;
using Value = typename Container::type; using Value = typename Container::type;
index size = static_cast<index>(args.next()); index size = static_cast<index>(args.next());
Container res(size); /// todo: fix allocator
Container res(size, FluidDefaultAllocator());
for (index i = 0; i < size; ++i) for (index i = 0; i < size; ++i)
res[i] = static_cast<Value>(args.next()); res[i] = static_cast<Value>(args.next());
return res; return res;
@ -225,7 +232,8 @@ struct ParamReader<sc_msg_iter>
return argTypeOK(T{},tag); return argTypeOK(T{},tag);
} }
static auto fromArgs(World*, sc_msg_iter& args, std::string, int) template<typename Alloc>
static auto fromArgs(World*, sc_msg_iter& args, std::basic_string<char,std::char_traits<char>,Alloc> const&, int)
{ {
const char* recv = args.gets(""); const char* recv = args.gets("");
@ -285,7 +293,7 @@ struct ParamReader<sc_msg_iter>
using Container = typename LongArrayT::type; using Container = typename LongArrayT::type;
using Value = typename Container::type; using Value = typename Container::type;
index size = static_cast<index>(args.geti()); index size = static_cast<index>(args.geti());
Container res(size); Container res(size, FluidDefaultAllocator());
for (index i = 0; i < size; ++i) for (index i = 0; i < size; ++i)
res[i] = static_cast<Value>(args.geti()); res[i] = static_cast<Value>(args.geti());
return res; return res;
@ -325,14 +333,14 @@ struct ClientParams{
template<typename Context, typename Client = typename Wrapper::Client, size_t Number = N> template<typename Context, typename Client = typename Wrapper::Client, size_t Number = N>
std::enable_if_t<!impl::IsNamedShared_v<Client> || Number!=0, typename T::type> std::enable_if_t<!impl::IsNamedShared_v<Client> || Number!=0, typename T::type>
operator()(Context* x, ArgType& args) operator()(Context* x, ArgType& args, Allocator& alloc)
{ {
// Just return default if there's nothing left to grab // Just return default if there's nothing left to grab
if (args.remain() == 0) if (args.remain() == 0)
{ {
std::cout << "WARNING: " << Wrapper::getName() std::cout << "WARNING: " << Wrapper::getName()
<< " received fewer parameters than expected\n"; << " received fewer parameters than expected\n";
return Wrapper::Client::getParameterDescriptors().template makeValue<N>(); return Wrapper::Client::getParameterDescriptors().template makeValue<N>(alloc);
} }
ParamLiteralConvertor<T, argSize> a; ParamLiteralConvertor<T, argSize> a;
@ -348,18 +356,25 @@ struct ClientParams{
template<typename Context, typename Client = typename Wrapper::Client, size_t Number = N> template<typename Context, typename Client = typename Wrapper::Client, size_t Number = N>
std::enable_if_t<impl::IsNamedShared_v<Client> && Number==0, typename T::type> std::enable_if_t<impl::IsNamedShared_v<Client> && Number==0, typename T::type>
operator()(Context* x, ArgType& args) operator()(Context* x, ArgType& args, Allocator& alloc)
{ {
// Just return default if there's nothing left to grab // Just return default if there's nothing left to grab
if (args.remain() == 0) if (args.remain() == 0)
{ {
std::cout << "WARNING: " << Wrapper::getName() std::cout << "WARNING: " << Wrapper::getName()
<< " received fewer parameters than expected\n"; << " received fewer parameters than expected\n";
return Wrapper::Client::getParameterDescriptors().template makeValue<N>(); return Wrapper::Client::getParameterDescriptors().template makeValue<N>(alloc);
} }
index id = ParamReader<ArgType>::fromArgs(x,args,index{},0); index id = ParamReader<ArgType>::fromArgs(x,args,index{},0);
return std::to_string(id); using StdAlloc = foonathan::memory::std_allocator<char, Allocator>;
using fmt_memory_buffer =
fmt::basic_memory_buffer<char, fmt::inline_buffer_size, StdAlloc>;
auto buf = fmt_memory_buffer(alloc);
std::string_view fmt_string("{}");
fmt::vformat_to(std::back_inserter(buf), fmt_string,
fmt::make_format_args(id));
return rt::string(buf.data(), buf.size(), alloc);
} }
}; };

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <data/FluidMemory.hpp>
namespace fluid { namespace fluid {
namespace client { namespace client {
@ -15,12 +17,12 @@ namespace client {
return 1; return 1;
} }
static index allocSize(std::string s) static index allocSize(std::string const& s)
{ {
return asSigned(s.size()) + 1; return asSigned(s.size()) + 1;
} // put null char at end when we send } // put null char at end when we send
static index allocSize(FluidTensor<std::string, 1> s) static index allocSize(FluidTensor<std::string, 1> const& s)
{ {
index count = 0; index count = 0;
for (auto& str : s) count += (str.size() + 1); for (auto& str : s) count += (str.size() + 1);
@ -28,7 +30,7 @@ namespace client {
} }
template <typename T> template <typename T>
static index allocSize(FluidTensor<T, 1> s) static index allocSize(FluidTensor<T, 1> const& s)
{ {
return s.size(); return s.size();
} }
@ -68,12 +70,12 @@ namespace client {
f[0] = static_cast<float>(x); f[0] = static_cast<float>(x);
} }
static void convert(float* f, std::string s) static void convert(float* f, std::string const& s)
{ {
std::copy(s.begin(), s.end(), f); std::copy(s.begin(), s.end(), f);
f[s.size()] = 0; // terminate f[s.size()] = 0; // terminate
} }
static void convert(float* f, FluidTensor<std::string, 1> s) static void convert(float* f, FluidTensor<std::string, 1> const& s)
{ {
for (auto& str : s) for (auto& str : s)
{ {
@ -83,7 +85,7 @@ namespace client {
} }
} }
template <typename T> template <typename T>
static void convert(float* f, FluidTensor<T, 1> s) static void convert(float* f, FluidTensor<T, 1> const& s)
{ {
static_assert(std::is_convertible<T, float>::value, static_assert(std::is_convertible<T, float>::value,
"Can't convert this to float output"); "Can't convert this to float output");
@ -114,19 +116,24 @@ namespace client {
return 1; return 1;
} }
static index numTags(std::string) static index numTags(rt::string const&)
{
return 1;;
}
static index numTags(std::string const&)
{ {
return 1;; return 1;;
} }
template <typename T> template <typename T>
static index numTags(FluidTensor<T, 1> s) static index numTags(FluidTensor<T, 1> const& s)
{ {
return s.size(); return s.size();
} }
template <typename... Ts> template <typename... Ts>
static index numTags(std::tuple<Ts...>&& t) static index numTags(std::tuple<Ts...> const& t)
{ {
index count = 0; index count = 0;
ForEach(t,[&count](auto& x){ count += numTags(x);}); ForEach(t,[&count](auto& x){ count += numTags(x);});
@ -143,10 +150,11 @@ namespace client {
static std::enable_if_t<std::is_floating_point<std::decay_t<T>>::value> static std::enable_if_t<std::is_floating_point<std::decay_t<T>>::value>
getTag(Packet& p, T&&) { p.addtag('f'); } getTag(Packet& p, T&&) { p.addtag('f'); }
static void getTag (Packet& p, std::string) { p.addtag('s'); } static void getTag (Packet& p, std::string const&) { p.addtag('s'); }
static void getTag (Packet& p, rt::string const&) { p.addtag('s'); }
template <typename T> template <typename T>
static void getTag(Packet& p, FluidTensor<T, 1> x) static void getTag(Packet& p, FluidTensor<T, 1> const& x)
{ {
T dummy{}; T dummy{};
for (int i = 0; i < x.rows(); i++) for (int i = 0; i < x.rows(); i++)
@ -154,7 +162,7 @@ namespace client {
} }
template <typename... Ts> template <typename... Ts>
static void getTag(Packet& p, std::tuple<Ts...>&& t) static void getTag(Packet& p, std::tuple<Ts...> const& t)
{ {
ForEach(t,[&p](auto& x){getTag(p,x);}); ForEach(t,[&p](auto& x){getTag(p,x);});
} }
@ -179,19 +187,24 @@ namespace client {
p.addf(static_cast<float>(x)); p.addf(static_cast<float>(x));
} }
static void convert(Packet& p, std::string s) static void convert(Packet& p, std::string const& s)
{
p.adds(s.c_str());
}
static void convert(Packet& p, rt::string const& s)
{ {
p.adds(s.c_str()); p.adds(s.c_str());
} }
template <typename T> template <typename T>
static void convert(Packet& p, FluidTensor<T, 1> s) static void convert(Packet& p, FluidTensor<T, 1> const& s)
{ {
for(auto& x: s) convert(p,x); for(auto& x: s) convert(p,x);
} }
template <typename... Ts> template <typename... Ts>
static void convert(Packet& p, std::tuple<Ts...>&& t) static void convert(Packet& p, std::tuple<Ts...> const& t)
{ {
ForEach(t,[&p](auto& x){ convert(p,x);}); ForEach(t,[&p](auto& x){ convert(p,x);});
} }

@ -154,7 +154,7 @@ public:
static void refreshParams(Params& p, MessageResult<ParamValues>& r) static void refreshParams(Params& p, MessageResult<ParamValues>& r)
{ {
p.fromTuple(ParamValues(r)); p.fromTuple(r.value());
} }
template<typename T> template<typename T>
@ -253,7 +253,7 @@ public:
template <typename T> // call from RT template <typename T> // call from RT
static void messageOutput(const std::string& s, index id, MessageResult<T>& result, void* replyAddr) static void messageOutput(const std::string& s, index id, MessageResult<T>& result, void* replyAddr)
{ {
index numTags = ToOSCTypes<small_scpacket>::numTags(static_cast<T>(result)); index numTags = ToOSCTypes<small_scpacket>::numTags(result.value());
if(numTags > 2048) if(numTags > 2048)
{ {
std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl; std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl;
@ -290,9 +290,7 @@ public:
template <typename... Ts> template <typename... Ts>
static void messageOutput(const std::string& s, index id, MessageResult<std::tuple<Ts...>>& result, void* replyAddr) static void messageOutput(const std::string& s, index id, MessageResult<std::tuple<Ts...>>& result, void* replyAddr)
{ {
using T = std::tuple<Ts...>; index numTags = ToOSCTypes<small_scpacket>::numTags(result.value());
index numTags = ToOSCTypes<small_scpacket>::numTags(static_cast<T>(result));
if(numTags > 2048) if(numTags > 2048)
{ {
std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl; std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl;
@ -304,10 +302,10 @@ public:
packet.maketags(static_cast<int>(numTags + 2)); packet.maketags(static_cast<int>(numTags + 2));
packet.addtag(','); packet.addtag(',');
packet.addtag('i'); packet.addtag('i');
ToOSCTypes<small_scpacket>::getTag(packet,static_cast<T>(result)); ToOSCTypes<small_scpacket>::getTag(packet,result.value());
packet.addi(static_cast<int>(id)); packet.addi(static_cast<int>(id));
ToOSCTypes<small_scpacket>::convert(packet, static_cast<T>(result)); ToOSCTypes<small_scpacket>::convert(packet, result.value());
if(replyAddr) if(replyAddr)
SendReply(replyAddr,packet.data(),static_cast<int>(packet.size())); SendReply(replyAddr,packet.data(),static_cast<int>(packet.size()));

@ -42,7 +42,8 @@ private:
/// Instance cache /// Instance cache
struct CacheEntry struct CacheEntry
{ {
CacheEntry(const Params& p) : mParams{p}, mClient{mParams} {} CacheEntry(const Params& p, FluidContext c)
: mParams{p}, mClient{mParams, c} {}
Params mParams; Params mParams;
Client mClient; Client mClient;
@ -151,11 +152,11 @@ public:
return lookup == mCache.end() ? WeakCacheEntryPointer() : lookup->second; return lookup == mCache.end() ? WeakCacheEntryPointer() : lookup->second;
} }
static WeakCacheEntryPointer add(World* world, index id, const Params& params) static WeakCacheEntryPointer add(World* world, index id, const Params& params, FluidContext context)
{ {
if (isNull(get(id))) if (isNull(get(id)))
{ {
auto result = mCache.emplace(id, std::make_shared<CacheEntry>(params)); auto result = mCache.emplace(id, std::make_shared<CacheEntry>(params, context));
addToRTCache{}(world, *(result.first)); addToRTCache{}(world, *(result.first));
@ -199,8 +200,10 @@ private:
struct NRTCommand struct NRTCommand
{ {
NRTCommand(World*, sc_msg_iter* args, void* replyAddr, NRTCommand(World* world, sc_msg_iter* args, void* replyAddr,
bool consumeID = true) bool consumeID = true)
: mSCAlloc{world, Wrapper::getInterfaceTable()},
mAlloc{foonathan::memory::make_allocator_reference(mSCAlloc)}
{ {
auto count = args->count; auto count = args->count;
auto pos = args->rdpos; auto pos = args->rdpos;
@ -221,9 +224,11 @@ private:
if (mReplyAddress) deleteReplyAddress(mReplyAddress); if (mReplyAddress) deleteReplyAddress(mReplyAddress);
} }
NRTCommand() {} // NRTCommand() {}
explicit NRTCommand(index id) : mID{id} {} explicit NRTCommand(World* world, index id)
: mSCAlloc{world, Wrapper::getInterfaceTable()},
mAlloc{foonathan::memory::make_allocator_reference(mSCAlloc)}, mID{id} {}
bool stage2(World*) { return true; } // nrt bool stage2(World*) { return true; } // nrt
bool stage3(World*) { return true; } // rt bool stage3(World*) { return true; } // rt
@ -248,7 +253,15 @@ private:
static_cast<int>(packet.size())); static_cast<int>(packet.size()));
} }
} }
Allocator& allocator()
{
return mAlloc;
}
// protected: // protected:
SCRawAllocator mSCAlloc;
Allocator mAlloc;
index mID; index mID;
void* mReplyAddress{nullptr}; void* mReplyAddress{nullptr};
}; };
@ -257,16 +270,18 @@ private:
{ {
CommandNew(World* world, sc_msg_iter* args, void* replyAddr) CommandNew(World* world, sc_msg_iter* args, void* replyAddr)
: NRTCommand{world, args, replyAddr, !IsNamedShared_v<Client>}, : NRTCommand{world, args, replyAddr, !IsNamedShared_v<Client>},
mParams{Client::getParameterDescriptors()} mParams{Client::getParameterDescriptors(), NRTCommand::allocator()}
{ {
mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world, mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world,
*args); *args, NRTCommand::allocator());
} }
CommandNew(index id, World*, FloatControlsIter& args, Unit* x) CommandNew(index id, World* world, FloatControlsIter& args, Unit* x)
: NRTCommand{id}, mParams{Client::getParameterDescriptors()} : NRTCommand{world, id}, mParams{Client::getParameterDescriptors(),
NRTCommand::allocator()}
{ {
mParams.template setParameterValuesRT<ParamsFromSynth>(nullptr, x, args); mParams.template setParameterValuesRT<ParamsFromSynth>(
nullptr, x, args, NRTCommand::allocator());
} }
static const char* name() static const char* name()
@ -281,7 +296,7 @@ private:
if (!constraintsRes.ok()) Wrapper::printResult(w, constraintsRes); if (!constraintsRes.ok()) Wrapper::printResult(w, constraintsRes);
mResult = (!isNull(add(w, NRTCommand::mID, mParams))); mResult = (!isNull(add(w, NRTCommand::mID, mParams, FluidContext())));
// Sigh. The cache entry above has both the client instance and main // Sigh. The cache entry above has both the client instance and main
// params instance. // params instance.
@ -343,21 +358,23 @@ private:
{ {
CommandProcess(World* world, sc_msg_iter* args, void* replyAddr) CommandProcess(World* world, sc_msg_iter* args, void* replyAddr)
: NRTCommand{world, args, replyAddr}, : NRTCommand{world, args, replyAddr},
mParams{Client::getParameterDescriptors()} mParams{Client::getParameterDescriptors(),NRTCommand::allocator()}
{ {
auto& ar = *args; auto& ar = *args;
if (auto ptr = get(NRTCommand::mID).lock()) if (auto ptr = get(NRTCommand::mID).lock())
{ {
ptr->mDone.store(false, std::memory_order_release); ptr->mDone.store(false, std::memory_order_release);
mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world, mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, world,
ar); ar, NRTCommand::allocator());
mSynchronous = static_cast<bool>(ar.geti()); mSynchronous = static_cast<bool>(ar.geti());
} // if this fails, we'll hear about it in stage2 anyway } // if this fails, we'll hear about it in stage2 anyway
} }
explicit CommandProcess(index id, bool synchronous, Params* params) explicit CommandProcess(World* world, index id, bool synchronous,
: NRTCommand{id}, Params* params)
mSynchronous(synchronous), mParams{Client::getParameterDescriptors()} : NRTCommand{world, id},
mSynchronous(synchronous), mParams{Client::getParameterDescriptors(),
NRTCommand::allocator()}
{ {
if (params) if (params)
{ {
@ -473,7 +490,8 @@ private:
/// Not registered as a PlugInCmd. Triggered by worker thread callback /// Not registered as a PlugInCmd. Triggered by worker thread callback
struct CommandAsyncComplete : public NRTCommand struct CommandAsyncComplete : public NRTCommand
{ {
CommandAsyncComplete(World*, index id, void* replyAddress) CommandAsyncComplete(World* world, index id, void* replyAddress)
: NRTCommand(world, id)
{ {
NRTCommand::mID = id; NRTCommand::mID = id;
NRTCommand::mReplyAddress = replyAddress; NRTCommand::mReplyAddress = replyAddress;
@ -612,7 +630,9 @@ private:
struct CommandProcessNew : public NRTCommand struct CommandProcessNew : public NRTCommand
{ {
CommandProcessNew(World* world, sc_msg_iter* args, void* replyAddr) CommandProcessNew(World* world, sc_msg_iter* args, void* replyAddr)
: mNew{world, args, replyAddr}, mProcess{mNew.mID, false, nullptr} : NRTCommand{world, args, replyAddr, false},
mNew{world, args, replyAddr},
mProcess{world, mNew.mID, false, nullptr}
{ {
mProcess.mSynchronous = args->geti(); mProcess.mSynchronous = args->geti();
mProcess.mReplyAddress = mNew.mReplyAddress; mProcess.mReplyAddress = mNew.mReplyAddress;
@ -695,8 +715,8 @@ private:
auto& ar = *args; auto& ar = *args;
if (auto ptr = get(NRTCommand::mID).lock()) if (auto ptr = get(NRTCommand::mID).lock())
{ {
ptr->mParams.template setParameterValuesRT<ParamsFromOSC>(nullptr, ptr->mParams.template setParameterValuesRT<ParamsFromOSC>(
world, ar); nullptr, world, ar, NRTCommand::allocator());
Result result = validateParameters(ptr->mParams); Result result = validateParameters(ptr->mParams);
ptr->mClient.setParams(ptr->mParams); ptr->mClient.setParams(ptr->mParams);
} }
@ -726,7 +746,8 @@ private:
if (auto ptr = get(NRTCommand::mID).lock()) if (auto ptr = get(NRTCommand::mID).lock())
{ {
ptr->mParams.template setParameterValues<ParamsFromOSC>(true, world, mArgs); ptr->mParams.template setParameterValues<ParamsFromOSC>(
true, world, mArgs, FluidDefaultAllocator());
Result result = validateParameters(ptr->mParams); Result result = validateParameters(ptr->mParams);
ptr->mClient.setParams(ptr->mParams); ptr->mClient.setParams(ptr->mParams);
} }
@ -810,7 +831,6 @@ private:
template <typename Command> template <typename Command>
static void defineNRTCommand() static void defineNRTCommand()
{ {
auto ft = getInterfaceTable();
auto commandRunner = [](World* world, void*, struct sc_msg_iter* args, auto commandRunner = [](World* world, void*, struct sc_msg_iter* args,
void* replyAddr) { void* replyAddr) {
auto ft = getInterfaceTable(); auto ft = getInterfaceTable();
@ -918,7 +938,9 @@ private:
NRTTriggerUnit() NRTTriggerUnit()
: mControlsIterator{mInBuf + ControlOffset(), ControlSize()}, : mControlsIterator{mInBuf + ControlOffset(), ControlSize()},
mParams{Client::getParameterDescriptors()} mSCAlloc(mWorld, Wrapper::getInterfaceTable()),
mAlloc{foonathan::memory::make_allocator_reference(mSCAlloc)},
mParams{Client::getParameterDescriptors(), mAlloc}
{ {
mID = static_cast<index>(mInBuf[0][0]); mID = static_cast<index>(mInBuf[0][0]);
if (mID == -1) mID = count(); if (mID == -1) mID = count();
@ -936,7 +958,7 @@ private:
~NRTTriggerUnit() ~NRTTriggerUnit()
{ {
set_calc_function<NRTTriggerUnit, &NRTTriggerUnit::clear>(); set_calc_function<NRTTriggerUnit, &NRTTriggerUnit::clear>();
auto cmd = NonRealTime::rtalloc<CommandFree>(mWorld, mID); auto cmd = NonRealTime::rtalloc<CommandFree>(mWorld, mWorld, mID);
if (runAsyncCommand(mWorld, cmd, nullptr, 0, nullptr) != 0) if (runAsyncCommand(mWorld, cmd, nullptr, 0, nullptr) != 0)
{ {
std::cout << "ERROR: Async command failed in ~NRTTriggerUnit()" std::cout << "ERROR: Async command failed in ~NRTTriggerUnit()"
@ -963,12 +985,12 @@ private:
if (trigger) if (trigger)
{ {
mControlsIterator.reset(1 + mInBuf); // add one for ID mControlsIterator.reset(1 + mInBuf); // add one for ID
Wrapper::setParams(this, mParams, mControlsIterator, true, false); Wrapper::setParams(this, mParams, mControlsIterator, mAlloc, true, false);
bool blocking = mInBuf[mNumInputs - 1][0] > 0; bool blocking = mInBuf[mNumInputs - 1][0] > 0;
CommandProcess* cmd = CommandProcess* cmd =
rtalloc<CommandProcess>(mWorld, mID, blocking, &mParams); rtalloc<CommandProcess>(mWorld, mWorld, mID, blocking, &mParams);
if (runAsyncCommand(mWorld, cmd, nullptr, 0, nullptr) != 0) if (runAsyncCommand(mWorld, cmd, nullptr, 0, nullptr) != 0)
{ {
std::cout << "ERROR: Async command failed in NRTTriggerUnit::next()" std::cout << "ERROR: Async command failed in NRTTriggerUnit::next()"
@ -1000,6 +1022,8 @@ private:
index mID; index mID;
index mRunCount{0}; index mRunCount{0};
WeakCacheEntryPointer mInst; WeakCacheEntryPointer mInst;
SCRawAllocator mSCAlloc;
Allocator mAlloc;
Params mParams; Params mParams;
bool mInit{false}; bool mInit{false};
}; };

@ -1,6 +1,8 @@
#pragma once #pragma once
#include <data/FluidMemory.hpp>
#include <SC_PlugIn.hpp> #include <SC_PlugIn.hpp>
#include <Eigen/Core>
namespace fluid { namespace fluid {
namespace client { namespace client {
@ -81,7 +83,8 @@ struct RealTimeBase
return countScan; return countScan;
} }
void init(SCUnit& unit, Client& client, FloatControlsIter& controls)
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) &&
@ -89,7 +92,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);
Result r; Result r;
if (!(r = expectedSize(controls)).ok()) if (!(r = expectedSize(controls)).ok())
{ {
@ -195,16 +198,19 @@ struct RealTimeBase
} }
void next(SCUnit& unit, Client& client, Params& params, void next(SCUnit& unit, Client& client, Params& params,
FloatControlsIter& controls, bool updateParams = true) FloatControlsIter& controls, Allocator& alloc,
bool updateParams = true)
{ {
bool trig = bool trig =
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
Eigen::internal::set_is_malloc_allowed(false);
#endif
if (updateParams) if (updateParams)
{ {
Wrapper::setParams(&unit, params, controls); Wrapper::setParams(&unit, params, controls, alloc);
params.constrainParameterValuesRT(nullptr); params.constrainParameterValuesRT(nullptr);
} }
@ -212,6 +218,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
Eigen::internal::set_is_malloc_allowed(true); //not really
#endif
} }
private: private:
@ -221,11 +230,11 @@ private:
std::vector<HostVector> mOutputs; std::vector<HostVector> mOutputs;
FluidTensor<float, 1> mControlInputBuffer; FluidTensor<float, 1> mControlInputBuffer;
FluidTensor<float, 1> mControlOutputBuffer; FluidTensor<float, 1> mControlOutputBuffer;
FluidContext mContext;
bool mPrevTrig; bool mPrevTrig;
IOMapFn mInputMapper; IOMapFn mInputMapper;
IOMapFn mOutMapperPre; IOMapFn mOutMapperPre;
IOMapFn mOutMapperPost; IOMapFn mOutMapperPost;
FluidContext mContext;
}; };
} // namespace impl } // namespace impl
} // namespace client } // namespace client

@ -3,6 +3,7 @@
#include "ArgsFromClient.hpp" #include "ArgsFromClient.hpp"
#include "Meta.hpp" #include "Meta.hpp"
#include "RealTimeBase.hpp" #include "RealTimeBase.hpp"
#include "SCWorldAllocator.hpp"
#include <clients/common/FluidBaseClient.hpp> #include <clients/common/FluidBaseClient.hpp>
#include <SC_PlugIn.hpp> #include <SC_PlugIn.hpp>
@ -53,73 +54,38 @@ public:
} }
RealTime() RealTime()
: mControls{mInBuf + ControlOffset(this),ControlSize(this)}, :
mClient{Wrapper::setParams(this, mParams, mControls,true)} mSCAlloc{mWorld, Wrapper::getInterfaceTable()},
mAlloc{foonathan::memory::make_allocator_reference(mSCAlloc)},
mContext{fullBufferSize(), mAlloc},
mControls{mInBuf + ControlOffset(this),ControlSize(this)},
mParams{Client::getParameterDescriptors(), mAlloc},
mClient{Wrapper::setParams(this, mParams, mControls, mAlloc,true), mContext}
{ {
init(); init();
} }
void init() void init()
{ {
// auto& client = mClient; mDelegate.init(*this,mClient,mControls,mAlloc);
mDelegate.init(*this,mClient,mControls);
mCalcFunc = make_calc_function<RealTime, &RealTime::next>(); mCalcFunc = make_calc_function<RealTime, &RealTime::next>();
Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1); Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1);
// assert(
// !(client.audioChannelsOut() > 0 && client.controlChannelsOut() > 0) &&
// "Client can't have both audio and control outputs");
//
// Result r;
// if(!(r = expectedSize(mWrapper->mControlsIterator)).ok())
// {
// mCalcFunc = Wrapper::getInterfaceTable()->fClearUnitOutputs;
// std::cout
// << "ERROR: " << Wrapper::getName()
// << " wrong number of arguments."
// << r.message()
// << std::endl;
// return;
// }
//
// mWrapper->mControlsIterator.reset(mInBuf + mSpecialIndex + 1);
//
// client.sampleRate(fullSampleRate());
// mInputConnections.reserve(asUnsigned(client.audioChannelsIn()));
// mOutputConnections.reserve(asUnsigned(client.audioChannelsOut()));
// mAudioInputs.reserve(asUnsigned(client.audioChannelsIn()));
// mOutputs.reserve(asUnsigned(
// std::max(client.audioChannelsOut(), client.controlChannelsOut())));
//
// for (index i = 0; i < client.audioChannelsIn(); ++i)
// {
// mInputConnections.emplace_back(isAudioRateIn(static_cast<int>(i)));
// mAudioInputs.emplace_back(nullptr, 0, 0);
// }
//
// for (index i = 0; i < client.audioChannelsOut(); ++i)
// {
// mOutputConnections.emplace_back(true);
// mOutputs.emplace_back(nullptr, 0, 0);
// }
//
// for (index i = 0; i < client.controlChannelsOut(); ++i)
// { mOutputs.emplace_back(nullptr, 0, 0); }
//
// mCalcFunc = make_calc_function<RealTime, &RealTime::next>();
// Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1);
} }
void next(int) void next(int)
{ {
mControls.reset(mInBuf + ControlOffset(this)); mControls.reset(mInBuf + ControlOffset(this));
mDelegate.next(*this,mClient,mParams,mControls); mDelegate.next(*this,mClient,mParams,mControls, mAlloc);
} }
private: private:
SCRawAllocator mSCAlloc;
Allocator mAlloc;
FluidContext mContext;
Delegate mDelegate; Delegate mDelegate;
FloatControlsIter mControls; FloatControlsIter mControls;
Params mParams{Client::getParameterDescriptors()}; Params mParams;
Client mClient; Client mClient;
Wrapper* mWrapper{static_cast<Wrapper*>(this)}; Wrapper* mWrapper{static_cast<Wrapper*>(this)};
}; };

@ -14,6 +14,7 @@
#include <limits> #include <limits>
#include <new> #include <new>
namespace fluid { namespace fluid {
template <typename T, typename Wrapper> template <typename T, typename Wrapper>
@ -57,4 +58,34 @@ public:
if (mWorld && mInterface) mInterface->fRTFree(mWorld, p); if (mWorld && mInterface) mInterface->fRTFree(mWorld, p);
} }
}; };
//foonathan::memory RawAllocator with SC rtalloc
struct SCRawAllocator
{
using is_stateful = std::true_type;
SCRawAllocator(World* w, InterfaceTable* interface)
: mWorld{w}, mInterface{interface}
{}
void* allocate_node(std::size_t size, std::size_t)
{
if(auto res = mInterface->fRTAlloc(mWorld,size))
{
// std::cout << "Allocated " << res << " with " << size << '\n';
return res;
}
throw std::bad_alloc();
}
void deallocate_node(void* node, std::size_t /*size*/, std::size_t) noexcept
{
mInterface->fRTFree(mWorld, node);
// std::cout << "Freed " << node << " with " << size << '\n';
}
private:
World* mWorld;
InterfaceTable* mInterface;
};
} // namespace fluid } // namespace fluid

@ -29,8 +29,8 @@ FluidBufLoudness : FluidBufProcessor{
source = source.asUGenInput; source = source.asUGenInput;
features = features.asUGenInput; features = features.asUGenInput;
source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw};
features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; features.isNil.if {"%: Invalid features buffer".format(this.class.name).throw};
^FluidProxyUgen.kr(\FluidBufLoudnessTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, trig, blocking); ^FluidProxyUgen.kr(\FluidBufLoudnessTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, trig, blocking);
} }
@ -44,8 +44,8 @@ FluidBufLoudness : FluidBufProcessor{
source = source.asUGenInput; source = source.asUGenInput;
features = features.asUGenInput; features = features.asUGenInput;
source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw};
features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; features.isNil.if {"%: Invalid features buffer".format(this.class.name).throw};
^this.new( ^this.new(
server, nil, [features] server, nil, [features]
@ -63,8 +63,8 @@ FluidBufLoudness : FluidBufProcessor{
source = source.asUGenInput; source = source.asUGenInput;
features = features.asUGenInput; features = features.asUGenInput;
source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw};
features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; features.isNil.if {"%: Invalid features buffer".format(this.class.name).throw};
^this.new( ^this.new(
server, nil, [features] server, nil, [features]

@ -2,9 +2,6 @@ FluidBufSTFT : FluidBufProcessor {
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0,windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 1| *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0,windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 1|
// source = source.asUGenInput;
// source.isNil.if {"FluidBufScale: Invalid source buffer".throw};
source = source ? -1; source = source ? -1;
magnitude = magnitude ? -1; magnitude = magnitude ? -1;
phase = phase ? -1; phase = phase ? -1;
@ -15,9 +12,6 @@ FluidBufSTFT : FluidBufProcessor {
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action|
// source = source.asUGenInput;
// source.isNil.if {"FluidBufSTFT: Invalid source buffer".throw};
source = source ? -1; source = source ? -1;
magnitude = magnitude ? -1; magnitude = magnitude ? -1;
phase = phase ? -1; phase = phase ? -1;
@ -32,7 +26,6 @@ FluidBufSTFT : FluidBufProcessor {
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1,freeWhenDone = true, action| *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1,freeWhenDone = true, action|
// source = source.asUGenInput;
source = source ? -1; source = source ? -1;
magnitude = magnitude ? -1; magnitude = magnitude ? -1;
phase = phase ? -1; phase = phase ? -1;

@ -5,8 +5,8 @@ FluidBufTransientSlice : FluidBufProcessor {
source = source.asUGenInput; source = source.asUGenInput;
indices = indices.asUGenInput; indices = indices.asUGenInput;
source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw};
indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; indices.isNil.if {"%: Invalid features buffer".format(this.class.name).throw};
^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, trig, blocking); ^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, trig, blocking);
} }
@ -16,8 +16,8 @@ FluidBufTransientSlice : FluidBufProcessor {
source = source.asUGenInput; source = source.asUGenInput;
indices = indices.asUGenInput; indices = indices.asUGenInput;
source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw};
indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; indices.isNil.if {"%: Invalid features buffer".format(this.class.name).throw};
^this.new( ^this.new(
server, nil,[indices] server, nil,[indices]
@ -30,8 +30,8 @@ FluidBufTransientSlice : FluidBufProcessor {
source = source.asUGenInput; source = source.asUGenInput;
indices = indices.asUGenInput; indices = indices.asUGenInput;
source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw};
indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; indices.isNil.if {"%: Invalid features buffer".format(this.class.name).throw};
^this.new( ^this.new(
server, nil,[indices] server, nil,[indices]

@ -1,4 +1,3 @@
FluidDataSetQuery : FluidDataObject { FluidDataSetQuery : FluidDataObject {
*new{|server| ^super.new(server) } *new{|server| ^super.new(server) }

@ -1,5 +1,5 @@
FluidKDTree : FluidModelObject FluidKDTree : FluidModelObject
{ {
var neighbours,radius; var neighbours,radius;
@ -46,7 +46,7 @@ FluidKDTree : FluidModelObject
} }
kr{|trig, inputBuffer,outputBuffer, numNeighbours = 1, lookupDataSet| kr{|trig, inputBuffer,outputBuffer, numNeighbours = 1, lookupDataSet|
/* this.numNeighbours_(numNeighbours); /* this.numNeighbours_(numNeighbours);
lookupDataSet = lookupDataSet ? -1; lookupDataSet = lookupDataSet ? -1;
this.lookupDataSet_(lookupDataSet);*/ this.lookupDataSet_(lookupDataSet);*/

@ -61,10 +61,9 @@ StaticText(w,Rect(732,150,50,20)).string_("maxIter:");
TextField(w,Rect(730,170,50,20)).string_(1000.asString).action_{|in| mlp.maxIter = in.value.asInteger.postln;}; TextField(w,Rect(730,170,50,20)).string_(1000.asString).action_{|in| mlp.maxIter = in.value.asInteger.postln;};
StaticText(w,Rect(732,190,50,20)).string_("validation:"); StaticText(w,Rect(732,190,50,20)).string_("validation:");
TextField(w,Rect(730,210,50,20)).string_(0.0.asString).action_{|in|mlp.validation = in.value.asFloat.postln;}; TextField(w,Rect(730,210,50,20)).string_(0.0.asString).action_{|in|mlp.validation = in.value.asFloat.postln;};
)
//2- the synth //2- the synth
(
b = { b = {
arg val = #[0,0,0,0,0,0,0,0,0,0]; arg val = #[0,0,0,0,0,0,0,0,0,0];
var osc1, osc2, feed1, feed2, base1=69, base2=69, base3 = 130; var osc1, osc2, feed1, feed2, base1=69, base2=69, base3 = 130;

Loading…
Cancel
Save