diff --git a/CMakeLists.txt b/CMakeLists.txt index ec910af..bbe963b 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - +set(CMAKE_POSITION_INDEPENDENT_CODE ON) ################################################################################ # Paths set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/install" CACHE PATH "") @@ -89,7 +89,7 @@ include(flucoma-buildtools) include(flucoma-buildtype) # 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") if(DOCS) diff --git a/README.md b/README.md index a1692f3..d5e0c55 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Note that on macOS you may need to [dequarantine](https://learn.flucoma.org/inst ## Pre-requisites -* C++14 compliant compiler (clang, GCC or MSVC) +* C++17 compliant compiler (clang, GCC or MSVC) * cmake * make (or Ninja or XCode or VisualStudio) * git diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index 226bddb..ac4ae03 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -76,8 +76,9 @@ public: } - static auto& setParams(Unit* x, ParamSetType& p, - FloatControlsIter& inputs, bool constrain = false, bool initialized = true) + static auto& setParams(Unit* x, ParamSetType& p, FloatControlsIter& inputs, + Allocator& alloc, bool constrain = false, + bool initialized = true) { bool verbose = x->mWorld->mVerbosity > 0; @@ -85,7 +86,7 @@ public: Reportage* reportage = initialized ? &(static_cast(x)->mReportage) : new Reportage(); - p.template setParameterValuesRT(verbose ? reportage: nullptr , x, inputs); + p.template setParameterValuesRT(verbose ? reportage: nullptr , x, inputs, alloc); if (constrain) p.constrainParameterValuesRT(verbose ? reportage : nullptr); if(verbose) { diff --git a/include/clients/rt/FluidDataSetWr.hpp b/include/clients/rt/FluidDataSetWr.hpp index f97c4c4..a5b4c46 100644 --- a/include/clients/rt/FluidDataSetWr.hpp +++ b/include/clients/rt/FluidDataSetWr.hpp @@ -46,12 +46,12 @@ public: static constexpr auto &getParameterDescriptors() { return DataSetWrParams; } - DataSetWriterClient(ParamSetViewType &p) : mParams(p) {} + DataSetWriterClient(ParamSetViewType &p, FluidContext&) : mParams(p) {} template Result process(FluidContext &) { auto dataset = get().get(); if (auto datasetPtr = dataset.lock()) { - std::string &idPrefix = get(); + std::string idPrefix = std::string(get()); auto &idNumberArr = get(); if (idNumberArr.size() != 2) return {Result::Status::kError, "ID number malformed"}; diff --git a/include/wrapper/ArgsFromClient.hpp b/include/wrapper/ArgsFromClient.hpp index 9f7b091..30a80ad 100644 --- a/include/wrapper/ArgsFromClient.hpp +++ b/include/wrapper/ArgsFromClient.hpp @@ -1,6 +1,8 @@ #pragma once #include "Meta.hpp" +#include +#include namespace fluid { namespace client { @@ -40,7 +42,11 @@ struct ParamReader 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 + static auto + fromArgs(Unit* /*x*/, Controls& args, + std::basic_string, Alloc> const&, int) { // first is string size, then chars index size = static_cast(args.next()); @@ -50,14 +56,15 @@ struct ParamReader res[asUnsigned(i)] = static_cast(args.next()); return res; } - + static auto fromArgs(Unit*, Controls& args,typename LongArrayT::type&, int) { //first is array size, then items using Container = typename LongArrayT::type; using Value = typename Container::type; index size = static_cast(args.next()); - Container res(size); + /// todo: fix allocator + Container res(size, FluidDefaultAllocator()); for (index i = 0; i < size; ++i) res[i] = static_cast(args.next()); return res; @@ -225,7 +232,8 @@ struct ParamReader return argTypeOK(T{},tag); } - static auto fromArgs(World*, sc_msg_iter& args, std::string, int) + template + static auto fromArgs(World*, sc_msg_iter& args, std::basic_string,Alloc> const&, int) { const char* recv = args.gets(""); @@ -285,7 +293,7 @@ struct ParamReader using Container = typename LongArrayT::type; using Value = typename Container::type; index size = static_cast(args.geti()); - Container res(size); + Container res(size, FluidDefaultAllocator()); for (index i = 0; i < size; ++i) res[i] = static_cast(args.geti()); return res; @@ -325,14 +333,14 @@ struct ClientParams{ template std::enable_if_t || 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 if (args.remain() == 0) { std::cout << "WARNING: " << Wrapper::getName() << " received fewer parameters than expected\n"; - return Wrapper::Client::getParameterDescriptors().template makeValue(); + return Wrapper::Client::getParameterDescriptors().template makeValue(alloc); } ParamLiteralConvertor a; @@ -348,18 +356,25 @@ struct ClientParams{ template std::enable_if_t && 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 if (args.remain() == 0) { std::cout << "WARNING: " << Wrapper::getName() << " received fewer parameters than expected\n"; - return Wrapper::Client::getParameterDescriptors().template makeValue(); + return Wrapper::Client::getParameterDescriptors().template makeValue(alloc); } index id = ParamReader::fromArgs(x,args,index{},0); - return std::to_string(id); + using StdAlloc = foonathan::memory::std_allocator; + using fmt_memory_buffer = + fmt::basic_memory_buffer; + 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); } }; diff --git a/include/wrapper/ArgsToClient.hpp b/include/wrapper/ArgsToClient.hpp index bafa412..fcb42b9 100644 --- a/include/wrapper/ArgsToClient.hpp +++ b/include/wrapper/ArgsToClient.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace fluid { namespace client { @@ -15,12 +17,12 @@ namespace client { return 1; } - static index allocSize(std::string s) + static index allocSize(std::string const& s) { return asSigned(s.size()) + 1; } // put null char at end when we send - static index allocSize(FluidTensor s) + static index allocSize(FluidTensor const& s) { index count = 0; for (auto& str : s) count += (str.size() + 1); @@ -28,7 +30,7 @@ namespace client { } template - static index allocSize(FluidTensor s) + static index allocSize(FluidTensor const& s) { return s.size(); } @@ -68,12 +70,12 @@ namespace client { f[0] = static_cast(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); f[s.size()] = 0; // terminate } - static void convert(float* f, FluidTensor s) + static void convert(float* f, FluidTensor const& s) { for (auto& str : s) { @@ -83,7 +85,7 @@ namespace client { } } template - static void convert(float* f, FluidTensor s) + static void convert(float* f, FluidTensor const& s) { static_assert(std::is_convertible::value, "Can't convert this to float output"); @@ -114,19 +116,24 @@ namespace client { return 1; } - static index numTags(std::string) + static index numTags(rt::string const&) + { + return 1;; + } + + static index numTags(std::string const&) { return 1;; } template - static index numTags(FluidTensor s) + static index numTags(FluidTensor const& s) { return s.size(); } template - static index numTags(std::tuple&& t) + static index numTags(std::tuple const& t) { index count = 0; ForEach(t,[&count](auto& x){ count += numTags(x);}); @@ -143,10 +150,11 @@ namespace client { static std::enable_if_t>::value> 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 - static void getTag(Packet& p, FluidTensor x) + static void getTag(Packet& p, FluidTensor const& x) { T dummy{}; for (int i = 0; i < x.rows(); i++) @@ -154,7 +162,7 @@ namespace client { } template - static void getTag(Packet& p, std::tuple&& t) + static void getTag(Packet& p, std::tuple const& t) { ForEach(t,[&p](auto& x){getTag(p,x);}); } @@ -179,19 +187,24 @@ namespace client { p.addf(static_cast(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()); } template - static void convert(Packet& p, FluidTensor s) + static void convert(Packet& p, FluidTensor const& s) { for(auto& x: s) convert(p,x); } template - static void convert(Packet& p, std::tuple&& t) + static void convert(Packet& p, std::tuple const& t) { ForEach(t,[&p](auto& x){ convert(p,x);}); } diff --git a/include/wrapper/Messaging.hpp b/include/wrapper/Messaging.hpp index 9237525..c4b8588 100644 --- a/include/wrapper/Messaging.hpp +++ b/include/wrapper/Messaging.hpp @@ -154,7 +154,7 @@ public: static void refreshParams(Params& p, MessageResult& r) { - p.fromTuple(ParamValues(r)); + p.fromTuple(r.value()); } template @@ -253,7 +253,7 @@ public: template // call from RT static void messageOutput(const std::string& s, index id, MessageResult& result, void* replyAddr) { - index numTags = ToOSCTypes::numTags(static_cast(result)); + index numTags = ToOSCTypes::numTags(result.value()); if(numTags > 2048) { std::cout << "ERROR: Message response too big to send (" << asUnsigned(numTags) * sizeof(float) << " bytes)." << std::endl; @@ -290,9 +290,7 @@ public: template static void messageOutput(const std::string& s, index id, MessageResult>& result, void* replyAddr) { - using T = std::tuple; - - index numTags = ToOSCTypes::numTags(static_cast(result)); + index numTags = ToOSCTypes::numTags(result.value()); if(numTags > 2048) { 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(numTags + 2)); packet.addtag(','); packet.addtag('i'); - ToOSCTypes::getTag(packet,static_cast(result)); + ToOSCTypes::getTag(packet,result.value()); packet.addi(static_cast(id)); - ToOSCTypes::convert(packet, static_cast(result)); + ToOSCTypes::convert(packet, result.value()); if(replyAddr) SendReply(replyAddr,packet.data(),static_cast(packet.size())); diff --git a/include/wrapper/NonRealtime.hpp b/include/wrapper/NonRealtime.hpp index 1782fe2..60a6b69 100644 --- a/include/wrapper/NonRealtime.hpp +++ b/include/wrapper/NonRealtime.hpp @@ -42,7 +42,8 @@ private: /// Instance cache struct CacheEntry { - CacheEntry(const Params& p) : mParams{p}, mClient{mParams} {} + CacheEntry(const Params& p, FluidContext c) + : mParams{p}, mClient{mParams, c} {} Params mParams; Client mClient; @@ -151,11 +152,11 @@ public: 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))) { - auto result = mCache.emplace(id, std::make_shared(params)); + auto result = mCache.emplace(id, std::make_shared(params, context)); addToRTCache{}(world, *(result.first)); @@ -199,8 +200,10 @@ private: struct NRTCommand { - NRTCommand(World*, sc_msg_iter* args, void* replyAddr, + NRTCommand(World* world, sc_msg_iter* args, void* replyAddr, bool consumeID = true) + : mSCAlloc{world, Wrapper::getInterfaceTable()}, + mAlloc{foonathan::memory::make_allocator_reference(mSCAlloc)} { auto count = args->count; auto pos = args->rdpos; @@ -221,9 +224,11 @@ private: 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 stage3(World*) { return true; } // rt @@ -248,7 +253,15 @@ private: static_cast(packet.size())); } } + + Allocator& allocator() + { + return mAlloc; + } + // protected: + SCRawAllocator mSCAlloc; + Allocator mAlloc; index mID; void* mReplyAddress{nullptr}; }; @@ -257,16 +270,18 @@ private: { CommandNew(World* world, sc_msg_iter* args, void* replyAddr) : NRTCommand{world, args, replyAddr, !IsNamedShared_v}, - mParams{Client::getParameterDescriptors()} + mParams{Client::getParameterDescriptors(), NRTCommand::allocator()} { mParams.template setParameterValuesRT(nullptr, world, - *args); + *args, NRTCommand::allocator()); } - CommandNew(index id, World*, FloatControlsIter& args, Unit* x) - : NRTCommand{id}, mParams{Client::getParameterDescriptors()} + CommandNew(index id, World* world, FloatControlsIter& args, Unit* x) + : NRTCommand{world, id}, mParams{Client::getParameterDescriptors(), + NRTCommand::allocator()} { - mParams.template setParameterValuesRT(nullptr, x, args); + mParams.template setParameterValuesRT( + nullptr, x, args, NRTCommand::allocator()); } static const char* name() @@ -281,7 +296,7 @@ private: 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 // params instance. @@ -343,21 +358,23 @@ private: { CommandProcess(World* world, sc_msg_iter* args, void* replyAddr) : NRTCommand{world, args, replyAddr}, - mParams{Client::getParameterDescriptors()} + mParams{Client::getParameterDescriptors(),NRTCommand::allocator()} { auto& ar = *args; if (auto ptr = get(NRTCommand::mID).lock()) { ptr->mDone.store(false, std::memory_order_release); mParams.template setParameterValuesRT(nullptr, world, - ar); + ar, NRTCommand::allocator()); mSynchronous = static_cast(ar.geti()); } // if this fails, we'll hear about it in stage2 anyway } - explicit CommandProcess(index id, bool synchronous, Params* params) - : NRTCommand{id}, - mSynchronous(synchronous), mParams{Client::getParameterDescriptors()} + explicit CommandProcess(World* world, index id, bool synchronous, + Params* params) + : NRTCommand{world, id}, + mSynchronous(synchronous), mParams{Client::getParameterDescriptors(), + NRTCommand::allocator()} { if (params) { @@ -473,7 +490,8 @@ private: /// Not registered as a PlugInCmd. Triggered by worker thread callback struct CommandAsyncComplete : public NRTCommand { - CommandAsyncComplete(World*, index id, void* replyAddress) + CommandAsyncComplete(World* world, index id, void* replyAddress) + : NRTCommand(world, id) { NRTCommand::mID = id; NRTCommand::mReplyAddress = replyAddress; @@ -612,7 +630,9 @@ private: struct CommandProcessNew : public NRTCommand { 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.mReplyAddress = mNew.mReplyAddress; @@ -695,8 +715,8 @@ private: auto& ar = *args; if (auto ptr = get(NRTCommand::mID).lock()) { - ptr->mParams.template setParameterValuesRT(nullptr, - world, ar); + ptr->mParams.template setParameterValuesRT( + nullptr, world, ar, NRTCommand::allocator()); Result result = validateParameters(ptr->mParams); ptr->mClient.setParams(ptr->mParams); } @@ -725,8 +745,9 @@ private: if(!mTryInNRT) return false; if (auto ptr = get(NRTCommand::mID).lock()) - { - ptr->mParams.template setParameterValues(true, world, mArgs); + { + ptr->mParams.template setParameterValues( + true, world, mArgs, FluidDefaultAllocator()); Result result = validateParameters(ptr->mParams); ptr->mClient.setParams(ptr->mParams); } @@ -810,7 +831,6 @@ private: template static void defineNRTCommand() { - auto ft = getInterfaceTable(); auto commandRunner = [](World* world, void*, struct sc_msg_iter* args, void* replyAddr) { auto ft = getInterfaceTable(); @@ -918,7 +938,9 @@ private: NRTTriggerUnit() : 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(mInBuf[0][0]); if (mID == -1) mID = count(); @@ -936,7 +958,7 @@ private: ~NRTTriggerUnit() { set_calc_function(); - auto cmd = NonRealTime::rtalloc(mWorld, mID); + auto cmd = NonRealTime::rtalloc(mWorld, mWorld, mID); if (runAsyncCommand(mWorld, cmd, nullptr, 0, nullptr) != 0) { std::cout << "ERROR: Async command failed in ~NRTTriggerUnit()" @@ -963,12 +985,12 @@ private: if (trigger) { 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; CommandProcess* cmd = - rtalloc(mWorld, mID, blocking, &mParams); + rtalloc(mWorld, mWorld, mID, blocking, &mParams); if (runAsyncCommand(mWorld, cmd, nullptr, 0, nullptr) != 0) { std::cout << "ERROR: Async command failed in NRTTriggerUnit::next()" @@ -1000,6 +1022,8 @@ private: index mID; index mRunCount{0}; WeakCacheEntryPointer mInst; + SCRawAllocator mSCAlloc; + Allocator mAlloc; Params mParams; bool mInit{false}; }; diff --git a/include/wrapper/RealTimeBase.hpp b/include/wrapper/RealTimeBase.hpp index feccfb8..ffeb5c7 100644 --- a/include/wrapper/RealTimeBase.hpp +++ b/include/wrapper/RealTimeBase.hpp @@ -1,6 +1,8 @@ #pragma once +#include #include +#include namespace fluid { namespace client { @@ -80,8 +82,9 @@ struct RealTimeBase std::forward(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 && client.controlChannelsOut().count > 0) && @@ -89,7 +92,7 @@ struct RealTimeBase client.sampleRate(unit.fullSampleRate()); mInputConnections.reserve(asUnsigned(client.audioChannelsIn())); mOutputConnections.reserve(asUnsigned(client.audioChannelsOut())); - + mContext = FluidContext(unit.fullBufferSize(), alloc); Result r; if (!(r = expectedSize(controls)).ok()) { @@ -195,16 +198,19 @@ struct RealTimeBase } void next(SCUnit& unit, Client& client, Params& params, - FloatControlsIter& controls, bool updateParams = true) + FloatControlsIter& controls, Allocator& alloc, + bool updateParams = true) { bool trig = IsModel_t::value ? !mPrevTrig && unit.in0(0) > 0 : false; mPrevTrig = trig; - + #ifdef EIGEN_RUNTIME_NO_MALLOC + Eigen::internal::set_is_malloc_allowed(false); + #endif if (updateParams) { - Wrapper::setParams(&unit, params, controls); + Wrapper::setParams(&unit, params, controls, alloc); params.constrainParameterValuesRT(nullptr); } @@ -212,6 +218,9 @@ struct RealTimeBase (this->*mOutMapperPre)(unit, client); client.process(mAudioInputs, mOutputs, mContext); (this->*mOutMapperPost)(unit, client); + #ifdef EIGEN_RUNTIME_NO_MALLOC + Eigen::internal::set_is_malloc_allowed(true); //not really + #endif } private: @@ -221,11 +230,11 @@ private: std::vector mOutputs; FluidTensor mControlInputBuffer; FluidTensor mControlOutputBuffer; - FluidContext mContext; bool mPrevTrig; IOMapFn mInputMapper; IOMapFn mOutMapperPre; IOMapFn mOutMapperPost; + FluidContext mContext; }; } // namespace impl } // namespace client diff --git a/include/wrapper/Realtime.hpp b/include/wrapper/Realtime.hpp index 64bff83..73aec80 100644 --- a/include/wrapper/Realtime.hpp +++ b/include/wrapper/Realtime.hpp @@ -3,6 +3,7 @@ #include "ArgsFromClient.hpp" #include "Meta.hpp" #include "RealTimeBase.hpp" +#include "SCWorldAllocator.hpp" #include #include @@ -53,73 +54,38 @@ public: } 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(); } void init() { -// auto& client = mClient; - - mDelegate.init(*this,mClient,mControls); + mDelegate.init(*this,mClient,mControls,mAlloc); mCalcFunc = make_calc_function(); 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(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(); - // Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1); + } void next(int) { mControls.reset(mInBuf + ControlOffset(this)); - mDelegate.next(*this,mClient,mParams,mControls); + mDelegate.next(*this,mClient,mParams,mControls, mAlloc); } private: + SCRawAllocator mSCAlloc; + Allocator mAlloc; + FluidContext mContext; Delegate mDelegate; FloatControlsIter mControls; - Params mParams{Client::getParameterDescriptors()}; + Params mParams; Client mClient; Wrapper* mWrapper{static_cast(this)}; }; diff --git a/include/wrapper/SCWorldAllocator.hpp b/include/wrapper/SCWorldAllocator.hpp index 51c697f..a6bae72 100644 --- a/include/wrapper/SCWorldAllocator.hpp +++ b/include/wrapper/SCWorldAllocator.hpp @@ -14,6 +14,7 @@ #include #include + namespace fluid { template @@ -57,4 +58,34 @@ public: 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