|
|
|
|
@ -14,8 +14,7 @@ static InterfaceTable *ft;
|
|
|
|
|
/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)
|
|
|
|
|
{
|
|
|
|
|
void bufferMatch(World *world, struct SndBuf *srcBuf, struct sc_msg_iter *msg) {
|
|
|
|
|
size_t srcFrameCount = srcBuf->frames;
|
|
|
|
|
size_t srcChanCount = srcBuf->channels;
|
|
|
|
|
|
|
|
|
|
@ -23,17 +22,20 @@ void BufferMatch(World *world, struct SndBuf *srcBuf, struct sc_msg_iter *msg)
|
|
|
|
|
size_t rank = msg->geti();
|
|
|
|
|
|
|
|
|
|
if (dstBufNum == -1) {
|
|
|
|
|
Print("BufferMatch is not happy because there is no output buffer specified.\n");
|
|
|
|
|
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);
|
|
|
|
|
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
|
|
|
|
|
// 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;
|
|
|
|
|
@ -56,24 +58,24 @@ struct BufferFunTimeCmdData
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//'Stage2()' happens in the NRT thread. Here we do our heavy stuff
|
|
|
|
|
bool ASyncBufferFun_NRTStage(World* world, void* inUserData)
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
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 ASyncBufferFun_RTStage(World* world, void* inUserData)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
// 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;
|
|
|
|
|
@ -83,23 +85,20 @@ bool ASyncBufferFun_RTStage(World* world, void* inUserData)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//'Stage 4()' is back on the NRT, we don't have anything to do here. SC will send 'done' after this
|
|
|
|
|
bool ASyncBufferFun_FinalBit(World* world, void* inUserData)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
bool aSyncBufferFunFinalBit(World *world, void *inUserData) { return true; }
|
|
|
|
|
|
|
|
|
|
//Here we free any resources, including the struct we made at the start
|
|
|
|
|
void ASyncBufferFun_CleanUp(World* world, void* inUserData)
|
|
|
|
|
{
|
|
|
|
|
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 ASyncBufferFun_Main(World *inWorld, void* inUserData, struct sc_msg_iter *msg, void *replyAddr)
|
|
|
|
|
{
|
|
|
|
|
BufferFunTimeCmdData* data = (BufferFunTimeCmdData*)RTAlloc(inWorld, sizeof(BufferFunTimeCmdData));
|
|
|
|
|
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();
|
|
|
|
|
@ -107,30 +106,27 @@ void ASyncBufferFun_Main(World *inWorld, void* inUserData, struct sc_msg_iter *m
|
|
|
|
|
|
|
|
|
|
bool ok = true;
|
|
|
|
|
|
|
|
|
|
if(data->srcbuf < 0 )
|
|
|
|
|
{
|
|
|
|
|
if (data->srcbuf < 0) {
|
|
|
|
|
Print("No source buffer");
|
|
|
|
|
ok = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(data->dstbuf < 0 )
|
|
|
|
|
{
|
|
|
|
|
if (data->dstbuf < 0) {
|
|
|
|
|
Print("No dst buffer");
|
|
|
|
|
ok = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!ok)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
|
// 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
|
|
|
|
|
@ -144,20 +140,18 @@ void ASyncBufferFun_Main(World *inWorld, void* inUserData, struct sc_msg_iter *m
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Now, set the wheels in motion
|
|
|
|
|
DoAsynchronousCommand(inWorld,replyAddr,"AsyncBufMatch",
|
|
|
|
|
data,
|
|
|
|
|
(AsyncStageFn)ASyncBufferFun_NRTStage,
|
|
|
|
|
(AsyncStageFn)ASyncBufferFun_RTStage,
|
|
|
|
|
(AsyncStageFn)ASyncBufferFun_FinalBit,
|
|
|
|
|
ASyncBufferFun_CleanUp,
|
|
|
|
|
completionMsgSize, completionMsgString);
|
|
|
|
|
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);
|
|
|
|
|
DefineBufGen("BufMatch", bufferMatch);
|
|
|
|
|
//ASync version: swaps between NRT and RT threads
|
|
|
|
|
DefinePlugInCmd("AsyncBufMatch", ASyncBufferFun_Main, nullptr);
|
|
|
|
|
|
|
|
|
|
DefinePlugInCmd("AsyncBufMatch", aSyncBufferFunMain, nullptr);
|
|
|
|
|
}
|
|
|
|
|
|