|
|
TITLE:: FluidBufNMF
|
|
|
summary:: Buffer-Based Non-Negative Matrix Factorisation on Spectral Frames
|
|
|
categories:: Libraries>FluidDecomposition, UGens>Buffer
|
|
|
related:: Guides/FluCoMa, Guides/FluidDecomposition
|
|
|
|
|
|
|
|
|
DESCRIPTION::
|
|
|
This class triggers a Non-Negative Matrix Factorisation process (NMF for short) on buffers on the non-real-time thread of the server. It is a good way to get different components out of a buffered signal. 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 algorithm will take a buffer in, and will divide it in a number of ranks. It can provide back either or all of the following: LIST::
|
|
|
## a spectral contour of each rank in the form of a magnitude spectrogramme (called a dictionary in NMF lingo);
|
|
|
## an amplitude envoloppe of each rank in the form of gains for each consecutive frames of the unterlying FFT (called an activation in NMF lingo);
|
|
|
## a reconstruction of each rank in audio domain. ::
|
|
|
|
|
|
The whole process can be related to a vocoder, where each filter is instead a spectrograme of magnitudes (no phase information). More information for musicianly uses of NMF are availabe in LINK::Guides/FluCoMa:: overview file.
|
|
|
|
|
|
|
|
|
CLASSMETHODS::
|
|
|
|
|
|
METHOD:: process
|
|
|
This is the method that calls for the factorisation to be calculated on a given source buffer.
|
|
|
|
|
|
ARGUMENT:: server
|
|
|
The server on which the buffers to be processed are allocated.
|
|
|
|
|
|
ARGUMENT:: srcBufNum
|
|
|
The index of the buffer to use as the source material to be decomposed through the NMF process. The different channels of multichannel buffers will be processing sequentially.
|
|
|
|
|
|
ARGUMENT:: startAt
|
|
|
Where in the srcBuf should the NMF process start, in sample.
|
|
|
|
|
|
ARGUMENT:: nFrames
|
|
|
How many frames should be processed.
|
|
|
|
|
|
ARGUMENT:: startChan
|
|
|
For multichannel srcBuf, which channel should be processed first.
|
|
|
|
|
|
ARGUMENT:: nChans
|
|
|
For multichannel srcBuf, how many channel should be processed.
|
|
|
|
|
|
ARGUMENT:: dstBufNum
|
|
|
The index of the buffer where the different reconstructed ranks will be reconstructed. The buffer will be resized to STRONG::rank * numChannelsProcessed:: channels and STRONG::sourceDuration:: lenght. If STRONG::nil:: is provided, the reconstruction will not happen.
|
|
|
|
|
|
ARGUMENT:: dictBufNum
|
|
|
The index of the buffer where the different dictionaries will be written to and/or read from: the behaviour is set in the following argument. If STRONG::nil:: is provided, no dictionary will be provided.
|
|
|
|
|
|
ARGUMENT:: dictFlag
|
|
|
This flag decides of how the dictionnary buffer passed as the previous argument is treated.
|
|
|
table::
|
|
|
## 0 || The dictionaries are seeded randomly, and the resulting ones will be written after the process in the passed buffer. The buffer is resized to STRONG::rank * numChannelsProcessed:: channels and STRONG::(fftSize / 2 + 1):: lenght.
|
|
|
## 1 || The passed buffer is considered as seed for the dictionaries. Its dimensions should match the values above. The resulting dictionaries will replace the seed ones.
|
|
|
## 2 || The passed buffer is considered as a template for the dictionaries, and will therefore not change. Its dictionaries should match the values above.
|
|
|
::
|
|
|
|
|
|
ARGUMENT:: actBufNum
|
|
|
The index of the buffer where the different activations will be written to and/or read from: the behaviour is set in the following argument. If STRONG::nil:: is provided, no activation will be provided.
|
|
|
|
|
|
ARGUMENT:: actFlag
|
|
|
This flag decides of how the activation buffer passed as the previous argument is treated.
|
|
|
table::
|
|
|
## 0 || The activations are seeded randomly, and the resulting ones will be written after the process in the passed buffer. The buffer is resized to STRONG::rank * numChannelsProcessed:: channels and STRONG::(sourceDuration / hopsize + 1):: lenght.
|
|
|
## 1 || The passed buffer is considered as seed for the activations. Its dimensions should match the values above. The resulting activations will replace the seed ones.
|
|
|
## 2 || The passed buffer is considered as a template for the activations, and will therefore not change. Its dimensions should match the values above.
|
|
|
::
|
|
|
|
|
|
ARGUMENT:: rank
|
|
|
The number of elements the NMF algorythim will try to divide the spectrogram of the source in.
|
|
|
|
|
|
ARGUMENT:: nIter
|
|
|
The NMF process is iterative, trying to converge to the smallest error in its factorisation. The number of iterations will decide how many times it tries to adjust its guestimates. Higher numbers here will be more CPU expensive, lower numbers will be more unpredictable in quality.
|
|
|
|
|
|
ARGUMENT:: sortFlag
|
|
|
This allows to choose between the different methods of sorting the ranks in order to get similar sonic qualities on a given rank (not implemented yet)
|
|
|
|
|
|
ARGUMENT:: winSize
|
|
|
The window size. As NMF relies on spectral frames, we need to decide what precision we give it spectrally and temporally, in line with Gabor Uncertainty principles. http://www.subsurfwiki.org/wiki/Gabor_uncertainty
|
|
|
|
|
|
ARGUMENT:: hopSize
|
|
|
The window hope size. As NMF relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts.
|
|
|
|
|
|
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.
|
|
|
|
|
|
ARGUMENT:: winType
|
|
|
The inner FFT/IFFT windowing type (not implemented yet)
|
|
|
|
|
|
ARGUMENT:: randSeed
|
|
|
The NMF process needs to seed its starting point. If specified, the same values will be used. The default of -1 will randomly assign them. (not implemented yet)
|
|
|
|
|
|
RETURNS::
|
|
|
Nothing, as the various destination buffers are declared in the function call.
|
|
|
|
|
|
|
|
|
EXAMPLES::
|
|
|
|
|
|
code::
|
|
|
b = Buffer.read(s,"../../../AudioFiles/01-mix.wav".resolveRelative);
|
|
|
b.play
|
|
|
::
|
|
|
|