commit 8eef64ae175deb524df552f02c001d0fc88e2db7 Author: Pierre Alexandre Tremblay Date: Tue Jul 10 17:58:06 2018 +0100 working basic clone of the 'waveSetCopyTo' instance method with all the trimmings diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..625e389 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build +**/.DS_Store +release-packaging/fdNMF/classes +release-packaging/fdNMF/plugins diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..43d07ff --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,89 @@ +set(FILENAME "fdNMF.cpp") #specify the .cpp file here +cmake_minimum_required (VERSION 2.8) +get_filename_component(PROJECT ${FILENAME} NAME_WE) #automatically sets project name from the filename +# set(PROJECT "my_name") #alternatively set project name manually +message(STATUS "Project name is ${PROJECT}") +project (${PROJECT}) + +include_directories(${SC_PATH}/include/plugin_interface) +include_directories(${SC_PATH}/include/common) +include_directories(${SC_PATH}/common) + +set(CMAKE_SHARED_MODULE_PREFIX "") +if(APPLE OR WIN32) +set(CMAKE_SHARED_MODULE_SUFFIX ".scx") +endif() + +option(SUPERNOVA "Build plugins for supernova" OFF) +if (SUPERNOVA) + include_directories(${SC_PATH}/external_libraries/nova-tt) + # actually just boost.atomic + include_directories(${SC_PATH}/external_libraries/boost) + include_directories(${SC_PATH}/external_libraries/boost_lockfree) + include_directories(${SC_PATH}/external_libraries/boost-lockfree) +endif() + +option(CPP11 "Build with c++11." ON) + +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(CMAKE_COMPILER_IS_CLANG 1) +endif() + +if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_CLANG) + add_definitions(-fvisibility=hidden) + + include (CheckCCompilerFlag) + include (CheckCXXCompilerFlag) + + CHECK_C_COMPILER_FLAG(-msse HAS_SSE) + CHECK_CXX_COMPILER_FLAG(-msse HAS_CXX_SSE) + + if (HAS_SSE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse") + endif() + if (HAS_CXX_SSE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse") + endif() + + CHECK_C_COMPILER_FLAG(-msse2 HAS_SSE2) + CHECK_CXX_COMPILER_FLAG(-msse2 HAS_CXX_SSE2) + + if (HAS_SSE2) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse2") + endif() + if (HAS_CXX_SSE2) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2") + endif() + + CHECK_C_COMPILER_FLAG(-mfpmath=sse HAS_FPMATH_SSE) + CHECK_CXX_COMPILER_FLAG(-mfpmath=sse HAS_CXX_FPMATH_SSE) + + if (HAS_FPMATH_SSE) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpmath=sse") + endif() + if (HAS_CXX_FPMATH_SSE) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse") + endif() + + if(NATIVE) + add_definitions(-march=native) + endif() + + if(CPP11) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + if(CMAKE_COMPILER_IS_CLANG) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++") + endif() + endif() +endif() +if(MINGW) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mstackrealign") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mstackrealign") +endif() + +add_library(${PROJECT} MODULE ${FILENAME}) +if(SUPERNOVA) + add_library(${PROJECT}_supernova MODULE ${FILENAME}) + set_property(TARGET ${PROJECT}_supernova + PROPERTY COMPILE_DEFINITIONS SUPERNOVA) +endif() diff --git a/fdNMF.cpp b/fdNMF.cpp new file mode 100644 index 0000000..f53b998 --- /dev/null +++ b/fdNMF.cpp @@ -0,0 +1,93 @@ +// FD_BufNMF, an NRT buffer NMF 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 "SC_PlugIn.h" + +static InterfaceTable *ft; + +void BufNMF(World *world, struct SndBuf *buf, struct sc_msg_iter *msg) +{ + int frames1 = buf->frames; + int channels1 = buf->channels; + + uint32 bufnum2 = msg->geti(); + int repetitions = msg->geti(); + + if (bufnum2 >= world->mNumSndBufs){ + Print("waveSetCopyTo is not happy because the source buffer does not exist.\n"); + return; + } + + SndBuf* buf2 = world->mSndBufs + bufnum2; + + if (buf2->data == buf->data){ + Print("waveSetCopyTo is not happy because the source buffer is the same as the destination buffer.\n"); + return; + } + + int frames2 = buf2->frames; + int channels2 = buf2->channels; + + if (channels1 != channels2) { + Print("waveSetCopyTo is not happy because the source buffer has a different channel count than the destination buffer.\n"); + return; + } + + // checks if default value (0) or error in quantity and sets to a filling behaviour or at least one + if (repetitions < 1){ + repetitions = int(frames1 / frames2); + if (repetitions < 1) + repetitions = 1; + } + + //for each channels + for (int j=0;jdata[j] > 0); //set the previous sample polarity as the first sample + long writeindex = 0; // set the writing index at the start of the buffer + long wavesetlenght; + + //interates through the source samples + for (int i=0;idata[(i*channels2)+j] < 0.0) { + // Print("in1-1\n"); + // ... flag as being now in negativeland and exit. + prevpol = 0; + } + } else { + // if previously in negativeland... + // Print("in2\n"); + if (buf2->data[(i*channels2)+j] >= 0.0) { + // ...and now being zero or up, so we write + // Print("in2-2\n"); + // check it is not the first zero crossing + if (lastXadd >=0) { + // check if the lenght will be too long for all repetitions + wavesetlenght = i - lastXadd; + if (((wavesetlenght*repetitions)+ writeindex) > frames1) break; + + // write if enough place + for (int k = 0; k < repetitions; k++){ + for (int l = 0; l < wavesetlenght; l++) { + buf->data[(writeindex*channels2)+j] = buf2->data[((lastXadd+l)*channels2)+j]; + writeindex++; + } + } + } + // setting the flag and the new past + prevpol = 1; + lastXadd = i; + } + } + } + } +} + +PluginLoad(OfflineFluidDecompositionUGens) { + ft = inTable; + DefineBufGen("BufNMF", BufNMF); +} diff --git a/fdfNMF.sc b/fdfNMF.sc new file mode 100644 index 0000000..80c0e3e --- /dev/null +++ b/fdfNMF.sc @@ -0,0 +1,7 @@ +// adds an instance method to the Buffer class ++ Buffer { + fdNMF { arg dstBuf, repetitions = 0; + if(bufnum.isNil) { Error("Cannot call % on a % that has been freed".format(thisMethod.name, this.class.name)).throw }; + server.listSendMsg([\b_gen, dstBuf.bufnum, "BufNMF", bufnum, repetitions]) + } +} diff --git a/release-packaging/fdNMF/HelpSource/Classes/Buffer.ext.schelp b/release-packaging/fdNMF/HelpSource/Classes/Buffer.ext.schelp new file mode 100644 index 0000000..af3c23c --- /dev/null +++ b/release-packaging/fdNMF/HelpSource/Classes/Buffer.ext.schelp @@ -0,0 +1,27 @@ +INSTANCEMETHODS:: + +SUBSECTION:: Fluid Decomposition + +METHOD:: fdNMF +This method does the same as Buffer.waveSetCopyTo + +ARGUMENT:: an arg +The amount by which the values will be multiplied. + +ARGUMENT:: another arg +The amount by which the values will be multiplied. + +DISCUSSION:: + +strong:: Didactic examples::: + +CODE:: +s.boot; + +:: + +strong:: More musical examples::: + +CODE:: +s.boot; +:: \ No newline at end of file diff --git a/tests.scd b/tests.scd new file mode 100644 index 0000000..f333ebf --- /dev/null +++ b/tests.scd @@ -0,0 +1,16 @@ +s.quit; + +s.boot; + +// create a one-and-a-bit-cycle buffer and an empty one +b = Buffer.alloc(s,256); +c = Buffer.alloc(s,1000); + +///resynthesis the source buffer with a slightly shorter wavelenght +b.sine2([256/250],[1],true,false); +b.fdNMF(c,4) +c.plot +//Voilà! + +// clean up +b.free; c.free \ No newline at end of file