fdNRTBase: Base wrapper class for Async commands
parent
535b36b8a7
commit
a39f75e241
@ -0,0 +1,114 @@
|
||||
####### added the eingenmf
|
||||
set(FLUID_DECOMP_DIR ../../fluid_decomposition)
|
||||
|
||||
include_directories(
|
||||
"${FLUID_DECOMP_DIR}"
|
||||
"${FLUID_DECOMP_DIR}/include"
|
||||
"${FLUID_DECOMP_DIR}/3rdparty"
|
||||
)
|
||||
|
||||
####### original SC Cmake file starts here
|
||||
set(FILENAME "fdNRTBase.cpp") #specify the .cpp file here
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
get_filename_component(PROJECT ${FILENAME} NAME_WE) #automatically sets project name from the filename
|
||||
message(STATUS "Project name is ${PROJECT}")
|
||||
project (${PROJECT})
|
||||
|
||||
include_directories(${SC_PATH}/include/plugin_interface)
|
||||
include_directories(${SC_PATH}/include/common)
|
||||
include_directories(${SC_PATH}/common)
|
||||
|
||||
set(CMAKE_SHARED_MODULE_PREFIX "")
|
||||
if(APPLE OR WIN32)
|
||||
set(CMAKE_SHARED_MODULE_SUFFIX ".scx")
|
||||
endif()
|
||||
|
||||
option(SUPERNOVA "Build plugins for supernova" OFF)
|
||||
if (SUPERNOVA)
|
||||
include_directories(${SC_PATH}/external_libraries/nova-tt)
|
||||
# actually just boost.atomic
|
||||
include_directories(${SC_PATH}/external_libraries/boost)
|
||||
include_directories(${SC_PATH}/external_libraries/boost_lockfree)
|
||||
include_directories(${SC_PATH}/external_libraries/boost-lockfree)
|
||||
endif()
|
||||
|
||||
option(CPP11 "Build with c++11." ON)
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
set(CMAKE_COMPILER_IS_CLANG 1)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG)
|
||||
add_definitions(-fvisibility=hidden)
|
||||
|
||||
include (CheckCCompilerFlag)
|
||||
include (CheckCXXCompilerFlag)
|
||||
|
||||
CHECK_C_COMPILER_FLAG(-msse HAS_SSE)
|
||||
CHECK_CXX_COMPILER_FLAG(-msse HAS_CXX_SSE)
|
||||
|
||||
if (HAS_SSE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse")
|
||||
endif()
|
||||
if (HAS_CXX_SSE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse")
|
||||
endif()
|
||||
|
||||
CHECK_C_COMPILER_FLAG(-msse2 HAS_SSE2)
|
||||
CHECK_CXX_COMPILER_FLAG(-msse2 HAS_CXX_SSE2)
|
||||
|
||||
if (HAS_SSE2)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2")
|
||||
endif()
|
||||
if (HAS_CXX_SSE2)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2")
|
||||
endif()
|
||||
|
||||
CHECK_C_COMPILER_FLAG(-mfpmath=sse HAS_FPMATH_SSE)
|
||||
CHECK_CXX_COMPILER_FLAG(-mfpmath=sse HAS_CXX_FPMATH_SSE)
|
||||
|
||||
if (HAS_FPMATH_SSE)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse")
|
||||
endif()
|
||||
if (HAS_CXX_FPMATH_SSE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse")
|
||||
endif()
|
||||
|
||||
if(NATIVE)
|
||||
add_definitions(-march=native)
|
||||
endif()
|
||||
|
||||
if(CPP11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
if(CMAKE_COMPILER_IS_CLANG)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
if(MINGW)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstackrealign")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mstackrealign")
|
||||
endif()
|
||||
|
||||
####### added the fluid_decomposition
|
||||
add_library(
|
||||
${PROJECT}
|
||||
MODULE
|
||||
${FILENAME}
|
||||
"${FLUID_DECOMP_DIR}/3rdparty/HISSTools_FFT/HISSTools_FFT.cpp"
|
||||
)
|
||||
if(SUPERNOVA)
|
||||
add_library(${PROJECT}_supernova MODULE ${FILENAME})
|
||||
set_property(TARGET ${PROJECT}_supernova
|
||||
PROPERTY COMPILE_DEFINITIONS SUPERNOVA)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET
|
||||
${PROJECT}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "../../release-packaging/${PROJECT}/plugins"
|
||||
COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${PROJECT}> "../../release-packaging/${PROJECT}/plugins"
|
||||
)
|
||||
|
||||
target_link_libraries (${PROJECT} "-framework Accelerate")
|
||||
@ -0,0 +1,198 @@
|
||||
//Can I reallocate buffers on the server? Yes I can.
|
||||
#include "SC_PlugIn.h"
|
||||
#include <vector>
|
||||
#include "data/FluidTensor.hpp"
|
||||
|
||||
static InterfaceTable *ft;
|
||||
|
||||
namespace fluid {
|
||||
namespace sc{
|
||||
using ViewType = fluid::FluidTensorView<float, 2>;
|
||||
|
||||
/**
|
||||
A descendent of SndBuf that will populate itself
|
||||
from the NRT mirror buffers given a world and a bufnum
|
||||
**/
|
||||
struct NRTBuf: public SndBuf
|
||||
{
|
||||
NRTBuf(SndBuf& b):SndBuf(b){}
|
||||
|
||||
NRTBuf(World* world,size_t bufnum):
|
||||
NRTBuf(*World_GetNRTBuf(world,bufnum))
|
||||
{}
|
||||
};
|
||||
|
||||
/**
|
||||
A combination of SndBuf and FluidTensorView, for simple transfer of data
|
||||
|
||||
Given a World* and a buffer number, this will populate its SndBuf stuff
|
||||
from the NRT mirror buffers, and create a FluidTensorView wrapper of
|
||||
appropriate dimensions.
|
||||
|
||||
The SndBuf can then be 'transferred' back to the RT buffers once we're done with it,
|
||||
and SC notified of the update. (In the context of SequencedCommands, in which this is meant
|
||||
to be used, this would happen at Stage3() on the real-time thread)
|
||||
|
||||
**/
|
||||
class SCBufferView: public NRTBuf,ViewType
|
||||
{
|
||||
public:
|
||||
SCBufferView() = delete;
|
||||
SCBufferView(SCBufferView&) = delete;
|
||||
SCBufferView operator=(SCBufferView&) = delete;
|
||||
|
||||
SCBufferView(size_t bufnum,World* world):
|
||||
NRTBuf(world,bufnum),
|
||||
ViewType({0,{static_cast<size_t>(frames),
|
||||
static_cast<size_t>(channels)}},NRTBuf::data),
|
||||
mBufnum(bufnum), mWorld(world)
|
||||
{}
|
||||
|
||||
void assignToRT()
|
||||
{
|
||||
SndBuf* rtBuf = World_GetBuf(mWorld,mBufnum);
|
||||
*rtBuf = static_cast<SndBuf>(*this);
|
||||
mWorld->mSndBufUpdates[mBufnum].writes++;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t mBufnum;
|
||||
World * mWorld;
|
||||
};
|
||||
|
||||
class NRTCommandBase{
|
||||
|
||||
|
||||
template <typename T>
|
||||
using AsyncFn = bool (T::*)();
|
||||
|
||||
template <typename T>
|
||||
using AsyncCleanup = void (T::*) ();
|
||||
|
||||
template<typename T, AsyncFn<T> F>
|
||||
static bool call(World*,void* x)
|
||||
{
|
||||
return (static_cast<T*>(x)->*F)();
|
||||
}
|
||||
|
||||
template<typename T, AsyncCleanup<T> F>
|
||||
static void call(World*, void* x)
|
||||
{
|
||||
(static_cast<T*>(x)->*F)();
|
||||
}
|
||||
|
||||
template<typename T, AsyncFn<T> Stage2, AsyncFn<T> Stage3, AsyncFn<T> Stage4, AsyncCleanup<T> Cleanup>
|
||||
void cmd(std::string name)
|
||||
{
|
||||
(*ft->fDoAsynchronousCommand)( mWorld, mReplyAddr,name.c_str(),this,
|
||||
call<T,Stage2>, call<T,Stage3>, call<T,Stage4>,call<T,Cleanup>,
|
||||
mCompletionMsgSize,mCompletionMsgData);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void cm()
|
||||
{
|
||||
cmd<NRTCommandBase,&NRTCommandBase::do_processing,&NRTCommandBase::post_processing,&NRTCommandBase::dummy_stage,&NRTCommandBase::dummy_cleanup>("Bob");
|
||||
}
|
||||
|
||||
|
||||
|
||||
public:
|
||||
NRTCommandBase() = delete;
|
||||
NRTCommandBase(NRTCommandBase&) = delete;
|
||||
NRTCommandBase& operator=(NRTCommandBase&) = delete;
|
||||
|
||||
|
||||
NRTCommandBase(size_t buffers_in, size_t buffers_out, World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr):
|
||||
input_buffers(buffers_in,-1), output_buffers(buffers_out,-1),
|
||||
mWorld(inWorld),mReplyAddr(replyAddr)
|
||||
{
|
||||
for(auto&& i: input_buffers)
|
||||
i = args->geti();
|
||||
|
||||
for(auto&& o: output_buffers)
|
||||
o = args->geti();
|
||||
|
||||
mCompletionMsgSize = args->getbsize();
|
||||
mCompletionMsgData = 0;
|
||||
if(mCompletionMsgSize)
|
||||
{
|
||||
//allocate string
|
||||
mCompletionMsgData = (char*)RTAlloc(mWorld,mCompletionMsgSize);
|
||||
args->getb(mCompletionMsgData,mCompletionMsgSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
virtual void process()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool do_processing()
|
||||
{
|
||||
|
||||
return true;
|
||||
}
|
||||
bool post_processing()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool dummy_stage() { return true; }
|
||||
void dummy_cleanup() {}
|
||||
|
||||
std::vector<long> input_buffers;
|
||||
std::vector<long> output_buffers;
|
||||
|
||||
protected:
|
||||
World * mWorld;
|
||||
void* mReplyAddr;
|
||||
const char* cmdName;
|
||||
void *cmdData;
|
||||
size_t mCompletionMsgSize;
|
||||
char* mCompletionMsgData;
|
||||
|
||||
};
|
||||
} //namespace supercollider
|
||||
}//namespace fluid
|
||||
|
||||
|
||||
template<typename NRT_Plug>
|
||||
void command(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr)
|
||||
{
|
||||
NRT_Plug cmd(inWorld, inUserData, args, replyAddr);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
template <typename NRT_Plug>
|
||||
void registerCommand(InterfaceTable* ft, const char* name)
|
||||
{
|
||||
//typedef void (*PlugInCmdFunc)(World *inWorld, void* inUserData, struct sc_msg_iter *args, void *replyAddr);
|
||||
PlugInCmdFunc cmd = command<NRT_Plug>;
|
||||
|
||||
|
||||
|
||||
(*ft->fDefinePlugInCmd)(name,cmd,nullptr);
|
||||
}
|
||||
|
||||
|
||||
//PluginLoad(BufferFunTime) {
|
||||
//
|
||||
// using fluid::sc::NRTCommandBase;
|
||||
//
|
||||
// registerCommand<NRTCommandBase>(inTable, "ASyncBufMatch");
|
||||
//
|
||||
//// ft = inTable;
|
||||
//// //BufGen version: all in the NRT thread
|
||||
////// DefineBufGen("BufMatch", BufferMatch);
|
||||
//// //ASync version: swaps between NRT and RT threads
|
||||
//// DefinePlugInCmd("AsyncBufMatch", ASyncBufferFun_Main, nullptr);
|
||||
////
|
||||
//}
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
s.reboot
|
||||
|
||||
//Quickie test of buffer allocation working
|
||||
//Read a sound file
|
||||
a = Buffer.read(s,"/Users/owen/Desktop/denoise_stn/sources/01-mix.wav");
|
||||
//Pass buffer to this, along with a rank. It will allocate a new buffer,
|
||||
//size it appropriately (in our server code) and return the new object
|
||||
f = FDBufferExperiments.allocMatch(s,a,rank:5);
|
||||
//Make sure everything is kosher:
|
||||
a.query
|
||||
f.query
|
||||
|
||||
|
||||
//Try full async version
|
||||
s.reboot
|
||||
|
||||
//Quickie test of buffer allocation working
|
||||
//Read a sound file
|
||||
a = Buffer.read(s,"/Users/owen/Desktop/denoise_stn/sources/01-mix.wav");
|
||||
//Pass buffer to this, along with a rank. It will allocate a new buffer,
|
||||
//size it appropriately (in our server code) and return the new object
|
||||
f = FDBufferExperiments.allocMatchAsync(s,a,rank:5);
|
||||
//Make sure everything is kosher:
|
||||
a.query
|
||||
f.query
|
||||
Loading…
Reference in New Issue