@ -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 r = ( args - > * Method ) ( 0 ) ;
T r = ( args - > * Method ) ( T { 0 } ) ;
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 >
{ } ;
{
// ArgumentGetter() { std::cout << "FloatT @ " << N << '\n'; }
} ;
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 >
{ } ;
{
// ArgumentGetter() { std::cout << "Enum @ " << N << '\n'; }
} ;
template < size_t N > struct ArgumentGetter < N , BufferT >
{
// ArgumentGetter() { std::cout << "Buffer @ " << N << '\n'; }
auto operator ( ) ( World * w , sc_msg_iter * args )
{
long bufnum = args - > geti ( - 1 ) ;
return std : : unique_ptr < BufferAdaptor > ( new SCBufferAdaptor ( bufnum , w ) ) ;
typename LongT : : type bufnum = args - > geti ( - 1 ) ;
return std : : unique_ptr < BufferAdaptor > ( bufnum > = 0 ? new SCBufferAdaptor ( bufnum , w ) : nullptr ) ;
}
} ;
@ -100,8 +107,8 @@ template <size_t N> struct ControlGetter<N, BufferT>
{
auto operator ( ) ( World * w , FloatControlsIter & iter )
{
long bufnum = iter . next ( ) ;
return std : : unique_ptr < BufferAdaptor > ( new SCBufferAdaptor ( bufnum , w ) ) ;
typename LongT : : type bufnum = iter . next ( ) ;
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 < class Wrapper > class RealTime : public SCUnit
template < typename Client , class Wrapper > class RealTime : public SCUnit
{
using HostVector = FluidTensorView < float , 1 > ;
// using Client = typename Wrapper::ClientType;
@ -124,18 +152,22 @@ template <class Wrapper> class RealTime : public SCUnit
public :
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 ( )
{
Wrapper * w = static_cast < Wrapper * > ( this ) ;
auto & mClient = w - > client ( ) ;
assert ( ! ( mClient . audioChannelsOut ( ) > 0 & & mClient . controlChannelsOut ( ) > 0 ) & & " Client can't have both audio and control outputs " ) ;
mInputConnections . reserve ( mClient . audioChannelsIn ( ) ) ;
mOutputConnections . reserve ( mClient . audioChannelsOut ( ) ) ;
mAudioInputs . reserve ( mClient . audioChannelsIn ( ) ) ;
mAudioOutputs . reserve ( mClient . audioChannelsOut ( ) ) ;
mControlOutputs . reserve ( mClient . controlChannelsOut ( ) ) ;
// mControlOutputData.resize(mClient.controlChannelsOut(),)
for ( int i = 0 ; i < mClient . audioChannelsIn ( ) ; + + i )
{
@ -149,6 +181,11 @@ public:
mAudioOutputs . emplace_back ( nullptr , 0 , 0 ) ;
}
// for (int i = 0; i < mClient.controlChannelsOut(); ++i)
// {
// mControlOutputs.emplace_back()
// }
set_calc_function < RealTime , & RealTime : : next > ( ) ;
Wrapper : : getInterfaceTable ( ) - > fClearUnitOutputs ( this , 1 ) ;
}
@ -156,43 +193,53 @@ public:
void next ( int n )
{
Wrapper * w = static_cast < Wrapper * > ( this ) ;
auto & client = w - > client ( ) ;
mControlsIterator . reset ( mInBuf + c lient. audioChannelsIn ( ) ) ;
// auto &client = w->client();
mControlsIterator . reset ( mInBuf + mC lient. audioChannelsIn ( ) ) ;
w - > setParams ( mWorld - > mVerbosity > 0 , mWorld , mControlsIterator ) ; // forward on inputs N + audio inputs as params
const Unit * unit = this ;
for ( int i = 0 ; i < c lient. audioChannelsIn ( ) ; + + i )
for ( int i = 0 ; i < mC lient. audioChannelsIn ( ) ; + + i )
{
if ( mInputConnections [ i ] ) mAudioInputs [ i ] . reset ( IN ( i ) , 0 , fullBufferSize ( ) ) ;
}
for ( int i = 0 ; i < c lient. audioChannelsOut ( ) ; + + i )
for ( int i = 0 ; i < mC lient. audioChannelsOut ( ) ; + + i )
{
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 :
std : : vector < bool > mInputConnections ;
std : : vector < bool > mOutputConnections ;
std : : vector < HostVector > mAudioInputs ;
std : : vector < HostVector > mAudioOutputs ;
std : : vector < HostVector > mControlOutputs ;
FloatControlsIter mControlsIterator ;
protected :
Client mClient ;
} ;
template < class Wrapper > class NonRealTime
template < typename Client , typename Wrapper> class NonRealTime
{
public :
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 ( ) { } ;
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 ) ;
int argsPosition = args - > count ;
auto argsRdPos = args - > rdpos ;
Result result = validateParameters ( w , world , args ) ;
if ( ! result . ok ( ) )
{
@ -200,6 +247,7 @@ public:
return ;
}
args - > count = argsPosition ;
args - > rdpos = argsRdPos ;
w - > setParams ( false , world , args ) ;
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 void destroy ( World * world , void * data ) { delete static_cast < Wrapper * > ( data ) ; }
protected :
Client mClient ;
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 ) ;
for ( auto & r : results )
{
@ -233,7 +284,7 @@ private:
void parseBuffers ( Wrapper * w , World * world , sc_msg_iter * args )
{
auto & c = w- > client ( ) ;
auto & c = mClient ;
mBuffersIn . reserve ( c . audioBuffersIn ( ) ) ;
mInputs . reserve ( c . audioBuffersIn ( ) ) ;
@ -261,8 +312,7 @@ private:
bool process ( World * world )
{
Wrapper * wrapper = static_cast < Wrapper * > ( this ) ;
Result r = wrapper - > client ( ) . process ( mInputs , mOutputs ) ;
Result r = mClient . process ( mInputs , mOutputs ) ;
if ( ! r . ok ( ) )
{
@ -275,6 +325,8 @@ private:
bool exchangeBuffers ( World * world )
{
mClient . template forEachParamType < BufferT , AssignBuffer > ( world ) ;
for ( auto & b : mBuffersOut ) b . assignToRT ( world ) ;
return true ;
}
@ -286,6 +338,16 @@ private:
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 > mBuffersOut ;
std : : vector < BufferProcessSpec > mInputs ;
@ -294,28 +356,31 @@ private:
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 )
{
RealTime < Wrapper> : : setup ( ft , name ) ;
NonRealTime < Wrapper> : : setup ( ft , name ) ;
RealTime < Client, Wrapper> : : setup ( ft , name ) ;
NonRealTime < Client, Wrapper> : : setup ( ft , name ) ;
}
} ;
// 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
template < typename Client >
using FluidSCWrapperBase = FluidSCWrapperImpl < FluidSCWrapper< Client > , isNonRealTime < Client > , isRealTime < Client > > ;
using FluidSCWrapperBase = FluidSCWrapperImpl < Client, FluidSCWrapper< Client > , isNonRealTime < Client > , isRealTime < Client > > ;
} // namespace impl
@ -327,6 +392,10 @@ public:
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 * name = nullptr ;
@ -348,18 +417,18 @@ public:
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 )
{
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 :
Client mClient ;
//private:
// Client mClient;
} ;
template < typename Client > void makeSCWrapper ( InterfaceTable * ft , const char * name )