From baf5f329483b08dc4fea595ff66e98de4d3d1d2d Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 5 Aug 2019 15:53:37 +0100 Subject: [PATCH 01/42] release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp: Function not metric, in this particular instance --- release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp index 84a25b0..4893b02 100644 --- a/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp @@ -71,7 +71,7 @@ ARGUMENT:: fftSize The inner FFT/IFFT size. It should be at least 4 samples long, at least the size of the window, and a power of 2. Making it larger allows an oversampling of the spectral precision. The -1 default value will default to windowSize. ARGUMENT:: action - A Function to be evaluated once the offline process has finished and indices instance variables have been updated on the client side. The metric will be passed indices as an argument. + A Function to be evaluated once the offline process has finished and indices instance variables have been updated on the client side. The function will be passed indices as an argument. RETURNS:: Nothing, as the destination buffer is declared in the function call. From 2aa3d545d470fd76bc5675e2c31e6473c72f706b Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 26 Aug 2019 14:52:20 +0100 Subject: [PATCH 02/42] fluidmfcc: added the menu to choose which buffer to play, and a restart button --- .../HelpSource/Classes/FluidMFCC.schelp | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidMFCC.schelp b/release-packaging/HelpSource/Classes/FluidMFCC.schelp index 8261515..d685eb2 100644 --- a/release-packaging/HelpSource/Classes/FluidMFCC.schelp +++ b/release-packaging/HelpSource/Classes/FluidMFCC.schelp @@ -131,7 +131,7 @@ STRONG::A musical example:: CODE:: //program that freezes mfcc spectra, then looks for matches between two frozen spectra ( -SynthDef("MFCCJamz", {arg freq=220, source = 0, buffer, mfccBus, distBus, t_freeze0=0, t_freeze1=0, onsetsOn0=0, onsetsOn1=0; +SynthDef("MFCCJamz", {arg freq=220, source = 0, buffer, mfccBus, distBus, t_freeze0=0, t_freeze1=0, onsetsOn0=0, onsetsOn1=0, restart = 1; var sound, mfcc, mfccFreeze0, mfccFreeze1, dist0, dist1, closest, slice; sound = SelectX.ar(source, [ @@ -141,7 +141,7 @@ SynthDef("MFCCJamz", {arg freq=220, source = 0, buffer, mfccBus, distBus, t_free Pulse.ar(freq, 0.5, 0.1), WhiteNoise.ar(0.1), PinkNoise.ar(0.1), - PlayBuf.ar(1, buffer, 1, loop:1) + PlayBuf.ar(1, buffer, 1, loop:1, trigger:restart) ]); slice = FluidOnsetSlice.ar(sound); //onset detection for mfcc freeze on onset @@ -168,7 +168,7 @@ SynthDef("MFCCJamz", {arg freq=220, source = 0, buffer, mfccBus, distBus, t_free ( -var buffers, buffer, paths, mfccBus, freezeBus, distBus, win, sliders, updateRout, winRange, currentMFCC, synth, movingGUI, trainButtons, oscFunc, closestBus; +var buffers, buffer, paths, mfccBus, freezeBus, distBus, win, sliders, updateRout, winRange, currentMFCC, synth, movingGUI, trainButtons, playbackButton, oscFunc, closestBus; winRange = 100; @@ -214,7 +214,7 @@ s.waitForBoot({ .maxWidth_(150), PopUpMenu().items_(paths) .action_{|menu| synth.set(\buffer, buffers[menu.value])} - .maxWidth_(150); + .maxWidth_(150) ]; //the buttons under the two frozen mfcc displays @@ -237,10 +237,18 @@ s.waitForBoot({ trainButtons.add(StaticText()); }; + playbackButton = Button().states_([["restart", Color.black, Color.green]]) + .mouseDownAction_({arg butt; + synth.set(\restart, 0.5); + }) + .action_{arg butt; + synth.set(\restart, -0.5); + }; + win.layout_(HLayout( VLayout(sliders[0], movingGUI[0], movingGUI[1], movingGUI[2]), - VLayout(sliders[1],HLayout(trainButtons[0],trainButtons[1]), HLayout(trainButtons[2],trainButtons[3])), - VLayout(sliders[2],HLayout(trainButtons[4],trainButtons[5]), HLayout(trainButtons[6],trainButtons[7])) + VLayout(sliders[1],HLayout(trainButtons[0],trainButtons[1]), HLayout(trainButtons[2],trainButtons[3]), movingGUI[3]), + VLayout(sliders[2],HLayout(trainButtons[4],trainButtons[5]), HLayout(trainButtons[6],trainButtons[7]), playbackButton) )); win.front; win.onClose_{synth.free; oscFunc.free; updateRout.stop}; From b0b2c7d3b3e1cc50a51326d72a1d5870fbd8b0f1 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 3 Sep 2019 15:05:37 +0100 Subject: [PATCH 03/42] Belated commit of threading updates for SC --- include/FluidSCWrapper.hpp | 119 ++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 35 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index 62510cd..cdfe8f5 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -8,6 +8,8 @@ #include +#include +#include #include #include #include @@ -161,14 +163,39 @@ template class NonRealTime: public SCUnit { using ParamSetType = typename Client::ParamSetType; + public: static void setup(InterfaceTable *ft, const char *name) { registerUnit(ft, name); ft->fDefineUnitCmd(name, "cancel", doCancel); + ft->fDefineUnitCmd(name, "queue_enabled", [](struct Unit* unit, struct sc_msg_iter* args) + { + auto w = static_cast(unit); + w->mQueueEnabled = args->geti(0); + w->mFifoMsg.Set(w->mWorld,[](FifoMsg* f) + { + auto w = static_cast(f->mData); + w->mClient.setQueueEnabled(w->mQueueEnabled); + },nullptr,w); + Wrapper::getInterfaceTable()->fSendMsgFromRT(w->mWorld, w->mFifoMsg); + }); + ft->fDefineUnitCmd(name, "synchronous", [](struct Unit* unit, struct sc_msg_iter* args) + { + auto w = static_cast(unit); + w->mSynchronous = args->geti(0); + w->mFifoMsg.Set(w->mWorld,[](FifoMsg* f) + { + auto w = static_cast(f->mData); + w->mClient.setSynchronous(w->mSynchronous); + },nullptr,w); + Wrapper::getInterfaceTable()->fSendMsgFromRT(w->mWorld, w->mFifoMsg); + }); } + + /// Final input is the doneAction, not a param, so we skip it in the controlsIterator NonRealTime() : mControlsIterator{mInBuf,static_cast(static_cast(mNumInputs) - mSpecialIndex - 1)} @@ -181,36 +208,46 @@ public: /// init() sets up the NRT process via the SC NRT thread, and then sets our UGen calc function going void init() { - mClient.setSynchronous(false); mFifoMsg.Set(mWorld, initNRTJob, nullptr, this); mWorld->ft->fSendMsgFromRT(mWorld,mFifoMsg); + + //we want to poll thread roughly every 20ms + checkThreadInterval = static_cast(0.02 / controlDur()); set_calc_function(); }; /// The calc function. Checks to see if we've cancelled, spits out progress, launches tidy up when complete void poll(int) { - if(!mClient.done()) - { +// if(!mClient.done()) +// { out0(0) = static_cast(mClient.progress()); - } - else { +// } +// else { + if(0 == pollCounter++) + { + mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, + postProcess, exchangeBuffers, tidyUp, destroy, + 0, nullptr); + } + + pollCounter %= checkThreadInterval; + // if(mClient.state() == kDone) // mDone = true; - mCalcFunc = mWorld->ft->fClearUnitOutputs; +// mCalcFunc = mWorld->ft->fClearUnitOutputs; // if(!mDone) - mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, - postProcess, exchangeBuffers, tidyUp, destroy, - 0, nullptr); - - } + +// } } + + static void nop(Unit*, int) {} /// To be called on NRT thread. Validate parameters and commence processing in new thread static void initNRTJob(FifoMsg* f) { auto w = static_cast(f->mData); - + w->mDone = false; Result result = validateParameters(w); if (!result.ok()) @@ -219,7 +256,9 @@ public: // w->mDone = true; return; } - +// w->mClient.setSynchronous(mSynchronous); +// mClient.setQueu + w->mClient.enqueue(w->mParams); w->mClient.process(); } @@ -228,22 +267,27 @@ public: { auto w = static_cast(data); Result r; - w->mClient.checkProgress(r); - if(r.status() == Result::Status::kCancelled) - { - std::cout << Wrapper::getName() << ": Processing cancelled \n"; - return false; - } + ProcessState s = w->mClient.checkProgress(r); - if(!r.ok()) + if(s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) { - std::cout << "ERROR: " << Wrapper::getName() << ": " << r.message().c_str() << '\n'; - return false; + w->mDone = true; + + if(r.status() == Result::Status::kCancelled) + { + std::cout << Wrapper::getName() << ": Processing cancelled \n"; + return false; + } + + if(!r.ok()) + { + std::cout << "ERROR: " << Wrapper::getName() << ": " << r.message().c_str() << '\n'; + return false; + } + + return true; } - -// w->mDone = true; - - return true; + return false; } /// swap NRT buffers back to RT-land @@ -252,14 +296,15 @@ public: static bool tidyUp(World *world, void *data) { return static_cast(data)->tidyUp(world); } /// Now we're actually properly done, call the UGen's done action (possibly destroying this instance) - static void destroy(World *world, void *data) + static void destroy(World* world, void* data) { auto w = static_cast(data); -// if(w->mDone) -// { - int doneAction = static_cast(w->in0(static_cast(w->mNumInputs - 1))); + if(w->mDone && w->mNumInputs > 0) //don't check for doneAction if UGen has no ins + { + int doneAction = static_cast(w->in0(static_cast(w->mNumInputs - 1))); //doneAction is last input; THIS IS THE LAW + if(doneAction >= 2) w->mCalcFunc = nop; world->ft->fDoneAction(doneAction,w); -// } + } } static void doCancel(Unit *unit, sc_msg_iter*) @@ -312,13 +357,16 @@ private: FloatControlsIter mControlsIterator; FifoMsg mFifoMsg; - char * mCompletionMessage = nullptr; - void * mReplyAddr = nullptr; + char* mCompletionMessage = nullptr; + void* mReplyAddr = nullptr; const char *mName = nullptr; + size_t checkThreadInterval; + size_t pollCounter{0}; protected: ParamSetType mParams; Client mClient; - + bool mSynchronous{true}; + bool mQueueEnabled{false}; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -367,6 +415,7 @@ using FluidSCWrapperBase = FluidSCWrapperImpl, is template class FluidSCWrapper : public impl::FluidSCWrapperBase { + using FloatControlsIter = impl::FloatControlsIter; // Iterate over arguments via callbacks from params object @@ -441,7 +490,7 @@ public: p.template setParameterValues(verbose, world, inputs); if (constrain)p.constrainParameterValues(); } else { - std::cout << "ERROR: " << getName() << ": parameter count mismatch. Perhaps your binary plugins and SC sources are different versions"; + std::cout << "ERROR: " << getName() << ": parameter count mismatch. Perhaps your binary plugins and SC sources are different versions\n"; //TODO: work out how to bring any further work to a halt } return p; From fad43f18b24cb1ea6dde325e29e4a5378c0b6889 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Thu, 5 Sep 2019 14:11:24 +0100 Subject: [PATCH 04/42] wrapper: tidying --- include/FluidSCWrapper.hpp | 32 ++++++++------------------------ 1 file changed, 8 insertions(+), 24 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index cdfe8f5..cfb8bf9 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -219,26 +219,15 @@ public: /// The calc function. Checks to see if we've cancelled, spits out progress, launches tidy up when complete void poll(int) { -// if(!mClient.done()) -// { - out0(0) = static_cast(mClient.progress()); -// } -// else { - if(0 == pollCounter++) - { - mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, - postProcess, exchangeBuffers, tidyUp, destroy, - 0, nullptr); - } - - pollCounter %= checkThreadInterval; - -// if(mClient.state() == kDone) -// mDone = true; -// mCalcFunc = mWorld->ft->fClearUnitOutputs; -// if(!mDone) + out0(0) = static_cast(mClient.progress()); -// } + if(0 == pollCounter++) + { + mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, + postProcess, exchangeBuffers, tidyUp, destroy, + 0, nullptr); + } + pollCounter %= checkThreadInterval; } static void nop(Unit*, int) {} @@ -253,11 +242,8 @@ public: if (!result.ok()) { std::cout << "ERROR: " << Wrapper::getName() << ": " << result.message().c_str() << std::endl; -// w->mDone = true; return; } -// w->mClient.setSynchronous(mSynchronous); -// mClient.setQueu w->mClient.enqueue(w->mParams); w->mClient.process(); } @@ -311,8 +297,6 @@ public: { static_cast(unit)->mClient.cancel(); } - - private: static Result validateParameters(NonRealTime *w) From 05f7c044b0ba3d5f0037f44918493e4fedb63480 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Thu, 5 Sep 2019 16:00:37 +0100 Subject: [PATCH 05/42] Stop horrible race condition by ensuring that only one thread-checking aync command is ever in progress --- include/FluidSCWrapper.hpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index cfb8bf9..8ca7dc3 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -194,8 +194,6 @@ public: }); } - - /// Final input is the doneAction, not a param, so we skip it in the controlsIterator NonRealTime() : mControlsIterator{mInBuf,static_cast(static_cast(mNumInputs) - mSpecialIndex - 1)} @@ -209,8 +207,7 @@ public: void init() { mFifoMsg.Set(mWorld, initNRTJob, nullptr, this); - mWorld->ft->fSendMsgFromRT(mWorld,mFifoMsg); - + mWorld->ft->fSendMsgFromRT(mWorld,mFifoMsg); //we want to poll thread roughly every 20ms checkThreadInterval = static_cast(0.02 / controlDur()); set_calc_function(); @@ -223,9 +220,10 @@ public: if(0 == pollCounter++) { - mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, - postProcess, exchangeBuffers, tidyUp, destroy, - 0, nullptr); + mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, + postProcess, exchangeBuffers, tidyUp, destroy, + 0, nullptr); + mCalcFunc = nop; } pollCounter %= checkThreadInterval; } @@ -237,6 +235,7 @@ public: { auto w = static_cast(f->mData); w->mDone = false; + Result result = validateParameters(w); if (!result.ok()) @@ -258,7 +257,7 @@ public: if(s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) { w->mDone = true; - + if(r.status() == Result::Status::kCancelled) { std::cout << Wrapper::getName() << ": Processing cancelled \n"; @@ -270,9 +269,9 @@ public: std::cout << "ERROR: " << Wrapper::getName() << ": " << r.message().c_str() << '\n'; return false; } - return true; } + w->template set_calc_function(); return false; } @@ -288,7 +287,6 @@ public: if(w->mDone && w->mNumInputs > 0) //don't check for doneAction if UGen has no ins { int doneAction = static_cast(w->in0(static_cast(w->mNumInputs - 1))); //doneAction is last input; THIS IS THE LAW - if(doneAction >= 2) w->mCalcFunc = nop; world->ft->fDoneAction(doneAction,w); } } From 1be9076bbe5f6fc0f1f61a9a528e1c11609627a7 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 9 Sep 2019 13:45:33 +0100 Subject: [PATCH 06/42] Thread demo client --- .../Classes/FluidBufThreadDemo.sc | 50 +++++++++++++++++++ src/FluidBufThreadDemo/CMakeLists.txt | 20 ++++++++ src/FluidBufThreadDemo/FluidBufThreadDemo.cpp | 13 +++++ 3 files changed, 83 insertions(+) create mode 100644 release-packaging/Classes/FluidBufThreadDemo.sc create mode 100644 src/FluidBufThreadDemo/CMakeLists.txt create mode 100644 src/FluidBufThreadDemo/FluidBufThreadDemo.cpp diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc new file mode 100644 index 0000000..ddab3c5 --- /dev/null +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -0,0 +1,50 @@ +FluidBufThreadDemo : UGen{ + var <>synth, <>server; + + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + + var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; + + source = source.asUGenInput; + features = features.asUGenInput; + + source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; + features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; + + //NB For wrapped versions of NRT classes, we set the params for maxima to + //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + } + + *process { |server, result, time, action| + + var synth,instance; + + result = result.asUGenInput; + + result.isNil.if {"FluidBufThreadDemo: Invalid source buffer".throw}; + + server = server ? Server.default; + server.ifNotRunning({ + "WARNING: Server not running".postln; + ^nil; + }); + + synth = { instance = FluidBufPitch.kr(result, time, doneAction:Done.freeSelf)}.play(server); + + forkIfNeeded{ + synth.waitForFree; + server.sync; + result = server.cachedBufferAt(result); result.updateInfo; server.sync; + action.value(result); + }; + instance.synth = synth; + instance.server = server; + ^instance; + } + + cancel{ + if(this.server.notNil) + {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + } +} diff --git a/src/FluidBufThreadDemo/CMakeLists.txt b/src/FluidBufThreadDemo/CMakeLists.txt new file mode 100644 index 0000000..3693881 --- /dev/null +++ b/src/FluidBufThreadDemo/CMakeLists.txt @@ -0,0 +1,20 @@ +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) diff --git a/src/FluidBufThreadDemo/FluidBufThreadDemo.cpp b/src/FluidBufThreadDemo/FluidBufThreadDemo.cpp new file mode 100644 index 0000000..ae810f3 --- /dev/null +++ b/src/FluidBufThreadDemo/FluidBufThreadDemo.cpp @@ -0,0 +1,13 @@ + +// A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899) + +#include +#include + +static InterfaceTable *ft; + +PluginLoad(OfflineFluidDecompositionUGens) { + ft = inTable; + using namespace fluid::client; + makeSCWrapper("FluidBufThreadDemo", ft); +} From ac187eda9bef305036a02f1ded21d742dc348425 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 9 Sep 2019 17:05:24 +0100 Subject: [PATCH 07/42] release-packaging/Classes/FluidBufThreadDemo.sc: Finish sclang class --- release-packaging/Classes/FluidBufThreadDemo.sc | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index ddab3c5..e00432c 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,19 +1,15 @@ FluidBufThreadDemo : UGen{ var <>synth, <>server; - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr {|source, result, time, doneAction = 0| - var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; - - source = source.asUGenInput; - features = features.asUGenInput; + result = result.asUGenInput; - source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; - features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; + result.isNil.if {"FluidBufThreadDemo: Invalid output buffer".throw}; //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, result, time, doneAction); } *process { |server, result, time, action| @@ -22,7 +18,7 @@ FluidBufThreadDemo : UGen{ result = result.asUGenInput; - result.isNil.if {"FluidBufThreadDemo: Invalid source buffer".throw}; + result.isNil.if {"FluidBufThreadDemo: Invalid output buffer".throw}; server = server ? Server.default; server.ifNotRunning({ @@ -30,7 +26,7 @@ FluidBufThreadDemo : UGen{ ^nil; }); - synth = { instance = FluidBufPitch.kr(result, time, doneAction:Done.freeSelf)}.play(server); + synth = { instance = FluidBufThreadDemo.kr(result, time, doneAction:Done.freeSelf)}.play(server); forkIfNeeded{ synth.waitForFree; From ef701d155160d819fb7e979243cae2bd1a88afa6 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 10 Sep 2019 10:00:26 +0100 Subject: [PATCH 08/42] corrected FluidBBufThreadDemo class def, and first draft of help and tutorial --- .../Classes/FluidBufThreadDemo.sc | 4 +- .../Classes/FluidBufThreadDemo.schelp | 74 +++++++++++++++++++ .../Guides/FluidBufMultiThreading.schelp | 31 ++++++++ .../Guides/FluidDecomposition.schelp | 6 +- 4 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp create mode 100644 release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index e00432c..bbf9f61 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,7 +1,7 @@ FluidBufThreadDemo : UGen{ var <>synth, <>server; - *kr {|source, result, time, doneAction = 0| + *kr {|result, time, doneAction = 0| result = result.asUGenInput; @@ -12,7 +12,7 @@ FluidBufThreadDemo : UGen{ ^this.multiNew(\control, result, time, doneAction); } - *process { |server, result, time, action| + *process { |server, result, time = 1000, action| var synth,instance; diff --git a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp new file mode 100644 index 0000000..fd9ee2f --- /dev/null +++ b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp @@ -0,0 +1,74 @@ +TITLE:: FluidBufThreadDemo +SUMMARY:: A Tutorial Object to Experiment with Multithreading in FluidBuf* Objects +CATEGORIES:: Libraries>FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading + +DESCRIPTION:: +This class implements a simple tutorial object to illustrate and experiment with the behaviour of the FluidBuf* objects. It simply starts a process that will return a single value after a delay, during which it will just wait and do nothing. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: + +The process will return its delay lenght as the first index of the specified destination buffer. + +CLASSMETHODS:: + +METHOD:: process + This is the method that calls for the delay to be . + +ARGUMENT:: server +(describe argument here) + +ARGUMENT:: result + The destination buffer, where the value should be written at the end of the process. + +ARGUMENT:: time + The duration in milliseconds of the delay that the background thread will wait for before yielding the value to the destination buffer. + +ARGUMENT:: action + A function that will be executed upon completion. It is passed the destination buffer as argument. + +RETURNS:: + Nothing, as the destination buffer is specified in the call. + + +METHOD:: kr + This is the UGEN that is holding the link with the background thread. It is called by the 'process' method. + +ARGUMENT:: result + The destination buffer, where the value should be written at the end of the process. + +ARGUMENT:: time + The duration of the delay that the background thread will wait for before yielding the value to the destination buffer. + +ARGUMENT:: doneAction + An integer representing an action to be executed when the process is finished. This can be used to free the enclosing synth, etc. See link::Classes/Done:: for more detail. + +RETURNS:: + It report the approximate job progress, from 0 to 1. + + +INSTANCEMETHODS:: + +METHOD:: cancel + This allows to cancel the process on the background thread safely. + +RETURNS:: + Nothing. + + +EXAMPLES:: + +For a thorough explanation, please refer to the tutorial on link::Guides/FluidBufMultiThreading::. + +CODE:: +// define a destination buffer +b=Buffer.alloc(s,1); + +// simple call, where we query the destination buffer upon completion with the action message. +FluidBufThreadDemo.process(s, b, 1000, {|x|x.get(0,{|y|y.postln});}); + +// a simple call to the UGEN, where we can monitor the progress and interrup the process without killing the synth +{c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; + +// cancel the job +c.cancel +c.free +:: \ No newline at end of file diff --git a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp new file mode 100644 index 0000000..d17e149 --- /dev/null +++ b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp @@ -0,0 +1,31 @@ +TITLE:: FluidBuf* Multithreading Behaviour +SUMMARY:: A tutorial on the multithreading behaviour of offline processes of the FluCoMa toolbox for signal decomposition +CATEGORIES:: Libraries>FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition + +DESCRIPTION:: +The Fluid Decomposition toolbox provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. footnote:: +This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: + +subsection:: basic usage + + show the process method + + show the process returned variable + +subsection:: kr usage + + show the kr monitoring graphically + + show the interruption + + show the interruption again, but in a still working synth, mapping the KR out to a pitch gliss + + +subsection:: bufnmf example + + just for shits and giggles + +subsection: further reading + + a few tutorials on how fucked up it is, includign the thread sync and NRT thread in SC. \ No newline at end of file diff --git a/release-packaging/HelpSource/Guides/FluidDecomposition.schelp b/release-packaging/HelpSource/Guides/FluidDecomposition.schelp index fdbd03a..e3d5d2a 100644 --- a/release-packaging/HelpSource/Guides/FluidDecomposition.schelp +++ b/release-packaging/HelpSource/Guides/FluidDecomposition.schelp @@ -83,4 +83,8 @@ Statistics of buffers subsection:: Utility LINK:: Classes/FluidBufCompose:: -Copy, slice, stack, mix concatenate. All the things you've wanted to do with buffers... \ No newline at end of file +Copy, slice, stack, mix concatenate. All the things you've wanted to do with buffers... + +LINK:: Classes/FluidBufThreadDemo: + +A tutorial object to experiment with multithreading in FluidBuf* objects \ No newline at end of file From 8a60b12996bed3b748f9ac6663552675c7f739ad Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 10 Sep 2019 14:03:00 +0100 Subject: [PATCH 09/42] further along the MT SC tutorial --- .../Classes/FluidBufThreadDemo.schelp | 12 +-- .../Guides/FluidBufMultiThreading.schelp | 98 ++++++++++++++++--- 2 files changed, 91 insertions(+), 19 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp index fd9ee2f..b26c870 100644 --- a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp @@ -62,13 +62,13 @@ CODE:: // define a destination buffer b=Buffer.alloc(s,1); -// simple call, where we query the destination buffer upon completion with the action message. +// a simple call, where we query the destination buffer upon completion with the action message. FluidBufThreadDemo.process(s, b, 1000, {|x|x.get(0,{|y|y.postln});}); -// a simple call to the UGEN, where we can monitor the progress and interrup the process without killing the synth -{c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; - -// cancel the job +// as the 'process' returns its location, we can cancel the process easily +c = FluidBufThreadDemo.process(s, b, 100000, {|x|x.get(0,{|y|y.postln});}); c.cancel -c.free + +// if a simple call to the UGen is used, the progress can be monitored +{c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; :: \ No newline at end of file diff --git a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp index d17e149..503ba62 100644 --- a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp +++ b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp @@ -4,28 +4,100 @@ CATEGORIES:: Libraries>FluidDecomposition RELATED:: Guides/FluCoMa, Guides/FluidDecomposition DESCRIPTION:: -The Fluid Decomposition toolbox provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. footnote:: -This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: +The Fluid Decomposition toolbox footnote::This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. -subsection:: basic usage +These latter buffer-based processes can be very CPU intensive, and therefore require a careful consideration of the underlying architecture. Luckily, the FluidBuf* have different entry points, from transparent usage to more advanced control, to allow the creative coder to care as much as they need too. - show the process method +subsection:: Basic Usage - show the process returned variable +In SuperCollider, the server will delegate to a second, slow, non-real-time thread, tasks that are potentially too long for the real-time server, for instance, loading a soundfile to a buffer. This process is explained HERE and HERE, and for the inquisitive mind, in chapter XX of the SuperCollider book. -subsection:: kr usage +The problem with the FluidBuf* tasks is that they are very, very much longer than any of these native tasks, so we have to send them in their own thread in order to leave both real-time and non-real-time native server threads alone and responsive. - show the kr monitoring graphically +The first approach, the simplest, is therefore to call the 'process' method on the FluidBuf* objects. For this tutorial, we will use a dummy class, LINK::Classes/FluidBufThreadDemo::, which in effects does nothing but to wait on that new thread before sending back one value in a buffer. - show the interruption +CODE:: +// define a destination buffer +b=Buffer.alloc(s,1); - show the interruption again, but in a still working synth, mapping the KR out to a pitch gliss +// a simple call, where we query the destination buffer upon completion with the action message. +FluidBufThreadDemo.process(s, b, 1000, {|x|x.get(0,{|y|y.postln});}); +:: +This will print 1000 in the Post window. But actually, this is what is happening: +NUMBEREDLIST:: -subsection:: bufnmf example + ## The class will check the arguments' validity + ## It will send the job to a new thread (in this case, doing nothing but waiting for 1000 ms, then writing that number to the first index of a destination buffer) + ## It will received an acknoledgment of the job being done + ## It will call the user-defined function with the destination buffer as argument. In this case, we send it to a function get which prints the value of index 0. +:: +Actually, what is really happening is going to be discussed below, but this should be enough for most use cases. - just for shits and giggles +subsection:: Cancelling -subsection: further reading +The 'process' method returns a pointer to the task running in background, which allows to cancel the job. To allow that, one must capture the returned task ID. - a few tutorials on how fucked up it is, includign the thread sync and NRT thread in SC. \ No newline at end of file +CODE:: +//start a long process, capturing the instance of the process +c = FluidBufThreadDemo.process(s, b, 100000, {|x|x.get(0,{|y|y.postln});}); + +//cancel the job. Look at the Post Window +c.cancel; + +////////////////////////////// +////// FOR GERARD AND OWEN: we are still getting a call to the done function, which would be good to avoid +////////////////////////////// +:: + +subsection:: KR Usage + + If we look at the class definition, we will see that the 'process' method is actually calling a temporary Synth which connects to the process on the new thread. We can also call this method directly, in order to get a feedback on how the process is going. + + CODE:: +// if a simple call to the UGen is used, the progress can be monitored +{FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; + +//or polled within a synth +{FluidBufThreadDemo.kr(b,3000).poll;SinOsc.ar(110,0,0.1)}.play; + +////////////////////////////// +////// FOR GERARD AND OWEN: here the KR out is never 1 nor never stops... let's see +////////////////////////////// + +//or its value used to control other processes, here changing the pitch, whilst being polled to the window twice per second +{SinOsc.ar(Poll.kr(Impulse.kr(2),FluidBufThreadDemo.kr(b,3000)).exprange(110,220),0,0.1)}.play; +:: + +STRONG::FOR GERARD AND OWEN::: + +To cancel, we now have to do some complicated magic like explained here: + + CODE:: +a = {c = FluidBufThreadDemo.kr(b,50000,doneAction:Done.freeSelf)}.scope +c.server = Server.default; +c.synth = a; +c.cancel +:: + +it would be better to do something more transparent like managing to inherit c.synth and c.server from the call and do just: + + CODE:: +{c = FluidBufThreadDemo.kr(b,10000,doneAction:Done.freeSelf)}.scope +c.cancel +:: + +Owen said: +EMPHASIS::Synth definitely stores its server as a property, by dint of inheriting from Node. Would suggest that, barring any cleverer ideas, cancel() can take the synth as an argument; if its nil, the instance will try and fallback on its own stored synth variable and if that’s nil, an error happens. :: but what does Gerard the Wise think? + +NEXT IN LINE for PA to write: + show the interruption again, but in a still working synth, mapping the KR out to a pitch gliss for instance. + + +subsection:: A Musical Example: FluidBufNMF + + just for shits and giggles, I'll port something here. + +subsection: Further Reading + + a few tutorials on how messed up it is, includign the thread sync and NRT thread in SC. \ No newline at end of file From b4655bd4d86c9c8cc1845a8cbae2a4f670d2620a Mon Sep 17 00:00:00 2001 From: Gerard Date: Thu, 12 Sep 2019 15:27:12 +0200 Subject: [PATCH 10/42] refactor stubs for NRT objects --- release-packaging/Classes/FluidBufAmpSlice.sc | 32 ++-------- release-packaging/Classes/FluidBufCompose.sc | 36 ++---------- release-packaging/Classes/FluidBufHPSS.sc | 53 +++-------------- release-packaging/Classes/FluidBufLoudness.sc | 38 ++---------- release-packaging/Classes/FluidBufMFCC.sc | 37 ++---------- release-packaging/Classes/FluidBufMelBands.sc | 36 ++---------- release-packaging/Classes/FluidBufNMF.sc | 58 ++----------------- .../Classes/FluidBufNoveltySlice.sc | 39 ++----------- .../Classes/FluidBufOnsetSlice.sc | 39 ++----------- release-packaging/Classes/FluidBufPitch.sc | 37 ++---------- release-packaging/Classes/FluidBufSines.sc | 44 +++----------- .../Classes/FluidBufSpectralShape.sc | 37 ++---------- release-packaging/Classes/FluidBufStats.sc | 34 ++--------- .../Classes/FluidBufThreadDemo.sc | 46 +++------------ .../Classes/FluidBufTransients.sc | 47 +++------------ release-packaging/Classes/FluidNRTProcess.sc | 45 ++++++++++++++ 16 files changed, 132 insertions(+), 526 deletions(-) create mode 100644 release-packaging/Classes/FluidNRTProcess.sc diff --git a/release-packaging/Classes/FluidBufAmpSlice.sc b/release-packaging/Classes/FluidBufAmpSlice.sc index 6c8f901..d740433 100644 --- a/release-packaging/Classes/FluidBufAmpSlice.sc +++ b/release-packaging/Classes/FluidBufAmpSlice.sc @@ -1,9 +1,6 @@ FluidBufAmpSlice : UGen { - var <>server, <>synth; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0| - var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); source = source.asUGenInput; @@ -25,29 +22,10 @@ FluidBufAmpSlice : UGen { source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = {instance = FluidBufAmpSlice.kr(source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, doneAction: Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - indices = server.cachedBufferAt(indices); - indices.updateInfo; - server.sync; - action.value(indices); - }; - instance.synth = synth; - instance.server = server; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [indices] + ).process( + source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq + ); } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } - } diff --git a/release-packaging/Classes/FluidBufCompose.sc b/release-packaging/Classes/FluidBufCompose.sc index 0ae3502..5639e16 100644 --- a/release-packaging/Classes/FluidBufCompose.sc +++ b/release-packaging/Classes/FluidBufCompose.sc @@ -1,7 +1,5 @@ FluidBufCompose : UGen { - var <>server, <>synth; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0| source = source.asUGenInput; @@ -10,46 +8,24 @@ FluidBufCompose : UGen { source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction); - } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action| - var synth, instance; source = source.asUGenInput; destination = destination.asUGenInput; source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = {instance = FluidBufCompose.kr(source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction: Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - destination = server.cachedBufferAt(destination); - destination.updateInfo; - server.sync; - action.value(destination); - }; - - instance.server = server; - instance.synth = synth; - ^instance; - } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } + ^FluidNRTProcess.new( + server, this, action, [destination] + ).process( + source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain + ); + } } diff --git a/release-packaging/Classes/FluidBufHPSS.sc b/release-packaging/Classes/FluidBufHPSS.sc index c5804e6..d4ec59f 100644 --- a/release-packaging/Classes/FluidBufHPSS.sc +++ b/release-packaging/Classes/FluidBufHPSS.sc @@ -1,8 +1,6 @@ FluidBufHPSS : UGen { - var <>server, <>synth; - - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic, percussive, residual, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -10,10 +8,7 @@ FluidBufHPSS : UGen { harmonic = harmonic.asUGenInput; percussive = percussive.asUGenInput; residual = residual.asUGenInput; - - harmonic = harmonic ? -1; - percussive = percussive ? -1; - residual = residual ? -1; + source.isNil.if {"FluidBufHPSS: Invalid source buffer".throw}; //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) @@ -21,45 +16,13 @@ FluidBufHPSS : UGen { ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction); } - *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic, percussive, residual, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| - - var synth, instance; + *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| - source = source.asUGenInput; - harmonic = harmonic.asUGenInput; - percussive = percussive.asUGenInput; - residual = residual.asUGenInput; + ^FluidNRTProcess.new( + server, this, action, [harmonic, percussive, residual].select{|x| x!= -1} + ).process( + source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize + ); - source.isNil.if {"FluidBufHPSS: Invalid source buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - harmonic = harmonic ? -1; - percussive = percussive ? -1; - residual = residual ? -1; - - synth = { instance = FluidBufHPSS.kr(source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, doneAction:Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - if (harmonic != -1) {harmonic = server.cachedBufferAt(harmonic); harmonic.updateInfo; server.sync;} {harmonic = nil}; - if (percussive != -1) {percussive = server.cachedBufferAt(percussive); percussive.updateInfo; server.sync;} {percussive = nil}; - if (residual != -1) {residual = server.cachedBufferAt(residual); residual.updateInfo; server.sync;} {residual = nil}; - action.value(harmonic, percussive, residual); - }; - - instance.server = server; - instance.synth = synth; - ^instance; } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } - } diff --git a/release-packaging/Classes/FluidBufLoudness.sc b/release-packaging/Classes/FluidBufLoudness.sc index e46ee09..ff02b2f 100644 --- a/release-packaging/Classes/FluidBufLoudness.sc +++ b/release-packaging/Classes/FluidBufLoudness.sc @@ -1,7 +1,5 @@ FluidBufLoudness : UGen{ - var <>server, <>synth; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0| var maxwindowSize = windowSize.nextPowerOfTwo; @@ -16,36 +14,10 @@ FluidBufLoudness : UGen{ } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action| - - var synth, instance; - source = source.asUGenInput; - features = features.asUGenInput; - - source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; - features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = {instance = FluidBufLoudness.kr(source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, doneAction:Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - features = server.cachedBufferAt(features); features.updateInfo; server.sync; - action.value(features); - }; - - instance.server = server; - instance.synth = synth; - ^instance; - } - - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + ^FluidNRTProcess.new( + server, this, action, [features] + ).process( + source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize + ); } } diff --git a/release-packaging/Classes/FluidBufMFCC.sc b/release-packaging/Classes/FluidBufMFCC.sc index 4132af2..cc6d5c8 100644 --- a/release-packaging/Classes/FluidBufMFCC.sc +++ b/release-packaging/Classes/FluidBufMFCC.sc @@ -1,5 +1,5 @@ FluidBufMFCC : UGen{ - var <>server, <>synth; + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -17,35 +17,10 @@ FluidBufMFCC : UGen{ } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| - var synth, instance; - - source = source.asUGenInput; - features = features.asUGenInput; - - source.isNil.if {"FluidBufMFCC: Invalid source buffer".throw}; - features.isNil.if {"FluidBufMFCC: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = { instance = FluidBufMFCC.kr(source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, doneAction:Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - features = server.cachedBufferAt(features); features.updateInfo; server.sync; - action.value(features); - }; - - instance.synth = synth; - instance.server = server; - ^instance; - } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + ^FluidNRTProcess.new( + server, this, action, [features] + ).process( + source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize + ); } } diff --git a/release-packaging/Classes/FluidBufMelBands.sc b/release-packaging/Classes/FluidBufMelBands.sc index 282130c..cbe5365 100644 --- a/release-packaging/Classes/FluidBufMelBands.sc +++ b/release-packaging/Classes/FluidBufMelBands.sc @@ -1,5 +1,4 @@ FluidBufMelBands : UGen { - var <>server, <>synth; *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | @@ -19,36 +18,9 @@ FluidBufMelBands : UGen { } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| - - var synth, instance; - source = source.asUGenInput; - features = features.asUGenInput; - - source.isNil.if {"FluidBufMelBands: Invalid source buffer".throw}; - features.isNil.if {"FluidBufMelBands: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = { instance = FluidBufMelBands.kr(source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, doneAction: Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - features = server.cachedBufferAt(features); features.updateInfo; server.sync; - action.value(features); - }; - - instance.synth = synth; - instance.server = server; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [features] + ).process( + source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize); } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } - } diff --git a/release-packaging/Classes/FluidBufNMF.sc b/release-packaging/Classes/FluidBufNMF.sc index 97adaee..6b9c859 100644 --- a/release-packaging/Classes/FluidBufNMF.sc +++ b/release-packaging/Classes/FluidBufNMF.sc @@ -1,7 +1,5 @@ FluidBufNMF : UGen { - var <>server, <>synth; - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0| @@ -21,56 +19,12 @@ FluidBufNMF : UGen { } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| - - var instance,synth; - - source = source.asUGenInput; - destination = destination.asUGenInput; - bases = bases.asUGenInput; - activations = activations.asUGenInput; - - source.isNil.if {"FluidBufNMF: Invalid source buffer".throw}; - - destination = destination ? -1; - bases = bases ? -1; - activations = activations ? -1; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = {instance = FluidBufNMF.kr(source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, doneAction: Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - if (destination != -1) { - destination = server.cachedBufferAt(destination); - destination.updateInfo; - server.sync; - } {destination = nil}; - if (bases != -1) { - bases = server.cachedBufferAt(bases); - bases.updateInfo; - server.sync; - } {bases = nil}; - if (activations != -1) { - activations = server.cachedBufferAt(activations); - activations.updateInfo; - server.sync; - } {activations = nil}; - action.value(destination, bases, activations); - }; - - instance.synth = synth; - instance.server = server; - ^instance; - } + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + ^FluidNRTProcess.new( + server, this, action, [destination, bases, activations].select{|x| x!= -1} + ).process( + source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed + ); } } diff --git a/release-packaging/Classes/FluidBufNoveltySlice.sc b/release-packaging/Classes/FluidBufNoveltySlice.sc index f86d9b2..567cb54 100644 --- a/release-packaging/Classes/FluidBufNoveltySlice.sc +++ b/release-packaging/Classes/FluidBufNoveltySlice.sc @@ -1,7 +1,5 @@ FluidBufNoveltySlice : UGen { - var <>synth, <>server; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -17,38 +15,11 @@ FluidBufNoveltySlice : UGen { } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| - - var synth, instance; - var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; - - source = source.asUGenInput; - indices = indices.asUGenInput; - - source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; - indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - - synth = { instance = FluidBufNoveltySlice.kr(source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction: Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - indices = server.cachedBufferAt(indices); indices.updateInfo; server.sync; - action.value(indices); - }; - - instance.synth = synth; - instance.server = server; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [indices] + ).process( + source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize + ); } - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidBufOnsetSlice.sc b/release-packaging/Classes/FluidBufOnsetSlice.sc index 4579cb7..cf4bf6f 100644 --- a/release-packaging/Classes/FluidBufOnsetSlice.sc +++ b/release-packaging/Classes/FluidBufOnsetSlice.sc @@ -1,7 +1,5 @@ FluidBufOnsetSlice : UGen { - var <>synth, <>server; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -15,41 +13,14 @@ FluidBufOnsetSlice : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction); - } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| - var synth, instance; - source = source.asUGenInput; - indices = indices.asUGenInput; - - source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw}; - indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - //NB For wrapped versions of NRT classes, we set the params for maxima to - //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - synth = { instance = FluidBufOnsetSlice.kr(source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, doneAction: Done.freeSelf)}.play(server); - forkIfNeeded{ - synth.waitForFree; - server.sync; - indices = server.cachedBufferAt(indices); indices.updateInfo; server.sync; - action.value(indices); - }; - instance.server = server; - instance.synth = synth; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [indices] + ).process( + source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize + ); } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidBufPitch.sc b/release-packaging/Classes/FluidBufPitch.sc index fc97710..47419d8 100644 --- a/release-packaging/Classes/FluidBufPitch.sc +++ b/release-packaging/Classes/FluidBufPitch.sc @@ -1,5 +1,4 @@ FluidBufPitch : UGen{ - var <>synth, <>server; *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| @@ -18,36 +17,10 @@ FluidBufPitch : UGen{ } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| - - var synth,instance; - - source = source.asUGenInput; - features = features.asUGenInput; - - source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; - features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - - synth = { instance = FluidBufPitch.kr(source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, doneAction:Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - features = server.cachedBufferAt(features); features.updateInfo; server.sync; - action.value(features); - }; - instance.synth = synth; - instance.server = server; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [features] + ).process( + source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize + ); } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidBufSines.sc b/release-packaging/Classes/FluidBufSines.sc index 70985d2..2fd2cd3 100644 --- a/release-packaging/Classes/FluidBufSines.sc +++ b/release-packaging/Classes/FluidBufSines.sc @@ -1,8 +1,6 @@ FluidBufSines : UGen{ - var <>synth, <>server; - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines, residual, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -12,46 +10,18 @@ FluidBufSines : UGen{ source.isNil.if {"FluidBufSines: Invalid source buffer".throw}; - sines = sines ? -1; - residual = residual ? -1; - //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines, residual, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| - var synth, instance; - source = source.asUGenInput; - sines = sines.asUGenInput; - residual = residual.asUGenInput; - - source.isNil.if {"FluidBufSines: Invalid source buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - sines = sines ? -1; - residual = residual ? -1; - synth = { instance = FluidBufSines.kr(source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, doneAction:Done.freeSelf)}.play(server); - forkIfNeeded{ - synth.waitForFree; - server.sync; - if (sines != -1) {sines = server.cachedBufferAt(sines); sines.updateInfo; server.sync;} {sines = nil}; - if (residual != -1) {residual = server.cachedBufferAt(residual); residual.updateInfo; server.sync;} {residual = nil}; - action.value(sines, residual); - }; - instance.synth = synth; - instance.server = server; - ^instance; + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [sines, residual].select{|x| x!= -1} + ).process( + source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize + ); } - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidBufSpectralShape.sc b/release-packaging/Classes/FluidBufSpectralShape.sc index 342d912..b3a1129 100644 --- a/release-packaging/Classes/FluidBufSpectralShape.sc +++ b/release-packaging/Classes/FluidBufSpectralShape.sc @@ -1,7 +1,5 @@ FluidBufSpectralShape : UGen { - var <>synth, <>server; - *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -20,36 +18,11 @@ FluidBufSpectralShape : UGen { } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action| - - var synth, instance; - source = source.asUGenInput; - features = features.asUGenInput; - - source.isNil.if {"FluidBufSpectralShape: Invalid source buffer".throw}; - features.isNil.if {"FluidBufSpectralShape: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = { instance = FluidBufSpectralShape.kr(source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, doneAction:Done.freeSelf)}.play(server); - - //NB For wrapped versions of NRT classes, we set the params for maxima to - //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - forkIfNeeded{ - synth.waitForFree; - server.sync; - features = server.cachedBufferAt(features); features.updateInfo; server.sync; - action.value(features); - }; - instance.synth = synth; - instance.server = server; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [features] + ).process( + source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize + ); } - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidBufStats.sc b/release-packaging/Classes/FluidBufStats.sc index 409507b..833ddc6 100644 --- a/release-packaging/Classes/FluidBufStats.sc +++ b/release-packaging/Classes/FluidBufStats.sc @@ -1,5 +1,4 @@ FluidBufStats : UGen{ - var <>synth, <>server; *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, doneAction=0| @@ -13,34 +12,11 @@ FluidBufStats : UGen{ } *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action| - - var synth, instance; - source = source.asUGenInput; - stats = stats.asUGenInput; - - source.isNil.if {"FluidBufStats: Invalid source buffer".throw}; - stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - - synth = { instance = FluidBufStats.kr(source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high, doneAction:Done.freeSelf)}.play(server); - forkIfNeeded{ - synth.waitForFree; - server.sync; - stats = server.cachedBufferAt(stats); stats.updateInfo; server.sync; - action.value(stats); - }; - instance.synth = synth; - instance.server = server; - ^instance; + ^FluidNRTProcess.new( + server, this, action, [stats] + ).process( + source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high + ); } - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index bbf9f61..d4e2425 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,46 +1,16 @@ FluidBufThreadDemo : UGen{ - var <>synth, <>server; - - *kr {|result, time, doneAction = 0| + *kr {|result, time, doneAction = 0| result = result.asUGenInput; - - result.isNil.if {"FluidBufThreadDemo: Invalid output buffer".throw}; - - //NB For wrapped versions of NRT classes, we set the params for maxima to - //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) + result.isNil.if {this.class.name+": Invalid output buffer".throw}; ^this.multiNew(\control, result, time, doneAction); - } + } *process { |server, result, time = 1000, action| - - var synth,instance; - - result = result.asUGenInput; - - result.isNil.if {"FluidBufThreadDemo: Invalid output buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - - synth = { instance = FluidBufThreadDemo.kr(result, time, doneAction:Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - result = server.cachedBufferAt(result); result.updateInfo; server.sync; - action.value(result); - }; - instance.synth = synth; - instance.server = server; - ^instance; - } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + ^FluidNRTProcess.new( + server, this, action, [result] + ).process( + result, time + ); } } diff --git a/release-packaging/Classes/FluidBufTransients.sc b/release-packaging/Classes/FluidBufTransients.sc index 2d1c63b..eb0f832 100644 --- a/release-packaging/Classes/FluidBufTransients.sc +++ b/release-packaging/Classes/FluidBufTransients.sc @@ -1,8 +1,6 @@ FluidBufTransients : UGen { - var <>synth, <>server; - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients, residual, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0 | source = source.asUGenInput; transients = transients.asUGenInput; @@ -10,46 +8,15 @@ FluidBufTransients : UGen { source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; - transients = transients ? -1; - residual = residual ? -1; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients, residual, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| - - var synth, instance; - source = source.asUGenInput; - transients = transients.asUGenInput; - residual = residual.asUGenInput; - - source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - transients = transients ? -1; - residual = residual ? -1; - - synth = {instance = FluidBufTransients.kr(source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction:Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - if (transients != -1) {transients = server.cachedBufferAt(transients); transients.updateInfo; server.sync;} {transients = nil}; - if (residual != -1) {residual = server.cachedBufferAt(residual); residual.updateInfo; server.sync;} {residual = nil}; - action.value(transients, residual); - }; - instance.synth = synth; - instance.server = server; - ^instance; + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| + ^FluidNRTProcess.new( + server, this, action,[transients, residual].select{|x| x!= -1} + ).process( + source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength + ); } - - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; - } } diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc new file mode 100644 index 0000000..b47e0ad --- /dev/null +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -0,0 +1,45 @@ +FluidNRTProcess : Object{ + var Date: Sun, 15 Sep 2019 12:03:42 +0100 Subject: [PATCH 11/42] a missing character messed up the updated overview --- release-packaging/HelpSource/Guides/FluidDecomposition.schelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-packaging/HelpSource/Guides/FluidDecomposition.schelp b/release-packaging/HelpSource/Guides/FluidDecomposition.schelp index e3d5d2a..6760d15 100644 --- a/release-packaging/HelpSource/Guides/FluidDecomposition.schelp +++ b/release-packaging/HelpSource/Guides/FluidDecomposition.schelp @@ -85,6 +85,6 @@ LINK:: Classes/FluidBufCompose:: Copy, slice, stack, mix concatenate. All the things you've wanted to do with buffers... -LINK:: Classes/FluidBufThreadDemo: +LINK:: Classes/FluidBufThreadDemo:: A tutorial object to experiment with multithreading in FluidBuf* objects \ No newline at end of file From eab7216739d7e6f8803b327e36d4873a6207327e Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Sun, 15 Sep 2019 13:03:58 +0100 Subject: [PATCH 12/42] corrected errors in FluidBufAmpSlice helpfile and enhanced the explanations --- .../Classes/FluidBufAmpSlice.schelp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp index 35031d6..742ea7e 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp @@ -171,19 +171,22 @@ c = Buffer.new(s); FluidBufAmpSlice.process(s,b,indices:c, absRampUp:2205, absRampDown:2205, absThreshOn:-70, absThreshOff: -80, relRampUp:10, relRampDown:441, relThreshOn:14, relThreshOff:12, minSliceLength:4410) c.query c.getn(0,c.numFrames*2,{|item|item.postln;}) +//reformatting to read the onsets and offsets as pairs +c.getn(0,c.numFrames*2,{|items|items.reshape(c.numFrames,2).do({|x| x.postln});}) -//loops over a splice with the MouseX +//loops over a splice with the MouseX, taking the respective onset and offset of a given slice ( { BufRd.ar(1, b, Phasor.ar(0,1, - BufRd.kr(1, c, - MouseX.kr(0, BufFrames.kr(c) - 1), 0, 1), - BufRd.kr(1, c, - MouseX.kr(1, BufFrames.kr(c)), 0, 1), - BufRd.kr(1,c, - MouseX.kr(0, BufFrames.kr(c) - 1), 0, 1)), 0, 1); - }.play; + BufRd.kr(2, c, + MouseX.kr(0, BufFrames.kr(c)), 0, 1)[0], + BufRd.kr(2, c, + MouseX.kr(1, BufFrames.kr(c)), 0, 1)[1], + BufRd.kr(2,c, + MouseX.kr(0, BufFrames.kr(c)), 0, 1)[0] + ), 0, 1); +}.play; ) :: @@ -209,6 +212,6 @@ Routine{ }.play ) -// list the indicies of detected attacks - the two input channels have been summed -c.getn(0,c.numFrames,{|item|item.postln;}) +// list the indicies of detected attacks - the two input channels have been summed. The two channels of the output, respectively onset and offset indices, are interleaved as this is the SuperCollider buffer data formatting +c.getn(0,c.numFrames*2,{|item|item.postln;}) :: From 6e7ebed876d69680622b22c4ef4800058767b3db Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Sun, 15 Sep 2019 16:48:42 +0100 Subject: [PATCH 13/42] Examples: now has an iterative finder of a given number of slice (like the max JS version) --- .../ignore/Examples/nb_of_slices.scd | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 release-packaging/ignore/Examples/nb_of_slices.scd diff --git a/release-packaging/ignore/Examples/nb_of_slices.scd b/release-packaging/ignore/Examples/nb_of_slices.scd new file mode 100644 index 0000000..7f6bc5e --- /dev/null +++ b/release-packaging/ignore/Examples/nb_of_slices.scd @@ -0,0 +1,61 @@ +( +b = Buffer.read(s,File.realpath(FluidBufNoveltySlice.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav"); +c = Buffer.new(s); +) + +( +// with basic params +Routine{ + var startTime, goal, startThresh, prevThresh, curThresh, curVal, prevVal, iters, maxIters, dVal, dThresh; + startTime = Main.elapsedTime; + prevThresh = 0.1; //initial threshold + goal = 10; //number of slices desired + maxIters = 100; //max number of iterations acceptable + + //makes a first iteration + FluidBufNoveltySlice.process(s,b, indices: c, threshold:prevThresh,action:{|x|prevVal = x.numFrames}); + s.sync; + //makes a second iteration + if ( (prevVal < goal), { + curThresh = prevThresh * 0.5; + }, { + curThresh = prevThresh * 2; + }); + FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); + s.sync; + + //makes further iterations until the result is achieved, or the maximum of acceptable iterations is reached + iters = 2; + while ( { + (iters < maxIters) && ((curVal - goal) != 0) + }, { + iters = iters + 1; + dVal = curVal - prevVal; + dThresh = curThresh - prevThresh; + + prevThresh = curThresh; + prevVal = curVal; + + if ( (dVal == 0), { + //if we have not change results between the last 2 passes, make the variation of threshold bigger + curThresh = dThresh + curThresh; + },{ + //if we have + curThresh = ((dThresh / dVal) * (goal - curVal)) + curThresh; + }); + FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); + s.sync; + } + ); + //depending on the outcome, gives the right info back + + if ( iters >= maxIters, { + // failed + "Failed to find a suitable threshold in % seconds.\n".postf((Main.elapsedTime - startTime).round(0.01)); + }, { + // succeeded + "Found % as a suitable threshold in % seconds and % iterations.\n".postf(curThresh, (Main.elapsedTime - startTime).round(0.01), iters); + } + ); +}.play +) \ No newline at end of file From 2dc791906e4f2a7a7e76ec298908d3ce5c5f60fd Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 16 Sep 2019 16:16:36 +0100 Subject: [PATCH 14/42] clamped thresholds in nb_of_slices --- release-packaging/ignore/Examples/nb_of_slices.scd | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/release-packaging/ignore/Examples/nb_of_slices.scd b/release-packaging/ignore/Examples/nb_of_slices.scd index 7f6bc5e..be136bc 100644 --- a/release-packaging/ignore/Examples/nb_of_slices.scd +++ b/release-packaging/ignore/Examples/nb_of_slices.scd @@ -7,8 +7,8 @@ c = Buffer.new(s); // with basic params Routine{ var startTime, goal, startThresh, prevThresh, curThresh, curVal, prevVal, iters, maxIters, dVal, dThresh; - startTime = Main.elapsedTime; - prevThresh = 0.1; //initial threshold + startTime = Main.elapsedTime; + prevThresh = 0.1; //initial threshold (between 0.00001 and 0.99999 goal = 10; //number of slices desired maxIters = 100; //max number of iterations acceptable @@ -17,9 +17,9 @@ Routine{ s.sync; //makes a second iteration if ( (prevVal < goal), { - curThresh = prevThresh * 0.5; + curThresh = (prevThresh * 0.5).max(0.000001); }, { - curThresh = prevThresh * 2; + curThresh = (prevThresh * 2).min(0.999999); }); FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); s.sync; @@ -38,10 +38,10 @@ Routine{ if ( (dVal == 0), { //if we have not change results between the last 2 passes, make the variation of threshold bigger - curThresh = dThresh + curThresh; + curThresh = (dThresh + curThresh).min(0.999999).max(0.000001); },{ //if we have - curThresh = ((dThresh / dVal) * (goal - curVal)) + curThresh; + curThresh = (((dThresh / dVal) * (goal - curVal)) + curThresh).min(0.999999).max(0.000001); }); FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); s.sync; @@ -58,4 +58,4 @@ Routine{ } ); }.play -) \ No newline at end of file +) From 6d1c149b66e84ddb59033fc23ad226e083ef2788 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 16 Sep 2019 16:45:29 +0100 Subject: [PATCH 15/42] added tolerance to the number of slices --- .../ignore/Examples/nb_of_slices.scd | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/release-packaging/ignore/Examples/nb_of_slices.scd b/release-packaging/ignore/Examples/nb_of_slices.scd index be136bc..4268827 100644 --- a/release-packaging/ignore/Examples/nb_of_slices.scd +++ b/release-packaging/ignore/Examples/nb_of_slices.scd @@ -6,17 +6,18 @@ c = Buffer.new(s); ( // with basic params Routine{ - var startTime, goal, startThresh, prevThresh, curThresh, curVal, prevVal, iters, maxIters, dVal, dThresh; + var startTime, target, tolerance, startThresh, prevThresh, curThresh, curVal, prevVal, iters, maxIters, dVal, dThresh; startTime = Main.elapsedTime; prevThresh = 0.1; //initial threshold (between 0.00001 and 0.99999 - goal = 10; //number of slices desired + target = 10; //number of slices desired + tolerance = 0; // the acceptable error in the number of slices yield maxIters = 100; //max number of iterations acceptable //makes a first iteration FluidBufNoveltySlice.process(s,b, indices: c, threshold:prevThresh,action:{|x|prevVal = x.numFrames}); s.sync; //makes a second iteration - if ( (prevVal < goal), { + if ( (prevVal < target), { curThresh = (prevThresh * 0.5).max(0.000001); }, { curThresh = (prevThresh * 2).min(0.999999); @@ -27,7 +28,7 @@ Routine{ //makes further iterations until the result is achieved, or the maximum of acceptable iterations is reached iters = 2; while ( { - (iters < maxIters) && ((curVal - goal) != 0) + (iters < maxIters) && ((curVal - target).abs > tolerance) }, { iters = iters + 1; dVal = curVal - prevVal; @@ -41,7 +42,7 @@ Routine{ curThresh = (dThresh + curThresh).min(0.999999).max(0.000001); },{ //if we have - curThresh = (((dThresh / dVal) * (goal - curVal)) + curThresh).min(0.999999).max(0.000001); + curThresh = (((dThresh / dVal) * (target - curVal)) + curThresh).min(0.999999).max(0.000001); }); FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); s.sync; @@ -54,8 +55,8 @@ Routine{ "Failed to find a suitable threshold in % seconds.\n".postf((Main.elapsedTime - startTime).round(0.01)); }, { // succeeded - "Found % as a suitable threshold in % seconds and % iterations.\n".postf(curThresh, (Main.elapsedTime - startTime).round(0.01), iters); + "Found % as a suitable threshold for % slices in % seconds and % iterations.\n".postf(curThresh, curVal, (Main.elapsedTime - startTime).round(0.01), iters); } ); }.play -) +) \ No newline at end of file From 90dc29bc009bfa36c04fcdae63ffc51bc79affcf Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 17 Sep 2019 10:10:56 +0100 Subject: [PATCH 16/42] updated MT tutorials --- .../Classes/FluidBufThreadDemo.schelp | 25 +++----- .../Guides/FluidBufMultiThreading.schelp | 63 +++++++++---------- 2 files changed, 39 insertions(+), 49 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp index b26c870..131b304 100644 --- a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp @@ -4,17 +4,17 @@ CATEGORIES:: Libraries>FluidDecomposition RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: -This class implements a simple tutorial object to illustrate and experiment with the behaviour of the FluidBuf* objects. It simply starts a process that will return a single value after a delay, during which it will just wait and do nothing. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: +This class implements a simple tutorial object to illustrate and experiment with the behaviour of the FluidBuf* objects. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: It simply starts a process that will, upon completion of its task, write a single value to the destination buffer. This is the general behaviour of much of the CPU consuming FluidBuf* objects. In this case, as a toy example, the task is simply just wait and do nothing, to simulate a task that would actually take that long in the background. -The process will return its delay lenght as the first index of the specified destination buffer. +The process will, after waiting for STRONG::time:: millisecond, return its delay lenght as a Float writen at index [0] of the specified destination buffer. CLASSMETHODS:: METHOD:: process - This is the method that calls for the delay to be . + This is the method that calls for the job to be done. In this case, simply waiting STRONG::time:: millisecond before writing a value in the destination buffer. ARGUMENT:: server -(describe argument here) + The server on which the destination buffer is declared. ARGUMENT:: result The destination buffer, where the value should be written at the end of the process. @@ -26,11 +26,11 @@ ARGUMENT:: action A function that will be executed upon completion. It is passed the destination buffer as argument. RETURNS:: - Nothing, as the destination buffer is specified in the call. + The instance of FluidNRTProcess which can be used to cancel the job. METHOD:: kr - This is the UGEN that is holding the link with the background thread. It is called by the 'process' method. + This is the UGen that is holding the link with the background thread. It is called by the 'process' method and can be used directly to monitor the progress of the job. For examples of such usage, please refer to the tutorial on link::Guides/FluidBufMultiThreading::. ARGUMENT:: result The destination buffer, where the value should be written at the end of the process. @@ -45,15 +45,6 @@ RETURNS:: It report the approximate job progress, from 0 to 1. -INSTANCEMETHODS:: - -METHOD:: cancel - This allows to cancel the process on the background thread safely. - -RETURNS:: - Nothing. - - EXAMPLES:: For a thorough explanation, please refer to the tutorial on link::Guides/FluidBufMultiThreading::. @@ -65,10 +56,10 @@ b=Buffer.alloc(s,1); // a simple call, where we query the destination buffer upon completion with the action message. FluidBufThreadDemo.process(s, b, 1000, {|x|x.get(0,{|y|y.postln});}); -// as the 'process' returns its location, we can cancel the process easily +// as the 'process' returns its parent UGen, we can cancel the process easily c = FluidBufThreadDemo.process(s, b, 100000, {|x|x.get(0,{|y|y.postln});}); c.cancel // if a simple call to the UGen is used, the progress can be monitored -{c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; +{c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf); Poll.kr(Impulse.kr(2),c);}.scope; :: \ No newline at end of file diff --git a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp index 503ba62..c253ad3 100644 --- a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp +++ b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp @@ -6,13 +6,13 @@ RELATED:: Guides/FluCoMa, Guides/FluidDecomposition DESCRIPTION:: The Fluid Decomposition toolbox footnote::This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. -These latter buffer-based processes can be very CPU intensive, and therefore require a careful consideration of the underlying architecture. Luckily, the FluidBuf* have different entry points, from transparent usage to more advanced control, to allow the creative coder to care as much as they need too. +These latter buffer-based processes can be very CPU intensive, and therefore require a careful consideration of the underlying architecture. Luckily, the FluidBuf* have different entry points, from transparent usage to more advanced control, to allow the creative coder to care as much as they need too. The overarching principle is to send the CPU intensive tasks to their own background thread, to avoid blocking the Server and its Non-Real Time thread, whilst providing ways to cancel the tasks and monitor their progress. subsection:: Basic Usage -In SuperCollider, the server will delegate to a second, slow, non-real-time thread, tasks that are potentially too long for the real-time server, for instance, loading a soundfile to a buffer. This process is explained HERE and HERE, and for the inquisitive mind, in chapter XX of the SuperCollider book. +In SuperCollider, the server will delegate to a second, non-real-time thread, tasks that are potentially too long for the real-time server, for instance, loading a soundfile to a buffer. This process is explained HERE and HERE, and for the inquisitive mind, in chapter XX of the SuperCollider book. -The problem with the FluidBuf* tasks is that they are very, very much longer than any of these native tasks, so we have to send them in their own thread in order to leave both real-time and non-real-time native server threads alone and responsive. +The problem with the FluidBuf* tasks is that they are much longer than any of these native tasks, so we have to send them in their own thread in order to leave both real-time and non-real-time native server threads alone and responsive. The first approach, the simplest, is therefore to call the 'process' method on the FluidBuf* objects. For this tutorial, we will use a dummy class, LINK::Classes/FluidBufThreadDemo::, which in effects does nothing but to wait on that new thread before sending back one value in a buffer. @@ -28,7 +28,7 @@ This will print 1000 in the Post window. But actually, this is what is happening NUMBEREDLIST:: ## The class will check the arguments' validity - ## It will send the job to a new thread (in this case, doing nothing but waiting for 1000 ms, then writing that number to the first index of a destination buffer) + ## It will send the job to a new thread (in this case, doing nothing but waiting for 1000 ms, then writing that number to index [0] of a destination buffer) ## It will received an acknoledgment of the job being done ## It will call the user-defined function with the destination buffer as argument. In this case, we send it to a function get which prints the value of index 0. :: @@ -36,7 +36,7 @@ Actually, what is really happening is going to be discussed below, but this shou subsection:: Cancelling -The 'process' method returns a pointer to the task running in background, which allows to cancel the job. To allow that, one must capture the returned task ID. +The 'process' method returns an instance of FluidNRTProcess, which is a pointer to a Synth running in the background. This allows us to cancel the job. CODE:: //start a long process, capturing the instance of the process @@ -46,57 +46,56 @@ c = FluidBufThreadDemo.process(s, b, 100000, {|x|x.get(0,{|y|y.postln});}); c.cancel; ////////////////////////////// -////// FOR GERARD AND OWEN: we are still getting a call to the done function, which would be good to avoid +////// FOR GERARD AND OWEN: we are still getting a call to the done function, which would be good to avoid. We can comment on this here when it is sorted. ////////////////////////////// :: subsection:: KR Usage - If we look at the class definition, we will see that the 'process' method is actually calling a temporary Synth which connects to the process on the new thread. We can also call this method directly, in order to get a feedback on how the process is going. +If we look at the class definition, we will see that the 'process' method is actually calling a temporary Synth which spawns a thread with the job defined by the specific UGen. We can also call this specify UGen directly, in order to get a feedback on how the process is going. - CODE:: +CODE:: // if a simple call to the UGen is used, the progress can be monitored {FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; //or polled within a synth -{FluidBufThreadDemo.kr(b,3000).poll;SinOsc.ar(110,0,0.1)}.play; - -////////////////////////////// -////// FOR GERARD AND OWEN: here the KR out is never 1 nor never stops... let's see -////////////////////////////// +{FluidBufThreadDemo.kr(b,3000).poll}.play; //or its value used to control other processes, here changing the pitch, whilst being polled to the window twice per second {SinOsc.ar(Poll.kr(Impulse.kr(2),FluidBufThreadDemo.kr(b,3000)).exprange(110,220),0,0.1)}.play; :: -STRONG::FOR GERARD AND OWEN::: +To cancel the job that way, we just free the synth, and the background thread will be killed. -To cancel, we now have to do some complicated magic like explained here: +CODE:: +// load a buffer, declare a destination, and make a control bus to monitor the work +( +b = Buffer.read(s,File.realpath(FluidBufNMF.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Tremblay-AaS-SynthTwoVoices-M.wav"); +c = Buffer.new(s); +d = Bus.control(s,1); +) - CODE:: -a = {c = FluidBufThreadDemo.kr(b,50000,doneAction:Done.freeSelf)}.scope -c.server = Server.default; -c.synth = a; -c.cancel -:: +// start a very long job +e = {Out.kr(d,FluidBufNMF.kr(b, destination:c, components:50, iterations:1000, windowSize:8192, hopSize:256))}.play -it would be better to do something more transparent like managing to inherit c.synth and c.server from the call and do just: +// make a dummy synth to look at the progress +f = {In.kr(d).poll}.play - CODE:: -{c = FluidBufThreadDemo.kr(b,10000,doneAction:Done.freeSelf)}.scope -c.cancel -:: +// stop the monitoring +f.free -Owen said: -EMPHASIS::Synth definitely stores its server as a property, by dint of inheriting from Node. Would suggest that, barring any cleverer ideas, cancel() can take the synth as an argument; if its nil, the instance will try and fallback on its own stored synth variable and if that’s nil, an error happens. :: but what does Gerard the Wise think? +//make a slighly more useful use of the progress +f = {SinOsc.ar(In.kr(d).poll.exprange(110,880),0,0.1)}.play -NEXT IN LINE for PA to write: - show the interruption again, but in a still working synth, mapping the KR out to a pitch gliss for instance. +//kill the process +e.free +//kill the synth +f.free -subsection:: A Musical Example: FluidBufNMF +//to appreciate the multithreading, use your favourite CPU monitoring application. scsynth will be very, very high, despite the peakCPU and avgCPU being very low. +:: - just for shits and giggles, I'll port something here. subsection: Further Reading From 92bed6e48cced3cb3a7566be36877f6f7c1f1272 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 17 Sep 2019 10:19:38 +0100 Subject: [PATCH 17/42] nb_of_slices: removed the superfluous sync --- release-packaging/ignore/Examples/nb_of_slices.scd | 3 --- 1 file changed, 3 deletions(-) diff --git a/release-packaging/ignore/Examples/nb_of_slices.scd b/release-packaging/ignore/Examples/nb_of_slices.scd index 4268827..c30174e 100644 --- a/release-packaging/ignore/Examples/nb_of_slices.scd +++ b/release-packaging/ignore/Examples/nb_of_slices.scd @@ -15,7 +15,6 @@ Routine{ //makes a first iteration FluidBufNoveltySlice.process(s,b, indices: c, threshold:prevThresh,action:{|x|prevVal = x.numFrames}); - s.sync; //makes a second iteration if ( (prevVal < target), { curThresh = (prevThresh * 0.5).max(0.000001); @@ -23,7 +22,6 @@ Routine{ curThresh = (prevThresh * 2).min(0.999999); }); FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); - s.sync; //makes further iterations until the result is achieved, or the maximum of acceptable iterations is reached iters = 2; @@ -45,7 +43,6 @@ Routine{ curThresh = (((dThresh / dVal) * (target - curVal)) + curThresh).min(0.999999).max(0.000001); }); FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh,action:{|x|curVal = x.numFrames}); - s.sync; } ); //depending on the outcome, gives the right info back From 7b9c50ee6265bc8354bc122d614dc2703a2901fb Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 23 Sep 2019 09:06:11 +0100 Subject: [PATCH 18/42] SC Wrapper: ensure NRT UGen done isn't set unless job has completed sucessfully and without cancellation. resolves #34 --- include/FluidSCWrapper.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index 8ca7dc3..e40e5b3 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -256,8 +256,6 @@ public: if(s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) { - w->mDone = true; - if(r.status() == Result::Status::kCancelled) { std::cout << Wrapper::getName() << ": Processing cancelled \n"; @@ -269,6 +267,8 @@ public: std::cout << "ERROR: " << Wrapper::getName() << ": " << r.message().c_str() << '\n'; return false; } + + w->mDone = true; return true; } w->template set_calc_function(); From 3f89afac0b119955264515bad78867d54c1c63aa Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 23 Sep 2019 12:13:11 +0100 Subject: [PATCH 19/42] SC Wrapper NRT: Ensure UGen emits 1.0 when it is done resolves #35 --- include/FluidSCWrapper.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index e40e5b3..a92cfa9 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -216,19 +216,18 @@ public: /// The calc function. Checks to see if we've cancelled, spits out progress, launches tidy up when complete void poll(int) { - out0(0) = static_cast(mClient.progress()); + out0(0) = mDone ? 1.0 : static_cast(mClient.progress()); - if(0 == pollCounter++) + if(0 == pollCounter++ && !mCheckingForDone) { + mCheckingForDone = true; mWorld->ft->fDoAsynchronousCommand(mWorld, nullptr, Wrapper::getName(), this, postProcess, exchangeBuffers, tidyUp, destroy, 0, nullptr); - mCalcFunc = nop; } pollCounter %= checkThreadInterval; } - static void nop(Unit*, int) {} /// To be called on NRT thread. Validate parameters and commence processing in new thread static void initNRTJob(FifoMsg* f) @@ -271,7 +270,6 @@ public: w->mDone = true; return true; } - w->template set_calc_function(); return false; } @@ -288,7 +286,9 @@ public: { int doneAction = static_cast(w->in0(static_cast(w->mNumInputs - 1))); //doneAction is last input; THIS IS THE LAW world->ft->fDoneAction(doneAction,w); + return; } + w->mCheckingForDone = false; } static void doCancel(Unit *unit, sc_msg_iter*) @@ -349,6 +349,7 @@ protected: Client mClient; bool mSynchronous{true}; bool mQueueEnabled{false}; + bool mCheckingForDone{false}; //only write to this from RT thread kthx }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// From 540d65a07b9534c143b85adb8edcd68ef70a35b7 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 24 Sep 2019 11:16:18 +0100 Subject: [PATCH 20/42] Add option for NRT clients to execute directly in command FIFO. --- include/FluidSCWrapper.hpp | 13 ++++++++----- release-packaging/Classes/FluidBufAmpSlice.sc | 8 ++++---- release-packaging/Classes/FluidBufCompose.sc | 8 ++++---- release-packaging/Classes/FluidBufHPSS.sc | 8 ++++---- release-packaging/Classes/FluidBufLoudness.sc | 8 ++++---- release-packaging/Classes/FluidBufMFCC.sc | 8 ++++---- release-packaging/Classes/FluidBufMelBands.sc | 9 +++++---- release-packaging/Classes/FluidBufNMF.sc | 8 ++++---- release-packaging/Classes/FluidBufNoveltySlice.sc | 8 ++++---- release-packaging/Classes/FluidBufOnsetSlice.sc | 8 ++++---- release-packaging/Classes/FluidBufPitch.sc | 8 ++++---- release-packaging/Classes/FluidBufSines.sc | 8 ++++---- release-packaging/Classes/FluidBufSpectralShape.sc | 8 ++++---- release-packaging/Classes/FluidBufStats.sc | 4 ++-- release-packaging/Classes/FluidBufThreadDemo.sc | 8 ++++---- release-packaging/Classes/FluidBufTransientSlice.sc | 6 +++--- release-packaging/Classes/FluidBufTransients.sc | 8 ++++---- release-packaging/Classes/FluidNRTProcess.sc | 3 ++- 18 files changed, 72 insertions(+), 67 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index a92cfa9..8bd0191 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -194,11 +194,12 @@ public: }); } - /// Final input is the doneAction, not a param, so we skip it in the controlsIterator + /// Penultimate input is the doneAction, final is blocking mode. Neither are params, so we skip them in the controlsIterator NonRealTime() : - mControlsIterator{mInBuf,static_cast(static_cast(mNumInputs) - mSpecialIndex - 1)} + mControlsIterator{mInBuf,static_cast(static_cast(mNumInputs) - mSpecialIndex - 2)} , mParams{Wrapper::Client::getParameterDescriptors()} , mClient{Wrapper::setParams(mParams,mWorld->mVerbosity > 0, mWorld, mControlsIterator,true)} + , mSynchronous{mNumInputs > 2 ? (in0(static_cast(mNumInputs - 1)) > 0) : false} {} @@ -242,6 +243,7 @@ public: std::cout << "ERROR: " << Wrapper::getName() << ": " << result.message().c_str() << std::endl; return; } + w->mClient.setSynchronous(w->mSynchronous); w->mClient.enqueue(w->mParams); w->mClient.process(); } @@ -253,7 +255,8 @@ public: Result r; ProcessState s = w->mClient.checkProgress(r); - if(s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) + if((s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) + || (w->mSynchronous && s==ProcessState::kNoProcess) ) //I think this hinges on the fact that when mSynchrous = true, this call will always be behind process() on the command FIFO, so we can assume that if the state is kNoProcess, it has run (vs never having run) { if(r.status() == Result::Status::kCancelled) { @@ -282,9 +285,9 @@ public: static void destroy(World* world, void* data) { auto w = static_cast(data); - if(w->mDone && w->mNumInputs > 0) //don't check for doneAction if UGen has no ins + if(w->mDone && w->mNumInputs > 2) //don't check for doneAction if UGen has no ins (there should be 3 minimum -> sig, doneAction, blocking mode) { - int doneAction = static_cast(w->in0(static_cast(w->mNumInputs - 1))); //doneAction is last input; THIS IS THE LAW + int doneAction = static_cast(w->in0(static_cast(w->mNumInputs - 2))); //doneAction is penultimate input; THIS IS THE LAW world->ft->fDoneAction(doneAction,w); return; } diff --git a/release-packaging/Classes/FluidBufAmpSlice.sc b/release-packaging/Classes/FluidBufAmpSlice.sc index d740433..a94a56e 100644 --- a/release-packaging/Classes/FluidBufAmpSlice.sc +++ b/release-packaging/Classes/FluidBufAmpSlice.sc @@ -1,6 +1,6 @@ FluidBufAmpSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0, blocking = 0| var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); source = source.asUGenInput; @@ -9,10 +9,10 @@ FluidBufAmpSlice : UGen { source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action, blocking = 0 | var instance,synth; @@ -25,7 +25,7 @@ FluidBufAmpSlice : UGen { ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq + source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, blocking ); } } diff --git a/release-packaging/Classes/FluidBufCompose.sc b/release-packaging/Classes/FluidBufCompose.sc index 5639e16..1ed9bca 100644 --- a/release-packaging/Classes/FluidBufCompose.sc +++ b/release-packaging/Classes/FluidBufCompose.sc @@ -1,6 +1,6 @@ FluidBufCompose : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0, blocking = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -8,11 +8,11 @@ FluidBufCompose : UGen { source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action, blocking = 0 | source = source.asUGenInput; destination = destination.asUGenInput; @@ -23,7 +23,7 @@ FluidBufCompose : UGen { ^FluidNRTProcess.new( server, this, action, [destination] ).process( - source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain + source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, blocking ); } diff --git a/release-packaging/Classes/FluidBufHPSS.sc b/release-packaging/Classes/FluidBufHPSS.sc index d4ec59f..468f7c0 100644 --- a/release-packaging/Classes/FluidBufHPSS.sc +++ b/release-packaging/Classes/FluidBufHPSS.sc @@ -1,6 +1,6 @@ FluidBufHPSS : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,15 @@ FluidBufHPSS : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction, blocking); } - *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [harmonic, percussive, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufLoudness.sc b/release-packaging/Classes/FluidBufLoudness.sc index ff02b2f..295ba5a 100644 --- a/release-packaging/Classes/FluidBufLoudness.sc +++ b/release-packaging/Classes/FluidBufLoudness.sc @@ -1,6 +1,6 @@ FluidBufLoudness : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0, blocking = 0| var maxwindowSize = windowSize.nextPowerOfTwo; @@ -10,14 +10,14 @@ FluidBufLoudness : UGen{ source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize + source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufMFCC.sc b/release-packaging/Classes/FluidBufMFCC.sc index cc6d5c8..7910d4a 100644 --- a/release-packaging/Classes/FluidBufMFCC.sc +++ b/release-packaging/Classes/FluidBufMFCC.sc @@ -1,6 +1,6 @@ FluidBufMFCC : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; source = source.asUGenInput; @@ -13,14 +13,14 @@ FluidBufMFCC : UGen{ //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same goes to maxNumCoeffs, which is passed numCoeffs in this case - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufMelBands.sc b/release-packaging/Classes/FluidBufMelBands.sc index cbe5365..725740c 100644 --- a/release-packaging/Classes/FluidBufMelBands.sc +++ b/release-packaging/Classes/FluidBufMelBands.sc @@ -1,6 +1,6 @@ FluidBufMelBands : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -14,13 +14,14 @@ FluidBufMelBands : UGen { //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same for maxNumBands which is passed numBands - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize); + source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking + ); } } diff --git a/release-packaging/Classes/FluidBufNMF.sc b/release-packaging/Classes/FluidBufNMF.sc index 6b9c859..4254925 100644 --- a/release-packaging/Classes/FluidBufNMF.sc +++ b/release-packaging/Classes/FluidBufNMF.sc @@ -1,7 +1,7 @@ FluidBufNMF : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0, blocking = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -14,17 +14,17 @@ FluidBufNMF : UGen { bases = bases ? -1; activations = activations ? -1; - ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction); + ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [destination, bases, activations].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed + source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed, blocking ); } } diff --git a/release-packaging/Classes/FluidBufNoveltySlice.sc b/release-packaging/Classes/FluidBufNoveltySlice.sc index 567cb54..2f33c6a 100644 --- a/release-packaging/Classes/FluidBufNoveltySlice.sc +++ b/release-packaging/Classes/FluidBufNoveltySlice.sc @@ -1,6 +1,6 @@ FluidBufNoveltySlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -10,15 +10,15 @@ FluidBufNoveltySlice : UGen { source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufOnsetSlice.sc b/release-packaging/Classes/FluidBufOnsetSlice.sc index cf4bf6f..693005f 100644 --- a/release-packaging/Classes/FluidBufOnsetSlice.sc +++ b/release-packaging/Classes/FluidBufOnsetSlice.sc @@ -1,6 +1,6 @@ FluidBufOnsetSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,14 @@ FluidBufOnsetSlice : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufPitch.sc b/release-packaging/Classes/FluidBufPitch.sc index 47419d8..0d408f9 100644 --- a/release-packaging/Classes/FluidBufPitch.sc +++ b/release-packaging/Classes/FluidBufPitch.sc @@ -1,6 +1,6 @@ FluidBufPitch : UGen{ - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -12,15 +12,15 @@ FluidBufPitch : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufSines.sc b/release-packaging/Classes/FluidBufSines.sc index 2fd2cd3..10ba5c6 100644 --- a/release-packaging/Classes/FluidBufSines.sc +++ b/release-packaging/Classes/FluidBufSines.sc @@ -1,6 +1,6 @@ FluidBufSines : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,14 @@ FluidBufSines : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [sines, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufSpectralShape.sc b/release-packaging/Classes/FluidBufSpectralShape.sc index b3a1129..d2949d6 100644 --- a/release-packaging/Classes/FluidBufSpectralShape.sc +++ b/release-packaging/Classes/FluidBufSpectralShape.sc @@ -1,6 +1,6 @@ FluidBufSpectralShape : UGen { - *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,15 @@ FluidBufSpectralShape : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufStats.sc b/release-packaging/Classes/FluidBufStats.sc index 833ddc6..d2b0736 100644 --- a/release-packaging/Classes/FluidBufStats.sc +++ b/release-packaging/Classes/FluidBufStats.sc @@ -11,11 +11,11 @@ FluidBufStats : UGen{ ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high,doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [stats] ).process( - source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high + source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, blocking ); } diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index d4e2425..a89c211 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,16 +1,16 @@ FluidBufThreadDemo : UGen{ - *kr {|result, time, doneAction = 0| + *kr {|result, time, doneAction = 0, blocking = 0| result = result.asUGenInput; result.isNil.if {this.class.name+": Invalid output buffer".throw}; - ^this.multiNew(\control, result, time, doneAction); + ^this.multiNew(\control, result, time, doneAction, blocking); } - *process { |server, result, time = 1000, action| + *process { |server, result, time = 1000, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [result] ).process( - result, time + result, time, blocking ); } } diff --git a/release-packaging/Classes/FluidBufTransientSlice.sc b/release-packaging/Classes/FluidBufTransientSlice.sc index bdafdd5..7810b0c 100644 --- a/release-packaging/Classes/FluidBufTransientSlice.sc +++ b/release-packaging/Classes/FluidBufTransientSlice.sc @@ -1,7 +1,7 @@ FluidBufTransientSlice : UGen{ var <>synth, <>server; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0, blocking = 0| source = source.asUGenInput; indices = indices.asUGenInput; @@ -9,11 +9,11 @@ FluidBufTransientSlice : UGen{ source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action, blocking = 0 | var synth, instance; source = source.asUGenInput; diff --git a/release-packaging/Classes/FluidBufTransients.sc b/release-packaging/Classes/FluidBufTransients.sc index eb0f832..b22879b 100644 --- a/release-packaging/Classes/FluidBufTransients.sc +++ b/release-packaging/Classes/FluidBufTransients.sc @@ -1,6 +1,6 @@ FluidBufTransients : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0, blocking = 0 | source = source.asUGenInput; transients = transients.asUGenInput; @@ -8,15 +8,15 @@ FluidBufTransients : UGen { source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action,[transients, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength + source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, blocking ); } } diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index b47e0ad..e54fd3a 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -23,12 +23,13 @@ FluidNRTProcess : Object{ process{|...ugenArgs| synth = { - ugen.performList(\kr, ugenArgs.collect{|a| a.asUGenInput} ++ Done.freeSelf) + ugen.performList(\kr, ugenArgs.drop(-1).collect{|a| a.asUGenInput} ++ Done.freeSelf ++ ugenArgs.keep(-1).collect{|a| a.asUGenInput}) }.play(server); synth.postln; forkIfNeeded{ synth.waitForFree; server.sync; + "HERE".postln; outputBuffers.do{|buf| buf = server.cachedBufferAt(buf.asUGenInput); buf.updateInfo; From 278d50c608e8d1ff8f7c6ff08bc03838a81e0ef1 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 24 Sep 2019 16:45:26 +0100 Subject: [PATCH 21/42] release-packaging/Classes/FluidNRTProcess.sc: Make process() send a done message to the language iff processing is successful, hopefully resolves #34 properly this time --- release-packaging/Classes/FluidNRTProcess.sc | 29 ++++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index b47e0ad..d7292d6 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -22,20 +22,25 @@ FluidNRTProcess : Object{ } process{|...ugenArgs| - synth = { - ugen.performList(\kr, ugenArgs.collect{|a| a.asUGenInput} ++ Done.freeSelf) + var reply = '/done' ++ UniqueID.next; + synth = { + var ug = ugen.performList(\kr, ugenArgs.collect{|a| a.asUGenInput} ++ Done.freeSelf); + SendReply.kr(Done.kr(ug),reply) }.play(server); synth.postln; - forkIfNeeded{ - synth.waitForFree; - server.sync; - outputBuffers.do{|buf| - buf = server.cachedBufferAt(buf.asUGenInput); - buf.updateInfo; - server.sync; - }; - if(action.notNil){action.valueArray(outputBuffers)}; - }; + + OSCFunc({ + forkIfNeeded{ + synth.waitForFree; + server.sync; + outputBuffers.do{|buf| + buf = server.cachedBufferAt(buf.asUGenInput); + buf.updateInfo; + server.sync; + }; + if(action.notNil){action.valueArray(outputBuffers)}; + } + }, reply).oneShot; ^this; } From bfb943fb97c391b7679d1fc1aba79cbe725bc68f Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 24 Sep 2019 16:46:07 +0100 Subject: [PATCH 22/42] include/FluidSCWrapper.hpp: When cancellation happens by freeing the synth, it would still be nice to get the informational message --- include/FluidSCWrapper.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index a92cfa9..dc98f14 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -201,6 +201,13 @@ public: , mClient{Wrapper::setParams(mParams,mWorld->mVerbosity > 0, mWorld, mControlsIterator,true)} {} + ~NonRealTime() + { + if(mClient.state() == ProcessState::kProcessing) + std::cout << Wrapper::getName() << ": Processing cancelled \n"; + //processing will be cancelled in ~NRTThreadAdaptor() + } + /// No option of not using a worker thread for now /// init() sets up the NRT process via the SC NRT thread, and then sets our UGen calc function going @@ -255,6 +262,8 @@ public: if(s==ProcessState::kDone || s==ProcessState::kDoneStillProcessing) { + //Given that cancellation from the language now always happens by freeing the + //synth, this block isn't reached normally. HOwever, if someone cancels using u_cmd, this is what will fire if(r.status() == Result::Status::kCancelled) { std::cout << Wrapper::getName() << ": Processing cancelled \n"; From 89e774ab9d9637be5d2fc3a2558b30cf4c75d6cd Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 24 Sep 2019 19:34:57 +0100 Subject: [PATCH 23/42] release-packaging/Classes/FluidNRTProcess.sc: process() still needs to be blocking until synth free whenever it is in a routine. yet another attempt to resolve #34 --- release-packaging/Classes/FluidNRTProcess.sc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index d7292d6..fe82bf6 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -31,8 +31,6 @@ FluidNRTProcess : Object{ OSCFunc({ forkIfNeeded{ - synth.waitForFree; - server.sync; outputBuffers.do{|buf| buf = server.cachedBufferAt(buf.asUGenInput); buf.updateInfo; @@ -41,6 +39,12 @@ FluidNRTProcess : Object{ if(action.notNil){action.valueArray(outputBuffers)}; } }, reply).oneShot; + + forkIfNeeded{ + synth.waitForFree; + server.sync; + } + ^this; } From 782e87f82dc861efdf4b0028039bc98329329b7a Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 24 Sep 2019 20:02:07 +0100 Subject: [PATCH 24/42] Revert changes to SC classes, because we're going to do something different --- release-packaging/Classes/FluidBufAmpSlice.sc | 8 ++++---- release-packaging/Classes/FluidBufCompose.sc | 8 ++++---- release-packaging/Classes/FluidBufHPSS.sc | 8 ++++---- release-packaging/Classes/FluidBufLoudness.sc | 8 ++++---- release-packaging/Classes/FluidBufMFCC.sc | 8 ++++---- release-packaging/Classes/FluidBufMelBands.sc | 9 ++++----- release-packaging/Classes/FluidBufNMF.sc | 8 ++++---- release-packaging/Classes/FluidBufNoveltySlice.sc | 8 ++++---- release-packaging/Classes/FluidBufOnsetSlice.sc | 8 ++++---- release-packaging/Classes/FluidBufPitch.sc | 8 ++++---- release-packaging/Classes/FluidBufSines.sc | 8 ++++---- release-packaging/Classes/FluidBufSpectralShape.sc | 8 ++++---- release-packaging/Classes/FluidBufStats.sc | 4 ++-- release-packaging/Classes/FluidBufThreadDemo.sc | 8 ++++---- release-packaging/Classes/FluidBufTransientSlice.sc | 6 +++--- release-packaging/Classes/FluidBufTransients.sc | 8 ++++---- release-packaging/Classes/FluidNRTProcess.sc | 3 +-- 17 files changed, 62 insertions(+), 64 deletions(-) diff --git a/release-packaging/Classes/FluidBufAmpSlice.sc b/release-packaging/Classes/FluidBufAmpSlice.sc index a94a56e..d740433 100644 --- a/release-packaging/Classes/FluidBufAmpSlice.sc +++ b/release-packaging/Classes/FluidBufAmpSlice.sc @@ -1,6 +1,6 @@ FluidBufAmpSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0| var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); source = source.asUGenInput; @@ -9,10 +9,10 @@ FluidBufAmpSlice : UGen { source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action| var instance,synth; @@ -25,7 +25,7 @@ FluidBufAmpSlice : UGen { ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, blocking + source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq ); } } diff --git a/release-packaging/Classes/FluidBufCompose.sc b/release-packaging/Classes/FluidBufCompose.sc index 1ed9bca..5639e16 100644 --- a/release-packaging/Classes/FluidBufCompose.sc +++ b/release-packaging/Classes/FluidBufCompose.sc @@ -1,6 +1,6 @@ FluidBufCompose : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -8,11 +8,11 @@ FluidBufCompose : UGen { source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction, blocking); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action| source = source.asUGenInput; destination = destination.asUGenInput; @@ -23,7 +23,7 @@ FluidBufCompose : UGen { ^FluidNRTProcess.new( server, this, action, [destination] ).process( - source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, blocking + source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain ); } diff --git a/release-packaging/Classes/FluidBufHPSS.sc b/release-packaging/Classes/FluidBufHPSS.sc index 468f7c0..d4ec59f 100644 --- a/release-packaging/Classes/FluidBufHPSS.sc +++ b/release-packaging/Classes/FluidBufHPSS.sc @@ -1,6 +1,6 @@ FluidBufHPSS : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,15 @@ FluidBufHPSS : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction, blocking); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction); } - *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [harmonic, percussive, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufLoudness.sc b/release-packaging/Classes/FluidBufLoudness.sc index 295ba5a..ff02b2f 100644 --- a/release-packaging/Classes/FluidBufLoudness.sc +++ b/release-packaging/Classes/FluidBufLoudness.sc @@ -1,6 +1,6 @@ FluidBufLoudness : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0| var maxwindowSize = windowSize.nextPowerOfTwo; @@ -10,14 +10,14 @@ FluidBufLoudness : UGen{ source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction, blocking); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, blocking + source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize ); } } diff --git a/release-packaging/Classes/FluidBufMFCC.sc b/release-packaging/Classes/FluidBufMFCC.sc index 7910d4a..cc6d5c8 100644 --- a/release-packaging/Classes/FluidBufMFCC.sc +++ b/release-packaging/Classes/FluidBufMFCC.sc @@ -1,6 +1,6 @@ FluidBufMFCC : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; source = source.asUGenInput; @@ -13,14 +13,14 @@ FluidBufMFCC : UGen{ //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same goes to maxNumCoeffs, which is passed numCoeffs in this case - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize ); } } diff --git a/release-packaging/Classes/FluidBufMelBands.sc b/release-packaging/Classes/FluidBufMelBands.sc index 725740c..cbe5365 100644 --- a/release-packaging/Classes/FluidBufMelBands.sc +++ b/release-packaging/Classes/FluidBufMelBands.sc @@ -1,6 +1,6 @@ FluidBufMelBands : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -14,14 +14,13 @@ FluidBufMelBands : UGen { //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same for maxNumBands which is passed numBands - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking - ); + source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize); } } diff --git a/release-packaging/Classes/FluidBufNMF.sc b/release-packaging/Classes/FluidBufNMF.sc index 4254925..6b9c859 100644 --- a/release-packaging/Classes/FluidBufNMF.sc +++ b/release-packaging/Classes/FluidBufNMF.sc @@ -1,7 +1,7 @@ FluidBufNMF : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0, blocking = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -14,17 +14,17 @@ FluidBufNMF : UGen { bases = bases ? -1; activations = activations ? -1; - ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction, blocking); + ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| ^FluidNRTProcess.new( server, this, action, [destination, bases, activations].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed, blocking + source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed ); } } diff --git a/release-packaging/Classes/FluidBufNoveltySlice.sc b/release-packaging/Classes/FluidBufNoveltySlice.sc index 2f33c6a..567cb54 100644 --- a/release-packaging/Classes/FluidBufNoveltySlice.sc +++ b/release-packaging/Classes/FluidBufNoveltySlice.sc @@ -1,6 +1,6 @@ FluidBufNoveltySlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -10,15 +10,15 @@ FluidBufNoveltySlice : UGen { source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufOnsetSlice.sc b/release-packaging/Classes/FluidBufOnsetSlice.sc index 693005f..cf4bf6f 100644 --- a/release-packaging/Classes/FluidBufOnsetSlice.sc +++ b/release-packaging/Classes/FluidBufOnsetSlice.sc @@ -1,6 +1,6 @@ FluidBufOnsetSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,14 @@ FluidBufOnsetSlice : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize ); } } diff --git a/release-packaging/Classes/FluidBufPitch.sc b/release-packaging/Classes/FluidBufPitch.sc index 0d408f9..47419d8 100644 --- a/release-packaging/Classes/FluidBufPitch.sc +++ b/release-packaging/Classes/FluidBufPitch.sc @@ -1,6 +1,6 @@ FluidBufPitch : UGen{ - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -12,15 +12,15 @@ FluidBufPitch : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize ); } } diff --git a/release-packaging/Classes/FluidBufSines.sc b/release-packaging/Classes/FluidBufSines.sc index 10ba5c6..2fd2cd3 100644 --- a/release-packaging/Classes/FluidBufSines.sc +++ b/release-packaging/Classes/FluidBufSines.sc @@ -1,6 +1,6 @@ FluidBufSines : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,14 @@ FluidBufSines : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [sines, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufSpectralShape.sc b/release-packaging/Classes/FluidBufSpectralShape.sc index d2949d6..b3a1129 100644 --- a/release-packaging/Classes/FluidBufSpectralShape.sc +++ b/release-packaging/Classes/FluidBufSpectralShape.sc @@ -1,6 +1,6 @@ FluidBufSpectralShape : UGen { - *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,15 @@ FluidBufSpectralShape : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufStats.sc b/release-packaging/Classes/FluidBufStats.sc index d2b0736..833ddc6 100644 --- a/release-packaging/Classes/FluidBufStats.sc +++ b/release-packaging/Classes/FluidBufStats.sc @@ -11,11 +11,11 @@ FluidBufStats : UGen{ ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high,doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action| ^FluidNRTProcess.new( server, this, action, [stats] ).process( - source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, blocking + source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high ); } diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index a89c211..d4e2425 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,16 +1,16 @@ FluidBufThreadDemo : UGen{ - *kr {|result, time, doneAction = 0, blocking = 0| + *kr {|result, time, doneAction = 0| result = result.asUGenInput; result.isNil.if {this.class.name+": Invalid output buffer".throw}; - ^this.multiNew(\control, result, time, doneAction, blocking); + ^this.multiNew(\control, result, time, doneAction); } - *process { |server, result, time = 1000, action, blocking = 0 | + *process { |server, result, time = 1000, action| ^FluidNRTProcess.new( server, this, action, [result] ).process( - result, time, blocking + result, time ); } } diff --git a/release-packaging/Classes/FluidBufTransientSlice.sc b/release-packaging/Classes/FluidBufTransientSlice.sc index 7810b0c..bdafdd5 100644 --- a/release-packaging/Classes/FluidBufTransientSlice.sc +++ b/release-packaging/Classes/FluidBufTransientSlice.sc @@ -1,7 +1,7 @@ FluidBufTransientSlice : UGen{ var <>synth, <>server; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0, blocking = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0| source = source.asUGenInput; indices = indices.asUGenInput; @@ -9,11 +9,11 @@ FluidBufTransientSlice : UGen{ source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action| var synth, instance; source = source.asUGenInput; diff --git a/release-packaging/Classes/FluidBufTransients.sc b/release-packaging/Classes/FluidBufTransients.sc index b22879b..eb0f832 100644 --- a/release-packaging/Classes/FluidBufTransients.sc +++ b/release-packaging/Classes/FluidBufTransients.sc @@ -1,6 +1,6 @@ FluidBufTransients : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0, blocking = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0 | source = source.asUGenInput; transients = transients.asUGenInput; @@ -8,15 +8,15 @@ FluidBufTransients : UGen { source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction, blocking); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| ^FluidNRTProcess.new( server, this, action,[transients, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, blocking + source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength ); } } diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index e54fd3a..b47e0ad 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -23,13 +23,12 @@ FluidNRTProcess : Object{ process{|...ugenArgs| synth = { - ugen.performList(\kr, ugenArgs.drop(-1).collect{|a| a.asUGenInput} ++ Done.freeSelf ++ ugenArgs.keep(-1).collect{|a| a.asUGenInput}) + ugen.performList(\kr, ugenArgs.collect{|a| a.asUGenInput} ++ Done.freeSelf) }.play(server); synth.postln; forkIfNeeded{ synth.waitForFree; server.sync; - "HERE".postln; outputBuffers.do{|buf| buf = server.cachedBufferAt(buf.asUGenInput); buf.updateInfo; From 0961f0410b5ce4bc80720ab3e5bcd0692dd2a782 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 1 Oct 2019 14:54:42 +0100 Subject: [PATCH 25/42] Revert "Revert changes to SC classes, because we're going to do something different" This reverts commit 782e87f82dc861efdf4b0028039bc98329329b7a. --- release-packaging/Classes/FluidBufAmpSlice.sc | 8 ++++---- release-packaging/Classes/FluidBufCompose.sc | 8 ++++---- release-packaging/Classes/FluidBufHPSS.sc | 8 ++++---- release-packaging/Classes/FluidBufLoudness.sc | 8 ++++---- release-packaging/Classes/FluidBufMFCC.sc | 8 ++++---- release-packaging/Classes/FluidBufMelBands.sc | 9 +++++---- release-packaging/Classes/FluidBufNMF.sc | 8 ++++---- release-packaging/Classes/FluidBufNoveltySlice.sc | 8 ++++---- release-packaging/Classes/FluidBufOnsetSlice.sc | 8 ++++---- release-packaging/Classes/FluidBufPitch.sc | 8 ++++---- release-packaging/Classes/FluidBufSines.sc | 8 ++++---- release-packaging/Classes/FluidBufSpectralShape.sc | 8 ++++---- release-packaging/Classes/FluidBufStats.sc | 4 ++-- release-packaging/Classes/FluidBufThreadDemo.sc | 8 ++++---- release-packaging/Classes/FluidBufTransientSlice.sc | 6 +++--- release-packaging/Classes/FluidBufTransients.sc | 8 ++++---- release-packaging/Classes/FluidNRTProcess.sc | 3 ++- 17 files changed, 64 insertions(+), 62 deletions(-) diff --git a/release-packaging/Classes/FluidBufAmpSlice.sc b/release-packaging/Classes/FluidBufAmpSlice.sc index d740433..a94a56e 100644 --- a/release-packaging/Classes/FluidBufAmpSlice.sc +++ b/release-packaging/Classes/FluidBufAmpSlice.sc @@ -1,6 +1,6 @@ FluidBufAmpSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0, blocking = 0| var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); source = source.asUGenInput; @@ -9,10 +9,10 @@ FluidBufAmpSlice : UGen { source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action, blocking = 0 | var instance,synth; @@ -25,7 +25,7 @@ FluidBufAmpSlice : UGen { ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq + source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, blocking ); } } diff --git a/release-packaging/Classes/FluidBufCompose.sc b/release-packaging/Classes/FluidBufCompose.sc index 5639e16..1ed9bca 100644 --- a/release-packaging/Classes/FluidBufCompose.sc +++ b/release-packaging/Classes/FluidBufCompose.sc @@ -1,6 +1,6 @@ FluidBufCompose : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0, blocking = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -8,11 +8,11 @@ FluidBufCompose : UGen { source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action, blocking = 0 | source = source.asUGenInput; destination = destination.asUGenInput; @@ -23,7 +23,7 @@ FluidBufCompose : UGen { ^FluidNRTProcess.new( server, this, action, [destination] ).process( - source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain + source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, blocking ); } diff --git a/release-packaging/Classes/FluidBufHPSS.sc b/release-packaging/Classes/FluidBufHPSS.sc index d4ec59f..468f7c0 100644 --- a/release-packaging/Classes/FluidBufHPSS.sc +++ b/release-packaging/Classes/FluidBufHPSS.sc @@ -1,6 +1,6 @@ FluidBufHPSS : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,15 @@ FluidBufHPSS : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction, blocking); } - *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [harmonic, percussive, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufLoudness.sc b/release-packaging/Classes/FluidBufLoudness.sc index ff02b2f..295ba5a 100644 --- a/release-packaging/Classes/FluidBufLoudness.sc +++ b/release-packaging/Classes/FluidBufLoudness.sc @@ -1,6 +1,6 @@ FluidBufLoudness : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0, blocking = 0| var maxwindowSize = windowSize.nextPowerOfTwo; @@ -10,14 +10,14 @@ FluidBufLoudness : UGen{ source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction); + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize + source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufMFCC.sc b/release-packaging/Classes/FluidBufMFCC.sc index cc6d5c8..7910d4a 100644 --- a/release-packaging/Classes/FluidBufMFCC.sc +++ b/release-packaging/Classes/FluidBufMFCC.sc @@ -1,6 +1,6 @@ FluidBufMFCC : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; source = source.asUGenInput; @@ -13,14 +13,14 @@ FluidBufMFCC : UGen{ //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same goes to maxNumCoeffs, which is passed numCoeffs in this case - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufMelBands.sc b/release-packaging/Classes/FluidBufMelBands.sc index cbe5365..725740c 100644 --- a/release-packaging/Classes/FluidBufMelBands.sc +++ b/release-packaging/Classes/FluidBufMelBands.sc @@ -1,6 +1,6 @@ FluidBufMelBands : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -14,13 +14,14 @@ FluidBufMelBands : UGen { //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same for maxNumBands which is passed numBands - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize); + source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking + ); } } diff --git a/release-packaging/Classes/FluidBufNMF.sc b/release-packaging/Classes/FluidBufNMF.sc index 6b9c859..4254925 100644 --- a/release-packaging/Classes/FluidBufNMF.sc +++ b/release-packaging/Classes/FluidBufNMF.sc @@ -1,7 +1,7 @@ FluidBufNMF : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0, blocking = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -14,17 +14,17 @@ FluidBufNMF : UGen { bases = bases ? -1; activations = activations ? -1; - ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction); + ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [destination, bases, activations].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed + source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed, blocking ); } } diff --git a/release-packaging/Classes/FluidBufNoveltySlice.sc b/release-packaging/Classes/FluidBufNoveltySlice.sc index 567cb54..2f33c6a 100644 --- a/release-packaging/Classes/FluidBufNoveltySlice.sc +++ b/release-packaging/Classes/FluidBufNoveltySlice.sc @@ -1,6 +1,6 @@ FluidBufNoveltySlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -10,15 +10,15 @@ FluidBufNoveltySlice : UGen { source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufOnsetSlice.sc b/release-packaging/Classes/FluidBufOnsetSlice.sc index cf4bf6f..693005f 100644 --- a/release-packaging/Classes/FluidBufOnsetSlice.sc +++ b/release-packaging/Classes/FluidBufOnsetSlice.sc @@ -1,6 +1,6 @@ FluidBufOnsetSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,14 @@ FluidBufOnsetSlice : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufPitch.sc b/release-packaging/Classes/FluidBufPitch.sc index 47419d8..0d408f9 100644 --- a/release-packaging/Classes/FluidBufPitch.sc +++ b/release-packaging/Classes/FluidBufPitch.sc @@ -1,6 +1,6 @@ FluidBufPitch : UGen{ - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -12,15 +12,15 @@ FluidBufPitch : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, blocking ); } } diff --git a/release-packaging/Classes/FluidBufSines.sc b/release-packaging/Classes/FluidBufSines.sc index 2fd2cd3..10ba5c6 100644 --- a/release-packaging/Classes/FluidBufSines.sc +++ b/release-packaging/Classes/FluidBufSines.sc @@ -1,6 +1,6 @@ FluidBufSines : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,14 @@ FluidBufSines : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [sines, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufSpectralShape.sc b/release-packaging/Classes/FluidBufSpectralShape.sc index b3a1129..d2949d6 100644 --- a/release-packaging/Classes/FluidBufSpectralShape.sc +++ b/release-packaging/Classes/FluidBufSpectralShape.sc @@ -1,6 +1,6 @@ FluidBufSpectralShape : UGen { - *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,15 @@ FluidBufSpectralShape : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize + source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, blocking ); } diff --git a/release-packaging/Classes/FluidBufStats.sc b/release-packaging/Classes/FluidBufStats.sc index 833ddc6..d2b0736 100644 --- a/release-packaging/Classes/FluidBufStats.sc +++ b/release-packaging/Classes/FluidBufStats.sc @@ -11,11 +11,11 @@ FluidBufStats : UGen{ ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high,doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [stats] ).process( - source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high + source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, blocking ); } diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index d4e2425..a89c211 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,16 +1,16 @@ FluidBufThreadDemo : UGen{ - *kr {|result, time, doneAction = 0| + *kr {|result, time, doneAction = 0, blocking = 0| result = result.asUGenInput; result.isNil.if {this.class.name+": Invalid output buffer".throw}; - ^this.multiNew(\control, result, time, doneAction); + ^this.multiNew(\control, result, time, doneAction, blocking); } - *process { |server, result, time = 1000, action| + *process { |server, result, time = 1000, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action, [result] ).process( - result, time + result, time, blocking ); } } diff --git a/release-packaging/Classes/FluidBufTransientSlice.sc b/release-packaging/Classes/FluidBufTransientSlice.sc index bdafdd5..7810b0c 100644 --- a/release-packaging/Classes/FluidBufTransientSlice.sc +++ b/release-packaging/Classes/FluidBufTransientSlice.sc @@ -1,7 +1,7 @@ FluidBufTransientSlice : UGen{ var <>synth, <>server; - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0| + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0, blocking = 0| source = source.asUGenInput; indices = indices.asUGenInput; @@ -9,11 +9,11 @@ FluidBufTransientSlice : UGen{ source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action, blocking = 0 | var synth, instance; source = source.asUGenInput; diff --git a/release-packaging/Classes/FluidBufTransients.sc b/release-packaging/Classes/FluidBufTransients.sc index eb0f832..b22879b 100644 --- a/release-packaging/Classes/FluidBufTransients.sc +++ b/release-packaging/Classes/FluidBufTransients.sc @@ -1,6 +1,6 @@ FluidBufTransients : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0, blocking = 0 | source = source.asUGenInput; transients = transients.asUGenInput; @@ -8,15 +8,15 @@ FluidBufTransients : UGen { source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction); + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action, blocking = 0 | ^FluidNRTProcess.new( server, this, action,[transients, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength + source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, blocking ); } } diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index b47e0ad..e54fd3a 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -23,12 +23,13 @@ FluidNRTProcess : Object{ process{|...ugenArgs| synth = { - ugen.performList(\kr, ugenArgs.collect{|a| a.asUGenInput} ++ Done.freeSelf) + ugen.performList(\kr, ugenArgs.drop(-1).collect{|a| a.asUGenInput} ++ Done.freeSelf ++ ugenArgs.keep(-1).collect{|a| a.asUGenInput}) }.play(server); synth.postln; forkIfNeeded{ synth.waitForFree; server.sync; + "HERE".postln; outputBuffers.do{|buf| buf = server.cachedBufferAt(buf.asUGenInput); buf.updateInfo; From de459643670ade831ce3dd2ce4f8c83d5ef58701 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 1 Oct 2019 15:37:42 +0100 Subject: [PATCH 26/42] Squish spurious debug message --- release-packaging/Classes/FluidNRTProcess.sc | 1 - 1 file changed, 1 deletion(-) diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index e54fd3a..839a8a9 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -29,7 +29,6 @@ FluidNRTProcess : Object{ forkIfNeeded{ synth.waitForFree; server.sync; - "HERE".postln; outputBuffers.do{|buf| buf = server.cachedBufferAt(buf.asUGenInput); buf.updateInfo; From 708de336eb98df9272fffcd97a985f1ae9cc2031 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 9 Sep 2019 13:45:33 +0100 Subject: [PATCH 27/42] Thread demo client --- .../Classes/FluidBufThreadDemo.sc | 50 +++++++++++++++++++ src/FluidBufThreadDemo/CMakeLists.txt | 20 ++++++++ src/FluidBufThreadDemo/FluidBufThreadDemo.cpp | 13 +++++ 3 files changed, 83 insertions(+) create mode 100644 release-packaging/Classes/FluidBufThreadDemo.sc create mode 100644 src/FluidBufThreadDemo/CMakeLists.txt create mode 100644 src/FluidBufThreadDemo/FluidBufThreadDemo.cpp diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc new file mode 100644 index 0000000..ddab3c5 --- /dev/null +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -0,0 +1,50 @@ +FluidBufThreadDemo : UGen{ + var <>synth, <>server; + + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + + var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; + + source = source.asUGenInput; + features = features.asUGenInput; + + source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; + features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; + + //NB For wrapped versions of NRT classes, we set the params for maxima to + //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction); + } + + *process { |server, result, time, action| + + var synth,instance; + + result = result.asUGenInput; + + result.isNil.if {"FluidBufThreadDemo: Invalid source buffer".throw}; + + server = server ? Server.default; + server.ifNotRunning({ + "WARNING: Server not running".postln; + ^nil; + }); + + synth = { instance = FluidBufPitch.kr(result, time, doneAction:Done.freeSelf)}.play(server); + + forkIfNeeded{ + synth.waitForFree; + server.sync; + result = server.cachedBufferAt(result); result.updateInfo; server.sync; + action.value(result); + }; + instance.synth = synth; + instance.server = server; + ^instance; + } + + cancel{ + if(this.server.notNil) + {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + } +} diff --git a/src/FluidBufThreadDemo/CMakeLists.txt b/src/FluidBufThreadDemo/CMakeLists.txt new file mode 100644 index 0000000..3693881 --- /dev/null +++ b/src/FluidBufThreadDemo/CMakeLists.txt @@ -0,0 +1,20 @@ +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) diff --git a/src/FluidBufThreadDemo/FluidBufThreadDemo.cpp b/src/FluidBufThreadDemo/FluidBufThreadDemo.cpp new file mode 100644 index 0000000..ae810f3 --- /dev/null +++ b/src/FluidBufThreadDemo/FluidBufThreadDemo.cpp @@ -0,0 +1,13 @@ + +// A tool from the FluCoMa project, funded by the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899) + +#include +#include + +static InterfaceTable *ft; + +PluginLoad(OfflineFluidDecompositionUGens) { + ft = inTable; + using namespace fluid::client; + makeSCWrapper("FluidBufThreadDemo", ft); +} From e7bc8c60dc1b9f1a47d933a971c4042bce10a492 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Wed, 2 Oct 2019 10:50:53 +0100 Subject: [PATCH 28/42] SC Wrapper: Send a /done message (before the doneAction) to let clients complete more quickly --- include/FluidSCWrapper.hpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index 8bd0191..854c204 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -235,6 +235,7 @@ public: { auto w = static_cast(f->mData); w->mDone = false; + w->mCancelled = false; Result result = validateParameters(w); @@ -261,6 +262,7 @@ public: if(r.status() == Result::Status::kCancelled) { std::cout << Wrapper::getName() << ": Processing cancelled \n"; + w->mCancelled = true; return false; } @@ -310,13 +312,17 @@ private: return {}; } - bool exchangeBuffers(World *world) + bool exchangeBuffers(World *world) //RT thread { mParams.template forEachParamType(world); + //At this point, we can see if we're finished and let the language know (or it can wait for the doneAction, but that takes extra time) + //use replyID to convey status (0 = normal completion, 1 = cancelled) + if(mDone) world->ft->fSendNodeReply(&mParent->mNode,0,"/done",0,nullptr); + if(mCancelled) world->ft->fSendNodeReply(&mParent->mNode,1,"/done",0,nullptr); return true; } - bool tidyUp(World *) + bool tidyUp(World *) //NRT thread { mParams.template forEachParamType(); return true; @@ -345,14 +351,15 @@ private: char* mCompletionMessage = nullptr; void* mReplyAddr = nullptr; const char *mName = nullptr; - size_t checkThreadInterval; - size_t pollCounter{0}; + size_t checkThreadInterval; + size_t pollCounter{0}; protected: ParamSetType mParams; Client mClient; bool mSynchronous{true}; bool mQueueEnabled{false}; bool mCheckingForDone{false}; //only write to this from RT thread kthx + bool mCancelled{false}; }; //////////////////////////////////////////////////////////////////////////////////////////////////////////////// From 2bb9d31e5d2f7c68291037d82c8295cf41797eeb Mon Sep 17 00:00:00 2001 From: Owen Green Date: Wed, 2 Oct 2019 10:56:33 +0100 Subject: [PATCH 29/42] New switchable blockiig interface. Highlights * Clients overload UGen::new1 , this gives a mehod we can pass a blocking arg to without cluttering kr, and puts all arg checks in one place. * Blocking calls are done with processBlocking * FluidBufCompose always blocks * NRT process calls new1, not kr * some server.syncs removed to lessen dilly dallying * completion is triggered by /done message from server, matched against nodeID. replyID indicates status --- release-packaging/Classes/FluidBufAmpSlice.sc | 26 ++++++---- release-packaging/Classes/FluidBufCompose.sc | 18 +++---- release-packaging/Classes/FluidBufHPSS.sc | 25 ++++++++-- release-packaging/Classes/FluidBufLoudness.sc | 21 ++++++-- release-packaging/Classes/FluidBufMFCC.sc | 21 ++++++-- release-packaging/Classes/FluidBufMelBands.sc | 21 ++++++-- release-packaging/Classes/FluidBufNMF.sc | 27 ++++++++-- .../Classes/FluidBufNoveltySlice.sc | 22 +++++++-- .../Classes/FluidBufOnsetSlice.sc | 21 ++++++-- release-packaging/Classes/FluidBufPitch.sc | 21 ++++++-- release-packaging/Classes/FluidBufSines.sc | 20 ++++++-- .../Classes/FluidBufSpectralShape.sc | 22 +++++++-- release-packaging/Classes/FluidBufStats.sc | 18 +++++-- .../Classes/FluidBufThreadDemo.sc | 21 ++++++-- .../Classes/FluidBufTransientSlice.sc | 49 ++++++------------- .../Classes/FluidBufTransients.sc | 22 +++++++-- release-packaging/Classes/FluidNRTProcess.sc | 25 ++++++---- 17 files changed, 281 insertions(+), 119 deletions(-) diff --git a/release-packaging/Classes/FluidBufAmpSlice.sc b/release-packaging/Classes/FluidBufAmpSlice.sc index a94a56e..8205564 100644 --- a/release-packaging/Classes/FluidBufAmpSlice.sc +++ b/release-packaging/Classes/FluidBufAmpSlice.sc @@ -1,6 +1,6 @@ FluidBufAmpSlice : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0, blocking = 0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0, blocking| var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); source = source.asUGenInput; @@ -9,23 +9,29 @@ FluidBufAmpSlice : UGen { source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, maxSize, 0, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action, blocking = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, doneAction = 0| - var instance,synth; - - source = source.asUGenInput; - indices = indices.asUGenInput; + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, 0, doneAction,blocking:0); + } - source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; - indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action | ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq, blocking + source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, absRampUp = 10, absRampDown = 10, absThreshOn = -90, absThreshOff = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, relRampUp = 1, relRampDown = 1, relThreshOn = 144, relThreshOff = -144, highPassFreq = 85, action| + + ^FluidNRTProcess.new( + server, this, action, [indices], blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, indices, absRampUp, absRampDown, absThreshOn, absThreshOff, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, relRampUp, relRampDown, relThreshOn, relThreshOff, highPassFreq ); } } diff --git a/release-packaging/Classes/FluidBufCompose.sc b/release-packaging/Classes/FluidBufCompose.sc index 1ed9bca..2f2407b 100644 --- a/release-packaging/Classes/FluidBufCompose.sc +++ b/release-packaging/Classes/FluidBufCompose.sc @@ -1,6 +1,6 @@ FluidBufCompose : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0, blocking = 0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0, blocking| source = source.asUGenInput; destination = destination.asUGenInput; @@ -8,22 +8,20 @@ FluidBufCompose : UGen { source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction, blocking); } +/* *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, doneAction = 0| - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action, blocking = 0 | + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, doneAction, blocking:1); + }*/ - source = source.asUGenInput; - destination = destination.asUGenInput; - - source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; - destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action| ^FluidNRTProcess.new( - server, this, action, [destination] + server, this, action, [destination], blocking:1 ).process( - source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, blocking + source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain ); } diff --git a/release-packaging/Classes/FluidBufHPSS.sc b/release-packaging/Classes/FluidBufHPSS.sc index 468f7c0..a1f2aef 100644 --- a/release-packaging/Classes/FluidBufHPSS.sc +++ b/release-packaging/Classes/FluidBufHPSS.sc @@ -1,6 +1,6 @@ FluidBufHPSS : UGen { - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *new1 {|rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,32 @@ FluidBufHPSS : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, harmFilterSize, percFilterSize, doneAction, blocking); } - *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + + ^this.multiNew( + 'control', source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, doneAction, blocking:0 + ); + } + + *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [harmonic, percussive, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize + ); + + } + + *processBlocking {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + + ^FluidNRTProcess.new( + server, this, action, [harmonic, percussive, residual].select{|x| x!= -1}, blocking:1 + ).process( + source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufLoudness.sc b/release-packaging/Classes/FluidBufLoudness.sc index 295ba5a..1b0b994 100644 --- a/release-packaging/Classes/FluidBufLoudness.sc +++ b/release-packaging/Classes/FluidBufLoudness.sc @@ -1,6 +1,5 @@ FluidBufLoudness : UGen{ - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0, blocking = 0| + *new1 { |rate,source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0, blocking = 0| var maxwindowSize = windowSize.nextPowerOfTwo; @@ -10,14 +9,26 @@ FluidBufLoudness : UGen{ source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; - ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, doneAction, blocking); + } + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, doneAction = 0| + ^this.multiNew('control', source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, doneAction, blocking:0 ); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize, blocking + source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, action| + ^FluidNRTProcess.new( + server, this, action, [features], blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, features, kWeighting, truePeak, windowSize, hopSize ); } } diff --git a/release-packaging/Classes/FluidBufMFCC.sc b/release-packaging/Classes/FluidBufMFCC.sc index 7910d4a..458e327 100644 --- a/release-packaging/Classes/FluidBufMFCC.sc +++ b/release-packaging/Classes/FluidBufMFCC.sc @@ -1,6 +1,5 @@ FluidBufMFCC : UGen{ - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; source = source.asUGenInput; @@ -13,14 +12,26 @@ FluidBufMFCC : UGen{ //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same goes to maxNumCoeffs, which is passed numCoeffs in this case - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + } + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, numCoeffs, windowSize, hopSize, fftSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action | ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action | + ^FluidNRTProcess.new( + server, this, action, [features],blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, features, numCoeffs, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize ); } } diff --git a/release-packaging/Classes/FluidBufMelBands.sc b/release-packaging/Classes/FluidBufMelBands.sc index 725740c..c9fa718 100644 --- a/release-packaging/Classes/FluidBufMelBands.sc +++ b/release-packaging/Classes/FluidBufMelBands.sc @@ -1,6 +1,5 @@ FluidBufMelBands : UGen { - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -14,14 +13,26 @@ FluidBufMelBands : UGen { //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) // same for maxNumBands which is passed numBands - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + } + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, numBands, windowSize, hopSize, fftSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize ); } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [features], blocking:1 + ).process( + source, startFrame, numFrames, startChan, numChans, features, numBands, minFreq, maxFreq, windowSize, hopSize, fftSize + ); } +} \ No newline at end of file diff --git a/release-packaging/Classes/FluidBufNMF.sc b/release-packaging/Classes/FluidBufNMF.sc index 4254925..87fac60 100644 --- a/release-packaging/Classes/FluidBufNMF.sc +++ b/release-packaging/Classes/FluidBufNMF.sc @@ -1,7 +1,6 @@ FluidBufNMF : UGen { - - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0, blocking = 0| + *new1 {|rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0, blocking = 0| source = source.asUGenInput; destination = destination.asUGenInput; @@ -14,17 +13,35 @@ FluidBufNMF : UGen { bases = bases ? -1; activations = activations ? -1; - ^this.multiNew('control',source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction, blocking); + ^super.new1(rate,source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction, blocking); + + } + + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, doneAction = 0| + ^this.multiNew(\control,source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components, iterations, windowSize, hopSize, fftSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| + + source.isNil.if {"FluidBufNMF: Invalid source buffer".throw}; ^FluidNRTProcess.new( server, this, action, [destination, bases, activations].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed, blocking + source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination = -1, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, windowType = 0, randomSeed = -1, action| + + source.isNil.if {"FluidBufNMF: Invalid source buffer".throw}; + + ^FluidNRTProcess.new( + server, this, action, [destination, bases, activations].select{|x| x!= -1},blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, destination, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, windowType, randomSeed ); } } diff --git a/release-packaging/Classes/FluidBufNoveltySlice.sc b/release-packaging/Classes/FluidBufNoveltySlice.sc index 2f33c6a..a2bf80d 100644 --- a/release-packaging/Classes/FluidBufNoveltySlice.sc +++ b/release-packaging/Classes/FluidBufNoveltySlice.sc @@ -1,6 +1,5 @@ FluidBufNoveltySlice : UGen { - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -10,16 +9,29 @@ FluidBufNoveltySlice : UGen { source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, maxFFTSize, kernelSize, filterSize, doneAction, blocking); + + } + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0 | + + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action | ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize ); } + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, feature = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action | + ^FluidNRTProcess.new( + server, this, action, [indices], blocking:1 + ).process( + source, startFrame, numFrames, startChan, numChans, indices, feature, kernelSize, threshold, filterSize, windowSize, hopSize, fftSize + ); + } } diff --git a/release-packaging/Classes/FluidBufOnsetSlice.sc b/release-packaging/Classes/FluidBufOnsetSlice.sc index 693005f..218e71c 100644 --- a/release-packaging/Classes/FluidBufOnsetSlice.sc +++ b/release-packaging/Classes/FluidBufOnsetSlice.sc @@ -1,6 +1,5 @@ FluidBufOnsetSlice : UGen { - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +12,26 @@ FluidBufOnsetSlice : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + } + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [indices] ).process( - source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [indices], blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize ); } } diff --git a/release-packaging/Classes/FluidBufPitch.sc b/release-packaging/Classes/FluidBufPitch.sc index 0d408f9..71e89c7 100644 --- a/release-packaging/Classes/FluidBufPitch.sc +++ b/release-packaging/Classes/FluidBufPitch.sc @@ -1,6 +1,6 @@ FluidBufPitch : UGen{ - *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *new1 {|rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -12,15 +12,28 @@ FluidBufPitch : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, doneAction); + + } + + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [features], blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, features, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize ); } } diff --git a/release-packaging/Classes/FluidBufSines.sc b/release-packaging/Classes/FluidBufSines.sc index 10ba5c6..ad65c64 100644 --- a/release-packaging/Classes/FluidBufSines.sc +++ b/release-packaging/Classes/FluidBufSines.sc @@ -1,6 +1,6 @@ FluidBufSines : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,14 +13,26 @@ FluidBufSines : UGen{ //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, doneAction); + } + + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [sines, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, threshold = 0.7, minTrackLen = 15, magWeight = 0.1, freqWeight = 1, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [sines, residual].select{|x| x!= -1}, blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, threshold, minTrackLen, magWeight, freqWeight, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufSpectralShape.sc b/release-packaging/Classes/FluidBufSpectralShape.sc index d2949d6..bdbdb4a 100644 --- a/release-packaging/Classes/FluidBufSpectralShape.sc +++ b/release-packaging/Classes/FluidBufSpectralShape.sc @@ -1,6 +1,6 @@ FluidBufSpectralShape : UGen { - *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| + *new1{ |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0, blocking = 0| var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; @@ -13,15 +13,29 @@ FluidBufSpectralShape : UGen { //NB For wrapped versions of NRT classes, we set the params for maxima to //whatever has been passed in language-side (e.g maxFFTSize still exists as a parameter for the server plugin, but makes less sense here: it just needs to be set to a legal value) - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, maxFFTSize, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action, blocking = 0 | + + *kr{ |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, doneAction); + + } + + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action| ^FluidNRTProcess.new( server, this, action, [features] ).process( - source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize, blocking + source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, windowSize = 1024, hopSize = -1, fftSize = -1, action| + ^FluidNRTProcess.new( + server, this, action, [features], blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, features, windowSize, hopSize, fftSize ); } diff --git a/release-packaging/Classes/FluidBufStats.sc b/release-packaging/Classes/FluidBufStats.sc index d2b0736..830b6c8 100644 --- a/release-packaging/Classes/FluidBufStats.sc +++ b/release-packaging/Classes/FluidBufStats.sc @@ -1,6 +1,6 @@ FluidBufStats : UGen{ - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, doneAction=0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, doneAction=0, blocking = 0| source = source.asUGenInput; stats = stats.asUGenInput; @@ -8,14 +8,26 @@ FluidBufStats : UGen{ source.isNil.if {"FluidBufStats: Invalid source buffer".throw}; stats.isNil.if {"FluidBufStats: Invalid stats buffer".throw}; + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high,doneAction, blocking); + } + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, doneAction=0| ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, stats, numDerivs, low, middle, high,doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action| ^FluidNRTProcess.new( server, this, action, [stats] ).process( - source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high, blocking + source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, stats, numDerivs = 0, low = 0, middle = 50, high = 100, action| + ^FluidNRTProcess.new( + server, this, action, [stats], blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, stats,numDerivs, low, middle, high ); } diff --git a/release-packaging/Classes/FluidBufThreadDemo.sc b/release-packaging/Classes/FluidBufThreadDemo.sc index a89c211..44d960b 100644 --- a/release-packaging/Classes/FluidBufThreadDemo.sc +++ b/release-packaging/Classes/FluidBufThreadDemo.sc @@ -1,16 +1,29 @@ FluidBufThreadDemo : UGen{ - *kr {|result, time, doneAction = 0, blocking = 0| + *new1 {|rate, result, time, doneAction = 0, blocking = 0 | result = result.asUGenInput; result.isNil.if {this.class.name+": Invalid output buffer".throw}; - ^this.multiNew(\control, result, time, doneAction, blocking); + ^super.new1(rate, result, time, doneAction, blocking); } - *process { |server, result, time = 1000, action, blocking = 0 | + + *kr {|result, time, doneAction = 0| + ^this.new1(\control, result, time, doneAction); + } + + *process { |server, result, time = 1000, action| ^FluidNRTProcess.new( server, this, action, [result] ).process( - result, time, blocking + result, time + ); + } + + *processBlocking { |server, result, time = 1000, action| + ^FluidNRTProcess.new( + server, this, action, [result], blocking: 1 + ).process( + result, time ); } } diff --git a/release-packaging/Classes/FluidBufTransientSlice.sc b/release-packaging/Classes/FluidBufTransientSlice.sc index 7810b0c..19362ea 100644 --- a/release-packaging/Classes/FluidBufTransientSlice.sc +++ b/release-packaging/Classes/FluidBufTransientSlice.sc @@ -1,7 +1,5 @@ FluidBufTransientSlice : UGen{ - var <>synth, <>server; - - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0, blocking = 0| + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0, blocking = 0| source = source.asUGenInput; indices = indices.asUGenInput; @@ -9,39 +7,24 @@ FluidBufTransientSlice : UGen{ source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction, blocking); - + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction, blocking); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action, blocking = 0 | - - var synth, instance; - source = source.asUGenInput; - indices = indices.asUGenInput; - - source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; - indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; - - server = server ? Server.default; - server.ifNotRunning({ - "WARNING: Server not running".postln; - ^nil; - }); - synth = {instance = FluidBufTransientSlice.kr(source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction: Done.freeSelf)}.play(server); - - forkIfNeeded{ - synth.waitForFree; - server.sync; - indices = server.cachedBufferAt(indices); indices.updateInfo; server.sync; - action.value(indices); - }; - instance.synth = synth; - instance.server = server; - ^instance; + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, doneAction); } - cancel{ - if(this.server.notNil) - {this.server.sendMsg("/u_cmd", this.synth.nodeID, this.synthIndex, "cancel")}; + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action| + ^FluidNRTProcess.new( + server, this, action,[indices] + ).process(source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, action| + ^FluidNRTProcess.new( + server, this, action,[indices], blocking: 1 + ).process(source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength + ); } } diff --git a/release-packaging/Classes/FluidBufTransients.sc b/release-packaging/Classes/FluidBufTransients.sc index b22879b..00cecbb 100644 --- a/release-packaging/Classes/FluidBufTransients.sc +++ b/release-packaging/Classes/FluidBufTransients.sc @@ -1,6 +1,7 @@ FluidBufTransients : UGen { - *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0, blocking = 0 | + + *new1 { |rate, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0, blocking = 0 | source = source.asUGenInput; transients = transients.asUGenInput; @@ -8,15 +9,28 @@ FluidBufTransients : UGen { source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; - ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction, blocking); + ^super.new1(rate, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction, blocking); + } + + + *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, doneAction = 0| + ^this.multiNew(\control, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, doneAction); } - *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action, blocking = 0 | + *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| ^FluidNRTProcess.new( server, this, action,[transients, residual].select{|x| x!= -1} ).process( - source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, blocking + source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength + ); + } + + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, action| + ^FluidNRTProcess.new( + server, this, action,[transients, residual].select{|x| x!= -1}, blocking: 1 + ).process( + source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength ); } } diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index 839a8a9..da4ea14 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -1,8 +1,8 @@ FluidNRTProcess : Object{ - var Date: Wed, 2 Oct 2019 12:12:52 +0100 Subject: [PATCH 30/42] SC Wrapper: always send done for any flavour of cancellation --- include/FluidSCWrapper.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/FluidSCWrapper.hpp b/include/FluidSCWrapper.hpp index 0a88e19..13f7b65 100644 --- a/include/FluidSCWrapper.hpp +++ b/include/FluidSCWrapper.hpp @@ -205,7 +205,10 @@ public: ~NonRealTime() { if(mClient.state() == ProcessState::kProcessing) + { std::cout << Wrapper::getName() << ": Processing cancelled \n"; + Wrapper::getInterfaceTable()->fSendNodeReply(&mParent->mNode,1,"/done",0,nullptr); + } //processing will be cancelled in ~NRTThreadAdaptor() } @@ -324,7 +327,7 @@ private: bool exchangeBuffers(World *world) //RT thread { mParams.template forEachParamType(world); - //At this point, we can see if we're finished and let the language know (or it can wait for the doneAction, but that takes extra time) + //At this point, we can see if we're finished and let the language know (or it can wait for the doneAction, but that takes extra time) //use replyID to convey status (0 = normal completion, 1 = cancelled) if(mDone) world->ft->fSendNodeReply(&mParent->mNode,0,"/done",0,nullptr); if(mCancelled) world->ft->fSendNodeReply(&mParent->mNode,1,"/done",0,nullptr); From 7a48b2d4fba56b3b6af4444c8dd7bbfe36e53080 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Wed, 2 Oct 2019 12:13:17 +0100 Subject: [PATCH 31/42] release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp: Additions and edits --- .../Guides/FluidBufMultiThreading.schelp | 84 ++++++++++++++----- 1 file changed, 61 insertions(+), 23 deletions(-) diff --git a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp index c253ad3..8b02a95 100644 --- a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp +++ b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp @@ -1,20 +1,24 @@ TITLE:: FluidBuf* Multithreading Behaviour -SUMMARY:: A tutorial on the multithreading behaviour of offline processes of the FluCoMa toolbox for signal decomposition +SUMMARY:: A tutorial on the multithreading behaviour of offline processes of the Fluid Decomposition toolbox for signal decomposition CATEGORIES:: Libraries>FluidDecomposition RELATED:: Guides/FluCoMa, Guides/FluidDecomposition DESCRIPTION:: The Fluid Decomposition toolbox footnote::This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. -These latter buffer-based processes can be very CPU intensive, and therefore require a careful consideration of the underlying architecture. Luckily, the FluidBuf* have different entry points, from transparent usage to more advanced control, to allow the creative coder to care as much as they need too. The overarching principle is to send the CPU intensive tasks to their own background thread, to avoid blocking the Server and its Non-Real Time thread, whilst providing ways to cancel the tasks and monitor their progress. + These latter buffer-based processes can be very CPU intensive, and so require a some consideration of SuperCollider's underlying architecture. The FluidBuf* objects have different entry points, from transparent usage to more advanced control, to allow the creative coder to care as much as they need to. The overarching principle is to send the CPU intensive tasks to their own background thread, to avoid blocking the Server and its Non-Real Time thread, whilst providing ways to cancel the tasks and monitor their progress. -subsection:: Basic Usage + In SuperCollider, the server will delegate tasks to a non-real-time thread that are potentially too long for the real-time server. For instance, loading a soundfile to a buffer. This process is explained in LINK::Classes/Buffer:: and LINK::Guides/ClientVsServer::. For comprehensive detail see Ross Bencina's 'SuperCollider Internals' in Chapter XX of the SuperCollider book. -In SuperCollider, the server will delegate to a second, non-real-time thread, tasks that are potentially too long for the real-time server, for instance, loading a soundfile to a buffer. This process is explained HERE and HERE, and for the inquisitive mind, in chapter XX of the SuperCollider book. + section:: Basic Usage -The problem with the FluidBuf* tasks is that they are much longer than any of these native tasks, so we have to send them in their own thread in order to leave both real-time and non-real-time native server threads alone and responsive. + Some FluidBuf* tasks are much longer than these native tasks, so we run them in their own worker thread to avoid clogging the server's command queue, which would interfere with you being able to fill buffers whilst these processes are running. -The first approach, the simplest, is therefore to call the 'process' method on the FluidBuf* objects. For this tutorial, we will use a dummy class, LINK::Classes/FluidBufThreadDemo::, which in effects does nothing but to wait on that new thread before sending back one value in a buffer. + There are two basic approaches to interacting with these objects. The first is simply to use the 'process' method. This method will block if run in a LINK::Classes/Routine::, but not otherwise. The alternative interaction is to use a FluidBuf* object as a UGen, as part of a synth. This latter approach enables you to get progress feedback for long running jobs. + +For this tutorial, we will use a demonstrative class, LINK::Classes/FluidBufThreadDemo::, which does nothing but wait on its thread of execution before sending back one value – the amount of time it waited – via a Buffer. + +This code will wait for 1000ms, and then print 1000 to the console: CODE:: // define a destination buffer @@ -24,48 +28,49 @@ b=Buffer.alloc(s,1); FluidBufThreadDemo.process(s, b, 1000, {|x|x.get(0,{|y|y.postln});}); :: -This will print 1000 in the Post window. But actually, this is what is happening: +What is happening: NUMBEREDLIST:: ## The class will check the arguments' validity - ## It will send the job to a new thread (in this case, doing nothing but waiting for 1000 ms, then writing that number to index [0] of a destination buffer) - ## It will received an acknoledgment of the job being done - ## It will call the user-defined function with the destination buffer as argument. In this case, we send it to a function get which prints the value of index 0. + ## The job runs on a new thread (in this case, doing nothing but waiting for 1000 ms, then writing that number to index [0] of a destination buffer) + ## It receives an acknowledgment of the job being done + ## It calls the user-defined function with the destination buffer as its argument. In this case, we send it to a function get which prints the value of index 0. :: -Actually, what is really happening is going to be discussed below, but this should be enough for most use cases. + +There are more details, but this should be enough for common use cases. subsection:: Cancelling -The 'process' method returns an instance of FluidNRTProcess, which is a pointer to a Synth running in the background. This allows us to cancel the job. +The 'process' method returns an instance of LINK::Classes/FluidNRTProcess::, which wraps a LINK::Classes/Synth:: running on the server. This gives us a simple interface to cancel a job: CODE:: + +// define a destination buffer +b=Buffer.alloc(s,1); + //start a long process, capturing the instance of the process c = FluidBufThreadDemo.process(s, b, 100000, {|x|x.get(0,{|y|y.postln});}); //cancel the job. Look at the Post Window c.cancel; - -////////////////////////////// -////// FOR GERARD AND OWEN: we are still getting a call to the done function, which would be good to avoid. We can comment on this here when it is sorted. -////////////////////////////// :: -subsection:: KR Usage +section:: .kr Usage -If we look at the class definition, we will see that the 'process' method is actually calling a temporary Synth which spawns a thread with the job defined by the specific UGen. We can also call this specify UGen directly, in order to get a feedback on how the process is going. + The 'process' method actually wraps a temporary LINK::Classes/Synth::, which enqueues our job on the server's command FIFO, which in turn launches a worker thread to do the actual work. We can instead interact with the class as a LINK::Classes/UGen::, running in our own custom synth. This allows us to poll the object for progress reports: CODE:: // if a simple call to the UGen is used, the progress can be monitored {FluidBufThreadDemo.kr(b,10000, Done.freeSelf);}.scope; //or polled within a synth -{FluidBufThreadDemo.kr(b,3000).poll}.play; - +a = {FluidBufThreadDemo.kr(b,3000).poll}.play; +a.free //or its value used to control other processes, here changing the pitch, whilst being polled to the window twice per second {SinOsc.ar(Poll.kr(Impulse.kr(2),FluidBufThreadDemo.kr(b,3000)).exprange(110,220),0,0.1)}.play; :: -To cancel the job that way, we just free the synth, and the background thread will be killed. +To cancel the job in this setup way, we just free the synth and the background thread will be killed. CODE:: // load a buffer, declare a destination, and make a control bus to monitor the work @@ -96,7 +101,40 @@ f.free //to appreciate the multithreading, use your favourite CPU monitoring application. scsynth will be very, very high, despite the peakCPU and avgCPU being very low. :: +section:: Opting Out + + Whilst using a worker thread makes sense for long running jobs, the overhead of creating the thread may outweigh any advantages for very small tasks. This is because a certain amount of pre- and post-task work needs to be done before doing a job, particularly copying the buffers involved to temporary memory to avoid working on scsynth's memory outside of scsynth's official threads. + + For these small jobs, you can opt out of using a worker thread by calling 'processBlocking' on a Fluid Decomposition Buf* object, instead of 'process'. This will run a job directly in the server's command FIFO. If your SCIDE status bar turns yellow, then be aware that this means you are clogging the queue and should consider using a thread instead. + + It is worth mentioning that there is one exception to the behaviour of the FluidBuf* objects: LINK::Classes/FluidBufCompose:: will always run directly in the command FIFO, because the overhead of setting up a job will always be greater than the amount of work this object would have to do. + + We don't offer an interface to run tasks directly in the command FIFO via .kr, because under these circumstances you would get no progress updates whilst the task runs, obviating the usefulness of using a custom synth in the first place. Similarly, jobs run with processBlocking can not be cancelled. + +You can compare these behaviours here. The blocking will run slightly faster than the default non-blocking, + + CODE:: +//Default mode – worker thread: +( +Routine{ + var startTime = Main.elapsedTime; + 100.do{|x,i| + FluidBufThreadDemo.process(s,b,10); + }; + "Threaded Processes 100 iterations in % seconds.\n".postf((Main.elapsedTime - startTime).round(0.01)); +}.play; +) + +//Danger zone – running directly in command FIFO: +( +Routine{ + var startTime = Main.elapsedTime; + 100.do{|x,i| + FluidBufThreadDemo.processBlocking(s,b,10); + }; + "Blocking Processes 100 iterations in % seconds.\n".postf((Main.elapsedTime - startTime).round(0.01)); +}.play; +) +:: -subsection: Further Reading - a few tutorials on how messed up it is, includign the thread sync and NRT thread in SC. \ No newline at end of file From abc9dadbcefcbda263625ca65a9db3d9b1d863d3 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Wed, 2 Oct 2019 13:29:19 +0100 Subject: [PATCH 32/42] release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp; Add documentation of job completion mechanisms. --- .../Guides/FluidBufMultiThreading.schelp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp index 8b02a95..c4000b0 100644 --- a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp +++ b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp @@ -101,6 +101,23 @@ f.free //to appreciate the multithreading, use your favourite CPU monitoring application. scsynth will be very, very high, despite the peakCPU and avgCPU being very low. :: +subsection:: Ding, Fries are Done + + There are a couple of options for dealing with the end of a job. First, the FluidBuf* objects support done actions, so you can use things like LINK::Classes/FreeSelfWhenDone:: or LINK::Classes/Done::, or set a doneAction in the call to .kr (see LINK::Classes/Done:: for details). Note that the UGen's done status only becomes true in the event of successful completion, so it will not catch cancellation. However, the doneAction will run whatever, so you can rely on the synth freeing itself. + + Alternatively, the synth will send a /done reply to the node, which also carries information about whether it completed normally or was cancelled. You can use LINK::Classes/OSCFunc:: to listen for this message, targetted to your nodeID. + +CODE:: +a = {FluidBufThreadDemo.kr(b,1000,doneAction: 2).poll}.play; + +OSCFunc({|msg| //args are message symbol (/done), nodeID and replyID (which gives status) + if(msg[2]==0){"Completed Normally".postln}{"Cancelled".postln}; + },"/done",argTemplate:[a.nodeID]).oneShot; //only listen to things sent for this node + +a.free; //optionally cancel +:: + + section:: Opting Out Whilst using a worker thread makes sense for long running jobs, the overhead of creating the thread may outweigh any advantages for very small tasks. This is because a certain amount of pre- and post-task work needs to be done before doing a job, particularly copying the buffers involved to temporary memory to avoid working on scsynth's memory outside of scsynth's official threads. From 52ddb8b21dec2e84ed9a59eddc6005f0a81978f7 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Wed, 2 Oct 2019 16:10:13 +0100 Subject: [PATCH 33/42] release-packaging/Classes/FluidNRTProcess.sc: Reintroduce a sync at the cost of performance, but the benefit of being sure that buffers have updated before action is called --- release-packaging/Classes/FluidNRTProcess.sc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/release-packaging/Classes/FluidNRTProcess.sc b/release-packaging/Classes/FluidNRTProcess.sc index da4ea14..35e8ce4 100644 --- a/release-packaging/Classes/FluidNRTProcess.sc +++ b/release-packaging/Classes/FluidNRTProcess.sc @@ -21,6 +21,7 @@ FluidNRTProcess : Object{ ^this; } + process{|...ugenArgs| var c = Condition.new(false); @@ -31,13 +32,16 @@ FluidNRTProcess : Object{ synth.postln; OSCFunc({ |m| + forkIfNeeded{ outputBuffers.do{|buf| buf = server.cachedBufferAt(buf.asUGenInput); buf.updateInfo; }; + server.sync; if(action.notNil && m[2]==0){action.valueArray(outputBuffers)}; c.test = true; c.signal; + } },'/done',argTemplate:[synth.nodeID]).oneShot; forkIfNeeded{ From d589b1ba3f13d46b331e17ccfbb2e782de5b1568 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Wed, 2 Oct 2019 16:14:01 +0100 Subject: [PATCH 34/42] release-packaging/Classes/FluidBufCompose.sc: Add processBlocking as alias to process() --- release-packaging/Classes/FluidBufCompose.sc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/release-packaging/Classes/FluidBufCompose.sc b/release-packaging/Classes/FluidBufCompose.sc index 2f2407b..51d1f80 100644 --- a/release-packaging/Classes/FluidBufCompose.sc +++ b/release-packaging/Classes/FluidBufCompose.sc @@ -26,4 +26,9 @@ FluidBufCompose : UGen { } + *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, action| + ^process( + source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain + ); + } } From ab924f8655d21b07b6a6e7abf25f401803714025 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Wed, 2 Oct 2019 13:23:40 -0400 Subject: [PATCH 35/42] fileiterator: syncing only at the end. --- .../ignore/Examples/buffer_compositing/fileiterator-2passes.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-packaging/ignore/Examples/buffer_compositing/fileiterator-2passes.sc b/release-packaging/ignore/Examples/buffer_compositing/fileiterator-2passes.sc index 4eaa92c..e1d05ef 100644 --- a/release-packaging/ignore/Examples/buffer_compositing/fileiterator-2passes.sc +++ b/release-packaging/ignore/Examples/buffer_compositing/fileiterator-2passes.sc @@ -28,8 +28,8 @@ FileDialog.new({|selection| f.postln; ("Loading"+(i+1)+"of"+total).postln; Buffer.read(s, f.asAbsolutePath,action:{arg tempbuf; FluidBufCompose.process(s,tempbuf,destination:b,destStartFrame:c[i],action:{tempbuf.free});}); - s.sync; }; + s.sync; ("loading buffers done in" + (Main.elapsedTime - t).round(0.1) + "seconds.").postln; }.play; }, fileMode:2); From 380afc69704fa2152ca38be2ccdfff76ab9aa4d8 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Thu, 3 Oct 2019 12:28:08 +0100 Subject: [PATCH 36/42] fluid buf multithread guide typo corrections --- .../Guides/FluidBufMultiThreading.schelp | 15 +++++++++++---- .../HelpSource/Guides/FluidDecomposition.schelp | 4 ++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp index c4000b0..43c0c73 100644 --- a/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp +++ b/release-packaging/HelpSource/Guides/FluidBufMultiThreading.schelp @@ -4,7 +4,7 @@ CATEGORIES:: Libraries>FluidDecomposition RELATED:: Guides/FluCoMa, Guides/FluidDecomposition DESCRIPTION:: -The Fluid Decomposition toolbox footnote::This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. +The Fluid Decomposition toolbox footnote::This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superpositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. These latter buffer-based processes can be very CPU intensive, and so require a some consideration of SuperCollider's underlying architecture. The FluidBuf* objects have different entry points, from transparent usage to more advanced control, to allow the creative coder to care as much as they need to. The overarching principle is to send the CPU intensive tasks to their own background thread, to avoid blocking the Server and its Non-Real Time thread, whilst providing ways to cancel the tasks and monitor their progress. @@ -101,20 +101,27 @@ f.free //to appreciate the multithreading, use your favourite CPU monitoring application. scsynth will be very, very high, despite the peakCPU and avgCPU being very low. :: -subsection:: Ding, Fries are Done +subsection:: Monitoring Task Completion There are a couple of options for dealing with the end of a job. First, the FluidBuf* objects support done actions, so you can use things like LINK::Classes/FreeSelfWhenDone:: or LINK::Classes/Done::, or set a doneAction in the call to .kr (see LINK::Classes/Done:: for details). Note that the UGen's done status only becomes true in the event of successful completion, so it will not catch cancellation. However, the doneAction will run whatever, so you can rely on the synth freeing itself. Alternatively, the synth will send a /done reply to the node, which also carries information about whether it completed normally or was cancelled. You can use LINK::Classes/OSCFunc:: to listen for this message, targetted to your nodeID. CODE:: -a = {FluidBufThreadDemo.kr(b,1000,doneAction: 2).poll}.play; +// define a destination buffer +b=Buffer.alloc(s,1); + +//start a long job +a = {FluidBufThreadDemo.kr(b,10000,doneAction: 2).poll}.play; +// set a OSC receiver function +( OSCFunc({|msg| //args are message symbol (/done), nodeID and replyID (which gives status) if(msg[2]==0){"Completed Normally".postln}{"Cancelled".postln}; },"/done",argTemplate:[a.nodeID]).oneShot; //only listen to things sent for this node +) -a.free; //optionally cancel +a.free; //optionally cancel - run the job twice to see both behaviour monitored by the OSCFunc above :: diff --git a/release-packaging/HelpSource/Guides/FluidDecomposition.schelp b/release-packaging/HelpSource/Guides/FluidDecomposition.schelp index 6760d15..fa4d288 100644 --- a/release-packaging/HelpSource/Guides/FluidDecomposition.schelp +++ b/release-packaging/HelpSource/Guides/FluidDecomposition.schelp @@ -3,7 +3,7 @@ SUMMARY:: An overview of the FluCoMa toolbox for signal decomposition CATEGORIES:: Libraries>FluidDecomposition DESCRIPTION:: -The Fluid Decomposition toolbox provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. footnote:: +The Fluid Decomposition toolbox provides an open-ended, loosely coupled set of objects to break up and analyse sound in terms of slices (segments in time), layers (superpositions in time and frequency) and objects (configurable or discoverable patterns in sound). Almost all objects have audio-rate and buffer-based versions. footnote:: This toolbox was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: subsection:: Slices @@ -87,4 +87,4 @@ Copy, slice, stack, mix concatenate. All the things you've wanted to do with buf LINK:: Classes/FluidBufThreadDemo:: -A tutorial object to experiment with multithreading in FluidBuf* objects \ No newline at end of file +A tutorial object to experiment with multithreading in FluidBuf* objects From 9de38537422d7ed9214d8bd9a836ed3a15e08548 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 7 Oct 2019 22:14:45 +0200 Subject: [PATCH 37/42] added wording for multithreading reference, sorts issue #37 --- .../HelpSource/Classes/FluidBufAmpSlice.schelp | 4 ++++ release-packaging/HelpSource/Classes/FluidBufCompose.schelp | 2 -- release-packaging/HelpSource/Classes/FluidBufHPSS.schelp | 3 +++ .../HelpSource/Classes/FluidBufLoudness.schelp | 4 ++++ release-packaging/HelpSource/Classes/FluidBufMFCC.schelp | 6 +++++- .../HelpSource/Classes/FluidBufMelBands.schelp | 6 +++++- release-packaging/HelpSource/Classes/FluidBufNMF.schelp | 5 ++++- .../HelpSource/Classes/FluidBufNoveltySlice.schelp | 6 ++++-- .../HelpSource/Classes/FluidBufOnsetSlice.schelp | 4 ++++ release-packaging/HelpSource/Classes/FluidBufPitch.schelp | 4 ++++ release-packaging/HelpSource/Classes/FluidBufSines.schelp | 4 ++++ .../HelpSource/Classes/FluidBufSpectralShape.schelp | 6 +++++- release-packaging/HelpSource/Classes/FluidBufStats.schelp | 4 ++++ .../HelpSource/Classes/FluidBufTransientSlice.schelp | 4 +++- .../HelpSource/Classes/FluidBufTransients.schelp | 4 +++- 15 files changed, 56 insertions(+), 10 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp index 742ea7e..63eeaee 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp @@ -10,6 +10,10 @@ FluidAmpSlice is based on two envelop followers on a highpassed version of the s The process will return a two-channel buffer with the addresses of the onset on the first channel, and the address of the offset on the second channel. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufCompose.schelp b/release-packaging/HelpSource/Classes/FluidBufCompose.schelp index e7425a7..991c41b 100644 --- a/release-packaging/HelpSource/Classes/FluidBufCompose.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufCompose.schelp @@ -3,7 +3,6 @@ SUMMARY:: Buffer Compositing Utility CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/Buffer - DESCRIPTION:: A FluidBufCompose object provides a flexible utility for combining the contents of buffers on the server. It can be used for thing like mixing down multichannel buffers, or converting from left-right stereo to mid-side. It is used extensively in all the example code of LINK::Guides/FluidDecomposition:: as part of the FluCoMa project. footnote:: This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: @@ -12,7 +11,6 @@ At its most simple, the object copies the content of a source buffer into a dest The algorithm takes a srcBuf, and writes the information at the provided dstBuf. These buffer arguments can all point to the same buffer, which gives great flexibility in transforming and reshaping. - CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp b/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp index 5532826..240ee2b 100644 --- a/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp @@ -22,6 +22,9 @@ This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ More information on median filtering, and on HPSS for musicianly usage, are availabe in LINK::Guides/FluCoMa:: overview file. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. CLASSMETHODS:: diff --git a/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp b/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp index 7cd256e..1ec1bc1 100644 --- a/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp @@ -9,6 +9,10 @@ This class implements two loudness descriptors, computing the true peak of the s The process will return a multichannel buffer with two channels per input channel, one for loudness and one for the true peak value of the frame, both in dBfs. More information on broadcasting standardisation of loudness measurement is available at the reference page FOOTNOTE::https://tech.ebu.ch/docs/tech/tech3341.pdf:: and in more musician-friendly explantions here FOOTNOTE::http://designingsound.org/2013/02/06/loudness-and-metering-part-1/::. Each sample represents a value, which is every hopSize. Its sampling rate is STRONG::sourceSR / hopSize::. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp b/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp index 3228b5b..57ca552 100644 --- a/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp @@ -8,6 +8,10 @@ This class implements a classic spectral descriptor, the Mel-Frequency Cepstral The process will return a single multichannel buffer of STRONG::numCoeffs:: per input channel. Each frame represents a value, which is every hopSize. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process @@ -111,4 +115,4 @@ Routine{ // look at the buffer: 5 coefs for left, then 5 coefs for right (the first of each is linked to the loudness) c.plot(separately:true) -:: \ No newline at end of file +:: diff --git a/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp b/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp index 5643f92..1f911ce 100644 --- a/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp @@ -9,6 +9,10 @@ This class implements a spectral shape descriptor where the amplitude is given f The process will return a single multichannel buffer of STRONG::numBands:: per input channel. Each frame represents a value, which is every hopSize. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process @@ -109,4 +113,4 @@ Routine{ // look at the buffer: 10 bands for left, then 10 bands for right c.plot(separately:true) -:: \ No newline at end of file +:: diff --git a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp index d4bc2e6..e3e7559 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp @@ -3,7 +3,6 @@ SUMMARY:: Buffer-Based Non-Negative Matrix Factorisation on Spectral Frames CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/FluidNMFMatch, Classes/FluidNMFFilter - DESCRIPTION:: The FluidBufNMF object decomposes the spectrum of a sound into a number of components using Non-Negative Matrix Factorisation (NMF) footnote:: Lee, Daniel D., and H. Sebastian Seung. 1999. ‘Learning the Parts of Objects by Non-Negative Matrix Factorization’. Nature 401 (6755): 788–91. https://doi.org/10.1038/44565. ::. NMF has been a popular technique in signal processing research for things like source separation and transcription footnote:: Smaragdis and Brown, Non-Negative Matrix Factorization for Polyphonic Music Transcription.::, although its creative potential is so far relatively unexplored. @@ -33,6 +32,10 @@ More information on possible musicianly uses of NMF are availabe in LINK::Guides FluidBufNMF is part of the Fluid Decomposition Toolkit of the FluCoMa project. footnote:: This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899). :: +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp b/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp index 55470b2..b043eb9 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp @@ -3,12 +3,14 @@ SUMMARY:: Buffer-Based Novelty-Based Slicer CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer RELATED:: Guides/FluCoMa, Guides/FluidDecomposition - DESCRIPTION:: This class implements a non-real-time slicer using an algorithm assessing novelty in the signal to estimate the slicing points. A novelty curve is being derived from running a kernel across the diagonal of the similarity matrix, and looking for peak of changes. It implements the seminal results published in 'Automatic Audio Segmentation Using a Measure of Audio Novelty' by J Foote. It is part of the Fluid Decomposition Toolkit of the FluCoMa project. footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: - The process will return a buffer which contains indices (in sample) of estimated starting points of different slices. +The process will return a buffer which contains indices (in sample) of estimated starting points of different slices. + +STRONG::Threading:: +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. CLASSMETHODS:: diff --git a/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp index 4893b02..2be572f 100644 --- a/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp @@ -8,6 +8,10 @@ This class implements many spectral-based onset detection metrics, most of them The process will return a buffer which contains indices (in sample) of estimated starting points of different slices. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufPitch.schelp b/release-packaging/HelpSource/Classes/FluidBufPitch.schelp index bf630c2..cc161ea 100644 --- a/release-packaging/HelpSource/Classes/FluidBufPitch.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufPitch.schelp @@ -9,6 +9,10 @@ This class implements three popular pitch descriptors, computed as frequency and The process will return a multichannel buffer with two channels per input channel, one for pitch and one for the pitch tracking confidence. Each sample represents a value, which is every hopSize. Its sampling rate is sourceSR / hopSize. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufSines.schelp b/release-packaging/HelpSource/Classes/FluidBufSines.schelp index e0e767c..e30f86c 100644 --- a/release-packaging/HelpSource/Classes/FluidBufSines.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufSines.schelp @@ -13,6 +13,10 @@ This class triggers a Sinusoidal Modelling process on buffers on the non-real-ti The whole process is based on the assumption that signal is made of pitched steady components that have a long-enough duration and are periodic enough to be perceived as such, that can be tracked, resynthesised and removed from the original, leaving behind what is considered as non-pitched, noisy, and/or transient. It first tracks the peaks, then checks if they are the continuation of a peak in previous spectral frames, by assigning them a track. More information on this model, and on how it links to musicianly thinking, are availabe in LINK::Guides/FluCoMa:: overview file. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp b/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp index 756561b..b4e56c4 100644 --- a/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp @@ -25,6 +25,10 @@ LIST:: The process will return a multichannel buffer with the seven channels per input channel, each containing the 7 shapes. Each sample represents a value, which is every hopSize. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process @@ -116,4 +120,4 @@ Routine{ // look at the buffer: 7shapes for left, then 7 shapes for right c.plot(separately:true) -:: \ No newline at end of file +:: diff --git a/release-packaging/HelpSource/Classes/FluidBufStats.schelp b/release-packaging/HelpSource/Classes/FluidBufStats.schelp index 207be64..fbe1df5 100644 --- a/release-packaging/HelpSource/Classes/FluidBufStats.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufStats.schelp @@ -9,6 +9,10 @@ This class implements non-real-time statistical analysis on buffer channels. Typ The process returns a buffer where each channel of the STRONG::source:: buffer has been reduced to 7 statistics: mean, standard deviation, skewness, kurtosis, followed by 3 percentiles, by default the minimum value, the median, and the maximum value. Moreover, it is possible to request the same 7 stats to be applied to derivative of the input. These are useful to describe statistically the rate of change of the time series. The STRONG::stats:: buffer will grow accordingly, yielding the seven same statistical description of the n requested derivatives. Therefore, the STRONG::stats:: buffer will have as many channel as the input buffer, and as many frames as 7 times the requested STRONG::numDerivs::. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. + CLASSMETHODS:: METHOD:: process diff --git a/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp index e2f3bd6..41445ba 100644 --- a/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp @@ -3,12 +3,14 @@ SUMMARY:: Buffer-Based Transient-Based Slicer CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/FluidBufTransients - DESCRIPTION:: This class implements a non-real-time transient-based slice extractor relying on the same algorithm than Classes/FluidBufTransients using clicks/transients/derivation/anomaly in the signal to estimate the slicing points. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: The process will return a buffer which contains indices (in sample) of estimated starting points of the different slices. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. CLASSMETHODS:: diff --git a/release-packaging/HelpSource/Classes/FluidBufTransients.schelp b/release-packaging/HelpSource/Classes/FluidBufTransients.schelp index 7773e4c..44fe6b6 100644 --- a/release-packaging/HelpSource/Classes/FluidBufTransients.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufTransients.schelp @@ -3,7 +3,6 @@ SUMMARY:: Buffer-Based Transient Extractor CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer RELATED:: Guides/FluCoMa, Guides/FluidDecomposition - DESCRIPTION:: This class triggers a transient extractor on buffers on the non-real-time thread of the server. It implements declicking algorithm from chapter 5 of the classic Digital Audio Restoration by Godsill, Simon J., Rayner, Peter J.W. with some bespoke improvements on the detection function tracking. It is part of the Fluid Decomposition Toolkit of the FluCoMa project. footnote:: This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: @@ -14,6 +13,9 @@ This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ The whole process is based on the assumption that a transient is an element that is deviating from the surrounding material, as sort of click or anomaly. The algorithm then estimates what should have happened if the signal had followed its normal path, and resynthesises this estimate, removing the anomaly which is considered as the transient. More information on signal estimation, and on its musicianly usage, are availabe in LINK::Guides/FluCoMa:: overview file. +STRONG::Threading:: + +By default, this UGen spawns a new thread to avoid blocking the server command queue, so it is free to go about with its business. For a more detailed discussion of the available threading and monitoring options, including the two undocumented Class Methods below (.processBlocking and .kr) please read the guide LINK::Guides/FluidBufMultiThreading::. CLASSMETHODS:: From 908a56e048d2f8f6513e9477b4509d218a10e8ec Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 7 Oct 2019 22:19:48 +0200 Subject: [PATCH 38/42] added the related header too --- .../Classes/FluidBufAmpSlice.schelp | 2 +- .../HelpSource/Classes/FluidBufCompose.schelp | 2 +- .../HelpSource/Classes/FluidBufHPSS.schelp | 2 +- .../Classes/FluidBufLoudness.schelp | 2 +- .../HelpSource/Classes/FluidBufMFCC.schelp | 2 +- .../Classes/FluidBufMelBands.schelp | 2 +- .../HelpSource/Classes/FluidBufNMF.schelp | 2 +- .../Classes/FluidBufNoveltySlice.schelp | 2 +- .../Classes/FluidBufOnsetSlice.schelp | 2 +- .../HelpSource/Classes/FluidBufPitch.schelp | 2 +- .../HelpSource/Classes/FluidBufSines.schelp | 2 +- .../Classes/FluidBufSpectralShape.schelp | 2 +- .../HelpSource/Classes/FluidBufStats.schelp | 2 +- .../Classes/FluidBufThreadDemo.schelp | 2 +- .../Classes/FluidBufTransientSlice.schelp | 2 +- .../Classes/FluidBufTransients.schelp | 2 +- .../HelpSource/Classes/QuickStart.md | 22 +++++++++++++++++++ 17 files changed, 38 insertions(+), 16 deletions(-) create mode 100644 release-packaging/HelpSource/Classes/QuickStart.md diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp index 63eeaee..7cd73ba 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufAmpSlice SUMMARY:: Amplitude-based Slicer for Buffers CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: This class implements an amplitude-based slicer, with various customisable options and conditions to detect absolute and relative amplitude changes as onsets and offsets. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: diff --git a/release-packaging/HelpSource/Classes/FluidBufCompose.schelp b/release-packaging/HelpSource/Classes/FluidBufCompose.schelp index 991c41b..7f188f8 100644 --- a/release-packaging/HelpSource/Classes/FluidBufCompose.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufCompose.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufCompose SUMMARY:: Buffer Compositing Utility CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/Buffer +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/Buffer DESCRIPTION:: A FluidBufCompose object provides a flexible utility for combining the contents of buffers on the server. It can be used for thing like mixing down multichannel buffers, or converting from left-right stereo to mid-side. It is used extensively in all the example code of LINK::Guides/FluidDecomposition:: as part of the FluCoMa project. footnote:: diff --git a/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp b/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp index 240ee2b..7a55417 100644 --- a/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufHPSS SUMMARY:: Buffer-Based Harmonic-Percussive Source Separation Using Median Filtering CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp b/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp index 1ec1bc1..006b9f6 100644 --- a/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufLoudness.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufLoudness SUMMARY:: A Loudness and True-Peak Descriptor on a Buffer CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp b/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp index 57ca552..d2e4b88 100644 --- a/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufMFCC.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufMFCC SUMMARY:: Mel-Frequency Cepstral Coefficients as Spectral Descriptors on a Buffer CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/FluidBufMelBands +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/FluidBufMelBands DESCRIPTION:: This class implements a classic spectral descriptor, the Mel-Frequency Cepstral Coefficients (https://en.wikipedia.org/wiki/Mel-frequency_cepstrum). The input is first filtered in to STRONG::numBands:: perceptually-spaced bands, as in LINK::Classes/FluidMelBands::. It is then analysed into STRONG::numCoeffs:: number of cepstral coefficients. It has the avantage of being amplitude invarient, except for the first coefficient. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.FOOTNOTE:: This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: diff --git a/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp b/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp index 1f911ce..a345c43 100644 --- a/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufMelBands.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufMelBands SUMMARY:: A Perceptually Spread Spectral Contour Descriptor on a Buffer CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/FluidBufMFCC +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/FluidBufMFCC DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp index e3e7559..e6824b3 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufNMF SUMMARY:: Buffer-Based Non-Negative Matrix Factorisation on Spectral Frames CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/FluidNMFMatch, Classes/FluidNMFFilter +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/FluidNMFMatch, Classes/FluidNMFFilter DESCRIPTION:: The FluidBufNMF object decomposes the spectrum of a sound into a number of components using Non-Negative Matrix Factorisation (NMF) footnote:: Lee, Daniel D., and H. Sebastian Seung. 1999. ‘Learning the Parts of Objects by Non-Negative Matrix Factorization’. Nature 401 (6755): 788–91. https://doi.org/10.1038/44565. diff --git a/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp b/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp index b043eb9..98be3fd 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNoveltySlice.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufNoveltySlice SUMMARY:: Buffer-Based Novelty-Based Slicer CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: This class implements a non-real-time slicer using an algorithm assessing novelty in the signal to estimate the slicing points. A novelty curve is being derived from running a kernel across the diagonal of the similarity matrix, and looking for peak of changes. It implements the seminal results published in 'Automatic Audio Segmentation Using a Measure of Audio Novelty' by J Foote. It is part of the Fluid Decomposition Toolkit of the FluCoMa project. footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: diff --git a/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp index 2be572f..2e6563a 100644 --- a/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufOnsetSlice.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufOnsetSlice SUMMARY:: Spectral Difference-Based Audio Buffer Slicer CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: This class implements many spectral-based onset detection metrics, most of them taken from the literature. (http://www.dafx.ca/proceedings/papers/p_133.pdf) Some are already available in SuperCollider's LINK::Classes/Onsets:: object yet not as offline processes. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: diff --git a/release-packaging/HelpSource/Classes/FluidBufPitch.schelp b/release-packaging/HelpSource/Classes/FluidBufPitch.schelp index cc161ea..ed40dfe 100644 --- a/release-packaging/HelpSource/Classes/FluidBufPitch.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufPitch.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufPitch SUMMARY:: A Selection of Pitch Descriptors on a Buffer CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/SpecCentroid, Classes/SpecFlatness, Classes/SpecCentroid, Classes/SpecPcile +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/SpecCentroid, Classes/SpecFlatness, Classes/SpecCentroid, Classes/SpecPcile DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufSines.schelp b/release-packaging/HelpSource/Classes/FluidBufSines.schelp index e30f86c..7b42a75 100644 --- a/release-packaging/HelpSource/Classes/FluidBufSines.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufSines.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufSines SUMMARY:: Buffer-Based Sinusoidal Modelling and Resynthesis CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Guides/FluidBufMultiThreading DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp b/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp index b4e56c4..a45b139 100644 --- a/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufSpectralShape.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufSpectralShape SUMMARY:: Seven Spectral Shape Descriptors on a Buffer CATEGORIES:: Libraries>FluidDecomposition -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/SpecCentroid, Classes/SpecFlatness, Classes/SpecCentroid, Classes/SpecPcile +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/SpecCentroid, Classes/SpecFlatness, Classes/SpecCentroid, Classes/SpecPcile DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufStats.schelp b/release-packaging/HelpSource/Classes/FluidBufStats.schelp index fbe1df5..f7ce1c1 100644 --- a/release-packaging/HelpSource/Classes/FluidBufStats.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufStats.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufStats SUMMARY:: Computing Statistics on Buffers as Series. CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: diff --git a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp index 131b304..2a78bc0 100644 --- a/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufThreadDemo.schelp @@ -62,4 +62,4 @@ c.cancel // if a simple call to the UGen is used, the progress can be monitored {c = FluidBufThreadDemo.kr(b,10000, Done.freeSelf); Poll.kr(Impulse.kr(2),c);}.scope; -:: \ No newline at end of file +:: diff --git a/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp index 41445ba..21f5c5e 100644 --- a/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufTransientSlice.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufTransientSlice SUMMARY:: Buffer-Based Transient-Based Slicer CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Classes/FluidBufTransients +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading, Classes/FluidBufTransients DESCRIPTION:: This class implements a non-real-time transient-based slice extractor relying on the same algorithm than Classes/FluidBufTransients using clicks/transients/derivation/anomaly in the signal to estimate the slicing points. It is part of the Fluid Decomposition Toolkit of the FluCoMa project.footnote::This was made possible thanks to the FluCoMa project ( http://www.flucoma.org/ ) funded by the European Research Council ( https://erc.europa.eu/ ) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 725899).:: diff --git a/release-packaging/HelpSource/Classes/FluidBufTransients.schelp b/release-packaging/HelpSource/Classes/FluidBufTransients.schelp index 44fe6b6..237d7d2 100644 --- a/release-packaging/HelpSource/Classes/FluidBufTransients.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufTransients.schelp @@ -1,7 +1,7 @@ TITLE:: FluidBufTransients SUMMARY:: Buffer-Based Transient Extractor CATEGORIES:: Libraries>FluidDecomposition, UGens>Buffer -RELATED:: Guides/FluCoMa, Guides/FluidDecomposition +RELATED:: Guides/FluCoMa, Guides/FluidDecomposition, Guides/FluidBufMultiThreading DESCRIPTION:: This class triggers a transient extractor on buffers on the non-real-time thread of the server. It implements declicking algorithm from chapter 5 of the classic Digital Audio Restoration by Godsill, Simon J., Rayner, Peter J.W. with some bespoke improvements on the detection function tracking. It is part of the Fluid Decomposition Toolkit of the FluCoMa project. footnote:: diff --git a/release-packaging/HelpSource/Classes/QuickStart.md b/release-packaging/HelpSource/Classes/QuickStart.md new file mode 100644 index 0000000..80d9288 --- /dev/null +++ b/release-packaging/HelpSource/Classes/QuickStart.md @@ -0,0 +1,22 @@ +# Instructions for the PureData version of the fluid.* toolbox + +## How to start: + +1) move the following items to their respective relevant pd search path +- externals are in /pd_objects +- help files are in /help +- audio used in the help files are in /media, which is expected to be parallel to /help +- detailed help is provided as a website in /docs + +2) The PureData document 'Fluid_Decomposition_Overview.pd' shows the toolbox at a glance. + +5) Parameters can be set by message (as in max with the same names) OR by option in the object box which work similarly to the [sigmund~] options. + +6) Most objects working on arrays/buffers are multichannel. The toolbox uses the following convention: a named array is expected to have a name, followed by -x where x is the 'channel' number, 0-indexed. For instance, a stereo source buffer defined as 'mybuf' will expect an array named 'mybuf-0' for the left channel, and an array named 'mybuf-1' for the right channel. A utility [multiarray.pd] is used throughout the helpfiles in conjonction with the [clone] to programmatically generate such 'multichannel' buffers. + +#### Enjoy! + + +## Known issues: +- pd is single threaded so doing buffer ops will do bad things to realtime audio. +- providing 'multichannel' arrays not enough in numbers (aka channels) will crash Pd. From 1a539e9de66acf98e37976932f4013392e49362b Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 8 Oct 2019 18:22:56 +0200 Subject: [PATCH 39/42] bufnmf: removed the placeholder nrt example --- .../HelpSource/Classes/FluidBufNMF.schelp | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp index e6824b3..e0a2d32 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp @@ -392,28 +392,3 @@ e.plot; // look at the activations (sharper 3rd component at transitions) g.plot; :: -STRONG:: Placeholder: Run process as .kr ugen and use Poll to get progress updates, cancel with server message:: -CODE:: -//load some buffers -( -b = Buffer.read(s,File.realpath(FluidBufNMF.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Tremblay-AaS-SynthTwoVoices-M.wav"); -c = Buffer.new(s); -x = Buffer.new(s); -y = Buffer.new(s); -~fft_size = 1024; -~frame_size = 512; -~hop_size = 256; -~which_component = 3; -) -//Run this to see progress in the scope -( -~synthID; -a = { - var nmf = FluidBufNMF.kr(b, 0,-1,0,-1,c,x,0,y,0,5,100,~frame_size,~hop_size,~fft_size, doneAction: Done.freeSelf); - ~synthID = nmf.synthIndex; - Poll.kr(Impulse.kr(3),nmf) -}.scope -) -//Run this to cancel processing -Server.default.sendMsg("/u_cmd", a.nodeID, ~synthID, "cancel") - :: From 1b433abd78247b361e0b69399a71ad70809833a0 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Sun, 27 Oct 2019 14:56:37 +0000 Subject: [PATCH 40/42] melbands: the perceptually spread vocoder example is ported from max --- .../HelpSource/Classes/FluidMelBands.schelp | 80 ++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidMelBands.schelp b/release-packaging/HelpSource/Classes/FluidMelBands.schelp index c7a266b..473bd4d 100644 --- a/release-packaging/HelpSource/Classes/FluidMelBands.schelp +++ b/release-packaging/HelpSource/Classes/FluidMelBands.schelp @@ -120,8 +120,84 @@ x.set(\low,20, \high, 20000) x.free;b.free;c.free;r.stop; :: -STRONG::A musical example:: +STRONG::A musical example: a perceptually spread vocoder:: CODE:: -// todo: port the Max one +//load a source and define control bus for the resynthesis cluster +( +b = Bus.new(\control,0,40); +c = Buffer.read(s,File.realpath(FluidMelBands.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav"); +d = Group.new; +) + +//play the source and s +( +x = { + arg dry = 0.2; + var source = PlayBuf.ar(1,c,loop:1); + Out.kr(b,FluidMelBands.kr(source,maxNumBands:40)); + Out.ar(0, DelayN.ar(source,delaytime:1024*SampleDur.ir,mul:dry)); +}.play; +) + +// set the dry playback volume +x.set(\dry, 0.5) + + +// create a cluster of sines tuned on each MelBand center frequency, as a sort of vocoder. +( +var lowMel = 1127.010498 * ((20/700) + 1).log; +var highMel = 1127.010498 * ((20000/700) + 1).log; +var rangeMel = highMel - lowMel; +var stepMel = rangeMel / 41; +40.do({ + arg i; + var freqMel = (stepMel * (i +1)) + lowMel; + var freq = ((freqMel/ 1127.01048).exp - 1 ) * 700; + {SinOsc.ar(freq,mul:Lag.kr(In.kr(b,40)[i],512*SampleDur.ir,0.0001))}.play(d,1,addAction:\addToTail); +}); +) + +// free all +d.free; x.free; b.free; c.free; + +///////////////////////////////////// +// instantiate a more dynamic vocoder: +// MouseX defines the bottom frequency and MouseY define the top frequency, between which the 40 bands of analysis and synthesis are perceptually equally spred + +// the bus, source and group +( +b = Bus.new(\control,0,40); +c = Buffer.read(s,File.realpath(FluidMelBands.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Nicol-LoopE-M.wav"); +d = Group.new; +) + +// the modified source +( +x = { + arg dry = 0.2; + var source = PlayBuf.ar(1,c,loop:1); + Out.kr(b,FluidMelBands.kr(source,maxNumBands:40,minFreq:MouseX.kr().exprange(20,600),maxFreq:MouseY.kr().exprange(650,20000))); + Out.ar(0, DelayN.ar(source,delaytime:1024*SampleDur.ir,mul:dry)); +}.play; +) + +// the modified vocoder +( +40.do({ + arg i; + { + var lowMel = 1127.010498 * ((MouseX.kr().exprange(20,600)/700) + 1).log; + var highMel = 1127.010498 * ((MouseY.kr().exprange(650,20000)/700) + 1).log; + var rangeMel = highMel - lowMel; + var stepMel = rangeMel / 41; + var freqMel = (stepMel * (i +1)) + lowMel; + var freq = ((freqMel/ 1127.01048).exp - 1 ) * 700; + SinOsc.ar(freq,mul:Lag.kr(In.kr(b,40)[i],512*SampleDur.ir,0.0001))}.play(d,1,addAction:\addToTail); +}); +) + +// free all +d.free; x.free; b.free; c.free; + :: From 44c7170b3c85c43935e13fe051e1c0f85dfb0cb1 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 28 Oct 2019 15:45:55 +0000 Subject: [PATCH 41/42] the creative example of bufstats is now done --- .../HelpSource/Classes/FluidBufStats.schelp | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/release-packaging/HelpSource/Classes/FluidBufStats.schelp b/release-packaging/HelpSource/Classes/FluidBufStats.schelp index f7ce1c1..dbae2f0 100644 --- a/release-packaging/HelpSource/Classes/FluidBufStats.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufStats.schelp @@ -115,7 +115,43 @@ FluidBufStats.process(s, b, stats:c, numDerivs:1, action:{c.getn(0,c.numFrames,{ STRONG::A musical example:: CODE:: -// todo: port the Max one +// create some buffers +( +b = Buffer.read(s,File.realpath(FluidBufStats.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"); +c = Buffer.new(s); +d = Buffer.new(s); +) + +//split in various chunks, collecting the indices in an array +FluidBufOnsetSlice.process(s,b, minSliceLength: 10, metric: 9, threshold: 0.4, filterSize: 7, indices: c, action:{c.loadToFloatArray(action: {|array| e = array.add(b.numFrames).addFirst(0);e.postln;})}); + +//describe the whole input too, here using pitch, and collecting the values in an array, dismissing the (interleaved) confidence. +FluidBufPitch.process(s,b,features:c, action:{c.loadToFloatArray(action: {|array| f = array.unlace(2)[0]; f.postln;})}); + +// iterate through each slice, taking the median of the first derivative of the pitch of each +( +g= Array.new; +Routine({ + e.doAdjacentPairs({ + arg start,end; + FluidBufStats.processBlocking(s,c,(start/512).asInt,((end-start)/512).max(2).asInt,0,1,d,1, action: {d.loadToFloatArray(action: { + arg array; + g = g.add(array[12]); + "% % %\n".postf((start/512).asInt,((end-start)/512).max(2).asInt, array[12]); + })}); +}); + "Done".postln; +}).play; +) + +//obtain the order of indices that would sort the stats +h = g.order; + +//play in loop the slice in order of pitch direction (the median of the slice's pitch variation) +( +var which = h[5]; +{BufRd.ar(1, b, Phasor.ar(0,1,e[which],e[which+1],e[which]))}.play; +) :: From 7188049266b11db5cf7791c6e84c2ff88f005272 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Thu, 31 Oct 2019 11:01:58 +0000 Subject: [PATCH 42/42] coded strange resonators in nmfmatch --- .../HelpSource/Classes/FluidNMFMatch.schelp | 65 ++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp b/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp index a8946ef..3aeecc2 100644 --- a/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp +++ b/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp @@ -107,7 +107,7 @@ c = Buffer.new(s); ~bases = Buffer.new(s); ~spectralshapes = Buffer.new(s); ~stats = Buffer.new(s); -~centroids = Buffer.new(s); +~centroids = Array.new(); ~trainedBases = Buffer.new(s); ) @@ -312,5 +312,66 @@ c.query :: STRONG::Strange Resonators:: CODE:: - //to be completed +//load the source and declare buffers/arrays +( +b = Buffer.read(s,File.realpath(FluidNMFMatch.class.filenameSymbol).dirname.withTrailingSlash ++ "../AudioFiles/Tremblay-AaS-AcousticStrums-M.wav"); +c = Buffer.new(s); +~bases = Buffer.new(s); +~spectralshapes = Buffer.new(s); +~stats = Buffer.new(s); +~centroids = Array.new(); +) + +// train only 2 seconds +( +Routine { + FluidBufNMF.process(s,b,0,88200,0,1, c, ~bases, components:8, hopSize:256, fftSize:2048); + c.query; +}.play; +) + +// wait for the query to print +// find the component that has the picking sound checking the median spectral centroid +( +FluidBufSpectralShape.process(s, c, features: ~spectralshapes, action:{ + |shapes|FluidBufStats.process(s,shapes,stats:~stats, action:{ + |stats|stats.getn(0, (stats.numChannels * stats.numFrames) ,{ + |x| ~centroids = x.select({ + |item, index| (index.mod(7) == 0) && (index.div(56) == 5); + }) + }) + }) +}); +) + +//7 shapes (track) x 8 components (tracks) x 7 stats(frames) +~stats.query +~centroids.size() + +// make a player with harmonic on the out0, percussive on the out1, and 8 ctlout of nmfmatch +~splitaudio = Bus.audio(s,1); +~nmfenvs = Bus.control(s,8); + +// start the player and you should hear only the pick a little +( +x = { + var sound = PlayBuf.ar(1,b,loop:1); + var harm, perc; + # harm, perc = FluidHPSS.ar(sound, maskingMode:1, harmThreshFreq1: 0.005869, harmThreshAmp1: -9.6875, harmThreshFreq2: 0.006609, harmThreshAmp2: -4.375, hopSize:256); + Out.ar(~splitaudio, harm); + Out.kr(~nmfenvs, FluidNMFMatch.kr(sound, ~bases, maxComponents:8, hopSize:256, fftSize:2048)); + Out.ar(0,perc.dup) +}.play; +) + +// make an array of resonators tuned on the median of the centroids +( +8.do({ + arg i; + { + var audio = BPF.ar(In.ar(~splitaudio,1), ~centroids[i],0.01,LagUD.kr(In.kr(~nmfenvs,8)[i],0.001,0.01,0.1)); + Out.ar(0,Pan2.ar(audio, (i / 14) - 0.25)); + }.play(x,addAction: \addAfter); +}); +) ::