Merge branch 'refactor-review' of https://bitbucket.org/flucoma/flucoma-supercollider into refactor-review
commit
f78fae5dbc
@ -1,20 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.3)
|
|
||||||
get_filename_component(PLUGIN ${CMAKE_CURRENT_LIST_DIR} NAME_WE)
|
|
||||||
message("Configuring ${PLUGIN}")
|
|
||||||
set(FILENAME ${PLUGIN}.cpp)
|
|
||||||
|
|
||||||
add_library(
|
|
||||||
${PLUGIN}
|
|
||||||
MODULE
|
|
||||||
${FILENAME}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(
|
|
||||||
${PLUGIN} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/../../include
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(
|
|
||||||
${PLUGIN} PRIVATE FLUID_DECOMPOSITION
|
|
||||||
)
|
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/../../scripts/target_post.cmake)
|
|
||||||
@ -1,157 +0,0 @@
|
|||||||
//Can I reallocate buffers on the server? Yes I can.
|
|
||||||
#include "SC_PlugIn.h"
|
|
||||||
|
|
||||||
static InterfaceTable *ft;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Can we do buffer resizing in a BufGen. I think so.
|
|
||||||
//Goal here is to mimic the NMF case, allowing
|
|
||||||
//the dst buffer to be resized accordingly (and not need to
|
|
||||||
// precalculate the number of frames in advance lang-side
|
|
||||||
|
|
||||||
/**
|
|
||||||
/buf_gen approach: Seems to work, but having to do the 'swap' bewteen NRT mirror buffer and RT buffer
|
|
||||||
in the same thread seems smelly, given how the allocation sequeneces in SC_SequenceCommand seem to work.
|
|
||||||
**/
|
|
||||||
void bufferMatch(World *world, struct SndBuf *srcBuf, struct sc_msg_iter *msg) {
|
|
||||||
size_t srcFrameCount = srcBuf->frames;
|
|
||||||
size_t srcChanCount = srcBuf->channels;
|
|
||||||
|
|
||||||
long dstBufNum = msg->geti();
|
|
||||||
size_t rank = msg->geti();
|
|
||||||
|
|
||||||
if (dstBufNum == -1) {
|
|
||||||
Print("BufferMatch is not happy because there is no output buffer "
|
|
||||||
"specified.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// This sequence follows what I saw in SC_SequenceCommand.cpp. Pretty much.
|
|
||||||
// Get the NRT thread mirror buffer
|
|
||||||
SndBuf *dstBufNRT = World_GetNRTBuf(world, dstBufNum);
|
|
||||||
// Call the allocation function on that
|
|
||||||
SCErr err = ft->fBufAlloc(dstBufNRT, srcChanCount * rank, srcFrameCount,
|
|
||||||
srcBuf->samplerate);
|
|
||||||
// If we were posh, we'd check for errors
|
|
||||||
// Norhing will happen, unless we (a) assign the allocated data back to the
|
|
||||||
// main buffer pool (b?) Tell the server the buffer has changed Get the RT
|
|
||||||
// buffer
|
|
||||||
SndBuf *dstBuf = World_GetBuf(world, dstBufNum);
|
|
||||||
// Assign value to our NRT buffer pointer's value
|
|
||||||
*dstBuf = *dstBufNRT;
|
|
||||||
// Ping the server
|
|
||||||
world->mSndBufUpdates[dstBufNum].writes++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
ASync command version. Is this an abuse of Async command? Doesn't *seem* to be, but there is almost no
|
|
||||||
documentation for its proper use :-|
|
|
||||||
**/
|
|
||||||
//Struct that holds all our state between stages
|
|
||||||
struct BufferFunTimeCmdData
|
|
||||||
{
|
|
||||||
long dstbuf;
|
|
||||||
long srcbuf;
|
|
||||||
size_t rank;
|
|
||||||
|
|
||||||
SndBuf* newdst;
|
|
||||||
};
|
|
||||||
|
|
||||||
//'Stage2()' happens in the NRT thread. Here we do our heavy stuff
|
|
||||||
bool aSyncBufferFunNrtStage(World *world, void *inUserData) {
|
|
||||||
BufferFunTimeCmdData *data = (BufferFunTimeCmdData *)inUserData;
|
|
||||||
|
|
||||||
SndBuf *src = World_GetNRTBuf(world, data->srcbuf);
|
|
||||||
SndBuf *dst = World_GetNRTBuf(world, data->dstbuf);
|
|
||||||
SCErr err = ft->fBufAlloc(dst, src->channels * data->rank, src->frames,
|
|
||||||
src->samplerate);
|
|
||||||
data->newdst = dst;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//'Statge3()' happens back in the RT thread, here we swap our new buffers
|
|
||||||
//SC will send the completion message after this
|
|
||||||
bool aSyncBufferFunRtStage(World *world, void *inUserData) {
|
|
||||||
BufferFunTimeCmdData *data = (BufferFunTimeCmdData *)inUserData;
|
|
||||||
// Norhing will happen, unless we (a) assign the allocated data back to the
|
|
||||||
// main buffer pool (b?) Tell the server the buffer has changed Get the RT
|
|
||||||
// buffer
|
|
||||||
SndBuf *dstBuf = World_GetBuf(world, data->dstbuf);
|
|
||||||
// Assign value to our NRT buffer pointer's value
|
|
||||||
*dstBuf = *data->newdst;
|
|
||||||
// Ping the server
|
|
||||||
world->mSndBufUpdates[data->dstbuf].writes++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//'Stage 4()' is back on the NRT, we don't have anything to do here. SC will send 'done' after this
|
|
||||||
bool aSyncBufferFunFinalBit(World *world, void *inUserData) { return true; }
|
|
||||||
|
|
||||||
//Here we free any resources, including the struct we made at the start
|
|
||||||
void aSyncBufferFunCleanUp(World *world, void *inUserData) {
|
|
||||||
BufferFunTimeCmdData *data = (BufferFunTimeCmdData *)inUserData;
|
|
||||||
RTFree(world, data);
|
|
||||||
// scsynth will take care of the completion message
|
|
||||||
}
|
|
||||||
|
|
||||||
//This is our entry point. We need to make a struct and populate it with good things
|
|
||||||
void aSyncBufferFunMain(World *inWorld, void *inUserData,
|
|
||||||
struct sc_msg_iter *msg, void *replyAddr) {
|
|
||||||
BufferFunTimeCmdData *data =
|
|
||||||
(BufferFunTimeCmdData *)RTAlloc(inWorld, sizeof(BufferFunTimeCmdData));
|
|
||||||
|
|
||||||
data->srcbuf = msg->geti();
|
|
||||||
data->dstbuf = msg->geti();
|
|
||||||
data->rank = msg->geti();
|
|
||||||
|
|
||||||
bool ok = true;
|
|
||||||
|
|
||||||
if (data->srcbuf < 0) {
|
|
||||||
Print("No source buffer");
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data->dstbuf < 0) {
|
|
||||||
Print("No dst buffer");
|
|
||||||
ok = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ok) {
|
|
||||||
RTFree(inWorld, data);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// how to pass a string argument: [WILL BE USEFUL FOR WINDOW FUNCTIONS?]
|
|
||||||
// const char *name = msg->gets(); // get the string argument
|
|
||||||
// if (name) {
|
|
||||||
// data->name = (char*)RTAlloc(inWorld, strlen(name)+1); // allocate
|
|
||||||
// space, free it in cmdCleanup. strcpy(data->name, name); // copy the
|
|
||||||
// string
|
|
||||||
// }
|
|
||||||
|
|
||||||
//Deal with completion message
|
|
||||||
size_t completionMsgSize = msg->getbsize();
|
|
||||||
char* completionMsgString = 0;
|
|
||||||
if(completionMsgSize)
|
|
||||||
{
|
|
||||||
//allocate string
|
|
||||||
completionMsgString = (char*)RTAlloc(inWorld,completionMsgSize);
|
|
||||||
msg->getb(completionMsgString,completionMsgSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Now, set the wheels in motion
|
|
||||||
DoAsynchronousCommand(inWorld, replyAddr, "AsyncBufMatch", data,
|
|
||||||
(AsyncStageFn)aSyncBufferFunNrtStage,
|
|
||||||
(AsyncStageFn)aSyncBufferFunRtStage,
|
|
||||||
(AsyncStageFn)aSyncBufferFunFinalBit,
|
|
||||||
aSyncBufferFunCleanUp, completionMsgSize,
|
|
||||||
completionMsgString);
|
|
||||||
}
|
|
||||||
|
|
||||||
PluginLoad(BufferFunTime) {
|
|
||||||
ft = inTable;
|
|
||||||
//BufGen version: all in the NRT thread
|
|
||||||
DefineBufGen("BufMatch", bufferMatch);
|
|
||||||
//ASync version: swaps between NRT and RT threads
|
|
||||||
DefinePlugInCmd("AsyncBufMatch", aSyncBufferFunMain, nullptr);
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
s.reboot
|
|
||||||
|
|
||||||
//Quickie test of buffer allocation working
|
|
||||||
//Read a sound file
|
|
||||||
a = Buffer.read(s,"../../release-packaging/AudioFiles/Tremblay-AaS-SynthTwoVoices-M.wav".resolveRelative);
|
|
||||||
//size it appropriately (in our server code) and return the new object
|
|
||||||
f = FluidBufExperiments.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,"../../release-packaging/AudioFiles/Tremblay-AaS-SynthTwoVoices-M.wav".resolveRelative);
|
|
||||||
//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 = FluidBufExperiments.allocMatchAsync(s,a,rank:5);
|
|
||||||
//Make sure everything is kosher:
|
|
||||||
a.query
|
|
||||||
f.query
|
|
||||||
Loading…
Reference in New Issue