diff --git a/release-packaging/Classes/FDHPSS.sc b/release-packaging/Classes/FDHPSS.sc index 1ee7e62..9564fe3 100644 --- a/release-packaging/Classes/FDHPSS.sc +++ b/release-packaging/Classes/FDHPSS.sc @@ -1,8 +1,9 @@ FDHPSS{ *process { arg server, src, offsetframes = 0, numframes = -1, offsetchans = 0, numchans = -1, harmbuf, percbuf, psize = 31, hsize = 17, winsize = 4096, hopsize = 1024, fftsize = -1; - server = server ? Server.default -;if(src.bufnum.isNil) {Error("Invalid Buffer").format(thisMethod.name, this.class.name).throw}; + server = server ? Server.default; + + if(src.bufnum.isNil) {Error("Invalid Buffer").format(thisMethod.name, this.class.name).throw}; server.sendMsg(\cmd, \BufHPSS, src.bufnum, offsetframes, numframes, offsetchans, numchans, if( harmbuf.isNil, -1, {harmbuf.bufnum}), diff --git a/release-packaging/Classes/fdSines.sc b/release-packaging/Classes/fdSines.sc new file mode 100644 index 0000000..5692ba8 --- /dev/null +++ b/release-packaging/Classes/fdSines.sc @@ -0,0 +1,14 @@ +FDSines{ + *process { arg server, src, offsetframes = 0, numframes = -1, offsetchans = 0, numchans = -1, sinebuf, resbuf, bandwidth = 76, threshold = 0.7, mintracklen = 15, magweight = 0.1, freqweight = 1, winsize = 4096, hopsize = 1024, fftsize = -1; + + server = server ? Server.default; + if(src.bufnum.isNil) {Error("Invalid Buffer").format(thisMethod.name, this.class.name).throw}; + + server.sendMsg(\cmd, \BufSines, src.bufnum, offsetframes, numframes, offsetchans, numchans, +if( sinebuf.isNil, -1, {sinebuf.bufnum}), +if( resbuf.isNil, -1, {resbuf.bufnum}), bandwidth, threshold, mintracklen, magweight, freqweight, winsize, hopsize, fftsize); + + + +} +} \ No newline at end of file diff --git a/release-packaging/HelpSource/Classes/fdSines.schelp b/release-packaging/HelpSource/Classes/fdSines.schelp new file mode 100644 index 0000000..d080c14 --- /dev/null +++ b/release-packaging/HelpSource/Classes/fdSines.schelp @@ -0,0 +1,15 @@ +s = Server.default; +s.reboot + +( + b = Buffer.read(s,"/Users/owen/Desktop/denoise_stn/sources/01-mix.wav"); + h = Buffer.new(s,0,1); + n = Buffer.new(s,0,1); +) + +Buffer.new(s) + +FDSines.process(s,b,0,1-1,0,-1,h,n,15,0.2) + +n.play; +h.play; \ No newline at end of file diff --git a/src/fdSines/CMakeLists.txt b/src/fdSines/CMakeLists.txt new file mode 100755 index 0000000..3693881 --- /dev/null +++ b/src/fdSines/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/fdSines/fdSines.cpp b/src/fdSines/fdSines.cpp new file mode 100644 index 0000000..380a49a --- /dev/null +++ b/src/fdSines/fdSines.cpp @@ -0,0 +1,96 @@ + // FD_BufSines, an NRT buffer Sinusoidal Modelling Processor +// 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 "fdNRTBase.hpp" +#include "algorithms/STFT.hpp" +#include "data/FluidTensor.hpp" +#include "clients/nrt/Sines.hpp" +#include "clients/common/FluidParams.hpp" +#include "SC_PlugIn.h" +#include +#include + +static InterfaceTable *ft; + +//Using statements for fluidtensor +using fluid::FluidTensor; +using fluid::FluidTensorView; + +namespace fluid { + namespace sc{ + + class BufSines: public NRTCommandBase + { + /* + - srcbuf num + – src start frame + - src numframes + – src start chan + – src num chans + – sines dst + – residual dst + – bandwidth (bins) + – threshold (0-1) + – minTrackLen (frames, 0 for no tracking) + - magnitude weight(0-1) + - freq weight (0-1) + – window size + – hop size + – fft size + */ + public: + using client_type = stn::SinesClient; + using NRTCommandBase::NRTCommandBase; + + ~BufSines() {} + + void runCommand(World* world, void* replyAddr, char* completionMsgData, size_t completionMsgSize) + { + cmd(world, "AsyncNMF", replyAddr, completionMsgData, completionMsgSize); + } + + bool process(World* world) + { + //sanity check the parameters + bool parametersOk; + stn::SinesClient::ProcessModel processModel; + std::string whatHappened;//this will give us a message to pass back if param check fails + std::tie(parametersOk,whatHappened,processModel) = processor.sanityCheck(); + if(!parametersOk) + { + Print("fdNMF: %s \n", whatHappened.c_str()); + return false; + } + //Now, we can proceed + processor.process(processModel); + mModel = processModel; + return true; + } + + bool postProcess(World* world) + { + static_cast + (parameter::lookupParam("sinebuf", processor.getParams()).getBuffer())->assignToRT(world); + static_cast + (parameter::lookupParam("resbuf", processor.getParams()).getBuffer())->assignToRT(world); + return true; + } + + bool postComplete(World* w) { return true; } + std::vector& parameters() + { + return processor.getParams(); + } + private: + stn::SinesClient processor; + stn::SinesClient::ProcessModel mModel; + };//class + } //namespace sc +}//namespace fluid + + +PluginLoad(OfflineFluidDecompositionUGens) { + ft = inTable; + registerCommand(ft, "BufSines"); + fluid::sc::printCmd(ft,"BufSines","FDSines"); +} diff --git a/src/fdSines/tests.scd b/src/fdSines/tests.scd new file mode 100644 index 0000000..996be66 --- /dev/null +++ b/src/fdSines/tests.scd @@ -0,0 +1,145 @@ +s.reboot +//////////////////////////// +// test for efficiency + +( +b = Buffer.read(s,"/Users/pa/Documents/documents@hudd/research/projects/fluid corpus navigation/research/archives-2017-18/denoise_stn/sources/01-mix.wav"); +c = Buffer.new(s); +x = Buffer.new(s); +y = Buffer.new(s); +~fft_size = 1024; +~frame_size = 512; +~hop_size = 256; +~which_rank = 0; +) + +( +// without sources +Routine{ + t = Main.elapsedTime; + FDNMF.process(s,b.bufnum,0,-1,0,-1,nil,x.bufnum,0,y.bufnum,0,5,100,0,~frame_size,~hop_size,~fft_size); + s.sync; + (Main.elapsedTime - t).postln; +}.play +); + +// with sources only +( +Routine{ + t = Main.elapsedTime; + FDNMF.process(s,b.bufnum, 0,-1,0,-1,c.bufnum,nil,0,nil,0,5,100,0,~frame_size,~hop_size,~fft_size); + s.sync; + (Main.elapsedTime - t).postln; +}.play +) + +// with everything +( +Routine{ + t = Main.elapsedTime; + FDNMF.process(s,b.bufnum, 0,-1,0,-1,c.bufnum,x.bufnum,0,y.bufnum,0,5,100,0,~frame_size,~hop_size,~fft_size); + s.sync; + (Main.elapsedTime - t).postln; +}.play +) + + +//look at the dictionaries and activations +c.plot;x.plot; y.plot; +//null test of the sum of sources +{(PlayBuf.ar(5,c.bufnum,doneAction:2).sum)+(-1*PlayBuf.ar(1,b.bufnum,doneAction:2))}.play + +// play around +{Splay.ar(PlayBuf.ar(5,c.bufnum,doneAction:2))}.play + +//play a single source +{PlayBuf.ar(5,c.bufnum,doneAction:2)[~which_rank].dup}.play + +//play noise through a filter +( +{ + var chain; + chain = FFT(LocalBuf(~fft_size), WhiteNoise.ar()); + + chain = chain.pvcollect(~fft_size, {|mag, phase, index| + [mag * BufRd.kr(5,x.bufnum,DC.kr(index),0,1)[~which_rank]]; + }); + + IFFT(chain); +}.play +) + +//play noise through an activation +{WhiteNoise.ar(BufRd.kr(5,y.bufnum,Phasor.ar(1,1/~hop_size,0,(b.numFrames / ~hop_size + 1)),0,1)[~which_rank])*0.5}.play + +//play noise through both activation and filter +( +{ + var chain; + chain = FFT(LocalBuf(~fft_size), WhiteNoise.ar(BufRd.kr(5,y.bufnum,Phasor.ar(1,1/~hop_size,0,(b.numFrames / ~hop_size + 1)),0,1)[~which_rank]*12),0.5,1); + + chain = chain.pvcollect(~fft_size, {|mag, phase, index| + [mag * BufRd.kr(5,x.bufnum,DC.kr(index),0,1)[~which_rank]]; + }); + + [0,IFFT(chain)]; +}.play +) + +// test with stereo input +Buffer.freeAll(s) + +( +b = Buffer.read(s,"/Users/pa/Desktop/verystereo.wav"); +c = Buffer.new(s); +x = Buffer.new(s); +y = Buffer.new(s); +~fft_size = 1024; +~frame_size = 512; +~hop_size = 256; +) + +b.play + +( +Routine{ + t = Main.elapsedTime; + FDNMF.process(s,b.bufnum,0,-1,0,-1,c.bufnum,x.bufnum,0,y.bufnum,0,5,100,0,~frame_size,~hop_size,~fft_size); + s.sync; + (Main.elapsedTime - t).postln; +}.play +) + +//test a single rank +{PlayBuf.ar(10,c.bufnum,doneAction:2)[9].dup}.play + +// play them all across in a sort of upmixed stereo... +{Splay.ar(PlayBuf.ar(10,c.bufnum,doneAction:2))}.play + +//test process on a segment +Buffer.freeAll(s) + +( +b = Buffer.read(s,"/Users/pa/Desktop/verystereo.wav"); +c = Buffer.new(s); +d = Buffer.new(s); +) + +b.play + +( +Routine{ + t = Main.elapsedTime; + FDNMF.process(s,b.bufnum,44100,44100,0,1,c.bufnum,rank:2); + s.sync; + (Main.elapsedTime - t).postln; + t = Main.elapsedTime; + FDNMF.process(s,b.bufnum,8810,44100,1,1,d.bufnum,rank:2); + s.sync; + (Main.elapsedTime - t).postln; +}.play +) +c.query +c.play +d.query +d.play