diff --git a/.github/workflows/json_api.yml b/.github/workflows/json_api.yml new file mode 100644 index 0000000..de0a5f9 --- /dev/null +++ b/.github/workflows/json_api.yml @@ -0,0 +1,48 @@ +name: Dev API + +on: + workflow_dispatch: + push: + branches: [ dev, ci/** ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: flucoma/actions/env@v4 + - uses: flucoma/actions/docs@v4 + with: + target: 'MAKE_RAW_REF' + + - uses: dev-drprasad/delete-tag-and-release@v0.2.0 + with: + delete_release: true # default: false + tag_name: api # tag name to delete + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup SSH + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH }} + known_hosts: 'placeholder' + + - name: Adding Known Hosts + run: | + mkdir -p ~/.ssh + ssh-keyscan -H ${{ secrets.DO_IP }} >> ~/.ssh/known_hosts + + - name: package and upload + uses: softprops/action-gh-release@v1 + with: + name: FluCoMa Docs API + body: "A JSON that can be accessed to derive parameters/args for objects. The build hash is ${{ github.sha }}" + files: 'build/flucoma.api.json' + prerelease: true + tag_name: api + draft: false + + - name: Upload To Droplet + run: | + rsync -avz --delete --no-times --no-o --no-g --no-perms ./build/api.json james@${{ secrets.DO_IP }}:/home/learn/www/ diff --git a/.gitignore b/.gitignore index c4f8df7..b3ab3b4 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ schelp *.pyc interfaces/* *.log +**/.DS_Store diff --git a/CMakeLists.txt b/CMakeLists.txt index 035a75a..4da7db2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set(MAX_DOC_OUT "${CMAKE_BINARY_DIR}/max_ref" CACHE PATH "") set(PD_DOC_OUT "${CMAKE_BINARY_DIR}/pd_ref" CACHE PATH "") set(CLI_DOC_OUT "${CMAKE_BINARY_DIR}/cli_ref" CACHE PATH "") set(SC_DOC_OUT "${CMAKE_BINARY_DIR}/sc_ref" CACHE PATH "") +set(RAW_DOC_OUT "${CMAKE_BINARY_DIR}" CACHE PATH "") # option(TESTS,"Run tests?") include(FetchContent) @@ -138,6 +139,7 @@ add_ref_target(max "Making Max ref") add_ref_target(pd "Making PD ref") add_ref_target(cli "Making CLI ref") add_ref_target(sc "Making SC ref") +add_ref_target(raw "Making raw API JSON") enable_testing() diff --git a/doc/AmpFeature.rst b/doc/AmpFeature.rst new file mode 100644 index 0000000..4425a7b --- /dev/null +++ b/doc/AmpFeature.rst @@ -0,0 +1,41 @@ +:digest: Realtime Amplitude Differential Feature +:species: transformer +:sc-categories: Libraries>FluidDecomposition +:sc-related: Guides/FluidCorpusManipulationToolkit +:see-also: AmpGate, AmpSlice, OnsetFeature, NoveltyFeature +:description: Calculate the amplitude differential feature in realtime. +:discussion: + :fluid-obj:`AmpSlice` uses the differential between a fast and a slow envelope follower to determine changes in amplitude. This object calculates the amplitude differential and copies it to an output buffer. + +:process: The audio rate in, control rate out version of the object. +:output: A KR signal of the feature. + +:control in: + + The audio to be processed. + +:control fastRampUp: + + The number of samples the relative envelope follower will take to reach the next value when raising. Typically, this will be faster than slowRampUp. + +:control fastRampDown: + + The number of samples the relative envelope follower will take to reach the next value when falling. Typically, this will be faster than slowRampDown. + +:control slowRampUp: + + The number of samples the absolute envelope follower will take to reach the next value when raising. + +:control slowRampDown: + + The number of samples the absolute envelope follower will take to reach the next value when falling. + +:control floor: + + The level in dB the slowRamp needs to be above to consider a detected difference valid, allowing to ignore the slices in the noise floor. + +:control highPassFreq: + + The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. A frequency of 0 bypasses the filter. + + diff --git a/doc/AudioTransport.rst b/doc/AudioTransport.rst index 84c8189..acfcc37 100644 --- a/doc/AudioTransport.rst +++ b/doc/AudioTransport.rst @@ -2,13 +2,15 @@ :species: transformer[2] :sc-categories: FluidManipulation :sc-related: Classes/FluidBufAudioTransport -:see-also: +:see-also: NMFMorph, BufNMFCross :description: - Interpolates between the spectra of two sounds using the Optimal Transport algorithm + Interpolates between the spectra of two sounds using optimal transport. +:discussion: + Interpolates between the spectra of two sounds using the optimal transport algorithm. This enables morphing and hybridisation of the perceptual qualities of each source linearly. See Henderson and Solomonm (2019) AUDIO TRANSPORT: A GENERALIZED PORTAMENTO VIA OPTIMAL TRANSPORT, DaFx - + https://arxiv.org/abs/1906.06763 :control in2: diff --git a/doc/BufAmpFeature.rst b/doc/BufAmpFeature.rst new file mode 100644 index 0000000..b121e70 --- /dev/null +++ b/doc/BufAmpFeature.rst @@ -0,0 +1,67 @@ +:digest: Buffer-Based Amplitude Differential Feature +:species: buffer-proc +:sc-categories: Libraries>FluidDecomposition +:sc-related: Guides/FluidCorpusManipulationToolkit +:see-also: BufAmpSlice, BufNoveltyFeature, BufAmpFeature, BufOnsetFeature +:description: Calculate the amplitude differential feature used by :fluid-obj:`BufAmpSlice`. +:discussion: + :fluid-obj:`BufAmpSlice` uses the differential between a fast and a slow envelope follower to determine changes in amplitude. This object calculates the amplitude differential and copies it to an output buffer. + +:output: Nothing, as the destination buffer is declared in the function call. + + +:control source: + + The index of the buffer to use as the source material to be sliced through novelty identification. The different channels of multichannel buffers will be summed. + +:control startFrame: + + Where in the srcBuf should the slicing process start, in sample. + +:control numFrames: + + How many frames should be processed. + +:control startChan: + + For multichannel sources, which channel should be processed. + +:control numChans: + + For multichannel sources, how many channel should be summed. + +:control features: + + The index of the buffer where the amplitude differential feature will be copied to. + +:control fastRampUp: + + The number of samples the relative envelope follower will take to reach the next value when raising. Typically, this will be faster than slowRampUp. + +:control fastRampDown: + + The number of samples the relative envelope follower will take to reach the next value when falling. Typically, this will be faster than slowRampDown. + +:control slowRampUp: + + The number of samples the absolute envelope follower will take to reach the next value when raising. + +:control slowRampDown: + + The number of samples the absolute envelope follower will take to reach the next value when falling. + +:control floor: + + The level in dB the slowRamp needs to be above to consider a detected difference valid, allowing to ignore the slices in the noise floor. + +:control highPassFreq: + + The frequency of the fourth-order Linkwitz–Riley high-pass filter (https://en.wikipedia.org/wiki/Linkwitz%E2%80%93Riley_filter). This is done first on the signal to minimise low frequency intermodulation with very fast ramp lengths. A frequency of 0 bypasses the filter. + +:control padding: + + Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centering the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. + +:control action: + + 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. \ No newline at end of file diff --git a/doc/BufAudioTransport.rst b/doc/BufAudioTransport.rst index 309a1ca..201c8c9 100644 --- a/doc/BufAudioTransport.rst +++ b/doc/BufAudioTransport.rst @@ -2,13 +2,16 @@ :species: buffer-proc :sc-categories: FluidManipulation :sc-related: Classes/FluidAudioTransport -:see-also: +:see-also: NMFMorph, BufNMFCross :description: - Interpolates between the spectra of two sounds using the Optimal Transport algorithm + Interpolates between the spectra of two sounds using optimal transport - See Henderson and Solomonm (2019) AUDIO TRANSPORT: A GENERALIZED PORTAMENTO VIA OPTIMAL TRANSPORT, DaFx +:discussion: + Interpolates between the spectra of two sounds using the optimal transport algorithm. This enables morphing and hybridisation of the perceptual qualities of each source linearly. + See Henderson and Solomonm (2019) AUDIO TRANSPORT: A GENERALIZED PORTAMENTO VIA OPTIMAL TRANSPORT, DaFx + https://arxiv.org/abs/1906.06763 :control sourceA: diff --git a/doc/BufFlatten.rst b/doc/BufFlatten.rst index 0650f34..bb987e4 100644 --- a/doc/BufFlatten.rst +++ b/doc/BufFlatten.rst @@ -2,11 +2,11 @@ :species: buffer-proc :sc-categories: FluidCorpusManipulation :sc-related: Classes/Buffer -:see-also: +:see-also: BufCompose, BufStats :description: - Flatten a multichannel |buffer| to a single channel. This can be useful for constructing n-dimensional data points for use with :fluid-obj:`DataSet` + Flatten a multichannel |buffer| to a single channel. This can be useful to structure a buffer such that it can be added to a :fluid-obj:`DataSet` - The ``axis`` determines how the flattening is arranged. The default value, 1, flattens channel-wise, such that (if we imagine channels are rows, time positions are columns): + The ``axis`` argument determines how the flattening is arranged. The default value, 1, flattens channel-wise (similar to how audio files are stored), such that (if we imagine channels are rows, time positions are columns): === === === a 1 a 2 a 3 @@ -14,47 +14,44 @@ c 1 c 2 c 3 === === === - becomes === === === === === === === === === a 1 b 1 c 1 a 2 b 2 c 2 a 3 b 3 c 3 === === === === === === === === === - - whereas with ``axis = 0`` we get + whereas with ``axis`` = 0, the buffer is flattened frame-wise, resulting in: === === === === === === === === === a 1 a 2 a 3 b 1 b 2 b 3 c 1 c 2 c 3 === === === === === === === === === - - + + To learn more visit https://learn.flucoma.org/reference/bufflatten/. :control source: - The |buffer| to flatten + The |buffer| to flatten. :control startFrame: - Where in the source should the flattening process start, in samples. + Where in ``source`` should the flattening process start, in samples. The default is 0. :control numFrames: - How many frames should be processed. + How many frames should be processed. The default of -1 indicates to process through the end of the buffer. :control startChan: - For multichannel source buffers, which channel to start processing at. + For multichannel ``source`` buffers, which which channel to begin the processing. The default is 0. :control numChans: - For multichannel source buffers, how many channels should be processed. + For multichannel ``source`` buffers, how many channels should be processed. The default of -1 indicates to process up through the last channel in ``source``. :control destination: - The |buffer| to write the flattened data to + The |buffer| to write the flattened data to. :control axis: - Whether to group points channel-wise or frame-wise - + Whether to flatten the buffer channel-wise (1) or frame-wise (0). The default is 1 (channel-wise). diff --git a/doc/BufMFCC.rst b/doc/BufMFCC.rst index e8e4184..700b721 100644 --- a/doc/BufMFCC.rst +++ b/doc/BufMFCC.rst @@ -4,59 +4,64 @@ :sc-related: Guides/FluidCorpusManipulationToolkit, Guides/FluidBufMultiThreading, Classes/FluidBufMelBands :see-also: :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 **numBands** perceptually-spaced bands, as in Classes/FluidMelBands. It is then analysed into **numCoeffs** number of cepstral coefficients. It has the advantage of being amplitude invariant, except for the first coefficient. It is part of the Guides/FluidCorpusManipulationToolkit of Guides/FluidCorpusManipulationToolkit. For more explanations, learning material, and discussions on its musicianly uses, visit http://www.flucoma.org/ - - The process will return a single multichannel buffer of **numCoeffs** per input channel. Each frame represents a value, which is every hopSize. + + MFCC stands for Mel-Frequency Cepstral Coefficients ("cepstral" is pronounced like "kepstral"). This analysis is often used for timbral description and timbral comparison. It compresses the overall spectrum into a smaller number of coefficients that, when taken together, describe the general contour the the spectrum. + The MFCC values are derived by first computing a mel-frequency spectrum, just as in :fluid-obj:`MelBands`. ``numCoeffs`` coefficients are then calculated by using that mel-frequency spectrum as input to the discrete cosine transform. This means that the shape of the mel-frequency spectrum is compared to a number of cosine wave shapes (different cosines shapes created from different different frequencies). Each MFCC value (i.e., "coefficient") represents how similar the mel-frequency spectrum is to one of these cosine shapes. + Other that the 0th coefficient, MFCCs are unchanged by differences in the overall energy of the spectrum (which relates to how we perceive loudness). This means that timbres with similar spectral contours, but different volumes, will still have similar MFCC values, other than MFCC 0. To remove any indication of loudness but keep the information about timbre, we can ignore MFCC 0 by setting the parameter ``startCoeff`` to 1. + For more information visit https://learn.flucoma.org/reference/mfcc/. + + For an interactive explanation of this relationship, visit https://learn.flucoma.org/reference/mfcc/explain. + :control source: - The index of the buffer to use as the source material to be described through the various descriptors. The different channels of multichannel buffers will be processing sequentially. + The index of the buffer to use as the source material to be analysed. The different channels of multichannel buffers will be processing sequentially. :control startFrame: - Where in the srcBuf should the process start, in sample. + Where in the ``srcBuf`` the analysis should start, in samples. The default is 0. :control numFrames: - How many frames should be processed. + How many frames should be analysed. The default of -1 indicates to analyse to the end of the buffer. :control startChan: - For multichannel srcBuf, which channel should be processed first. + For a multichannel ``srcBuf``, which channel should be processed first. The default is 0. :control numChans: - For multichannel srcBuf, how many channel should be processed. + For a multichannel ``srcBuf``, how many channels should be processed. The default of -1 indicates to analyse through the last channel. :control features: - The destination buffer for the numCoeffs coefficients describing the spectral shape. + The destination buffer to write the MFCC analysis into. :control numCoeffs: - The number of cepstral coefficients to be outputed. It will decide how many channels are produce per channel of the source. + The number of cepstral coefficients to return. The default is 13. :control numBands: - The number of bands that will be perceptually equally distributed between **minFreq** and **maxFreq**. + The number of bands that will be perceptually equally distributed between ``minFreq`` and ``maxFreq``. The default is 40. :control startCoeff: - The lowest index of the output cepstral coefficient, zero-counting. + The lowest index of the output cepstral coefficients to return, zero-counting. This can be useful to skip over the 0th coefficient (by indicating ``startCoeff`` = 1), because the 0th coefficient is representative of the overall energy in spectrum, while the rest of the coefficients are not affected by overall energy, only the mel-frequency spectral contour. The default is 0. :control minFreq: - The lower boundary of the lowest band of the model, in Hz. + The lower bound of the frequency band to use in analysis, in Hz. The default is 20. :control maxFreq: - The highest boundary of the highest band of the model, in Hz. + The upper bound of the frequency band to use in analysis, in Hz. The default is 20000. :control windowSize: - The window size. As MFCC computation 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 + The window size. As MFCC computation 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. The default is 1024. :control hopSize: @@ -68,13 +73,4 @@ :control padding: - Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centering the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. - -:control maxNumCoeffs: - - The maximum number of cepstral coefficients that can be computed. This sets the number of channels of the output, and therefore cannot be modulated. - -:control maxFFTSize: - - How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. - + Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centring the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. diff --git a/doc/BufMelBands.rst b/doc/BufMelBands.rst index 21b33e6..a311be5 100644 --- a/doc/BufMelBands.rst +++ b/doc/BufMelBands.rst @@ -3,65 +3,64 @@ :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit, Classes/FluidBufMFCC :see-also: MelBands, BufPitch, BufLoudness, BufMFCC, BufSpectralShape, BufStats -:description: A spectral shape descriptor where the amplitude is given for a number of equally spread perceptual bands. +:description: Magnitudes for a number of perceptually-evenly spaced bands. :discussion: - The spread is based on the Mel scale (https://en.wikipedia.org/wiki/Mel_scale) which is one of the first attempt to mimic pitch perception scientifically. This implementation allows to select the range and number of bands dynamically. - The process will return a single multichannel buffer of ``numBands`` per input channel. Each frame represents a value, which is every hopSize. + :fluid-obj:`BufMelBands` returns a Mel-Frequency Spectrum comprised of the user-defined ``numBands``. The Mel-Frequency Spectrum is a histogram of FFT bins bundled according their relationship to the Mel scale (https://en.wikipedia.org/wiki/Mel_scale) which represents frequency space logarithmically, mimicking how humans perceive pitch distance. The name "Mel" derives from the word "melody". The Hz-to-Mel conversion used by :fluid-obj:`BufMelBands` is ``mel = 1127.01048 * log(hz / 700.0 + 1.0)``. + + This implementation allows to select the range and number of bands dynamically. The ``numBands`` MelBands will be perceptually equally distributed between ``minFreq`` and ``maxFreq``. - When using a high value for ``numBands``, you may end up with empty channels (filled with zeros) in the MelBands output. This is because there is not enough information in the FFT analysis to properly calculate values for every MelBand. Increasing the ``fftSize`` will ensure you have values for all the MelBands. + When using a high value for ``numBands``, you may end up with empty channels (filled with zeros) in the MelBands output. This is because there is not enough information in the FFT analysis to properly calculate values for every MelBand. Increasing the ``fftSize`` will ensure you have values for all the MelBands. + + Visit https://learn.flucoma.org/reference/melbands to learn more. -:process: This is the method that calls for the spectral shape descriptors to be calculated on a given source buffer. -:output: Nothing, as the destination buffer is declared in the function call. +:process: This is the method that calls for the analysis to be calculated on a given source buffer. +:output: Nothing, as the ``features`` buffer is declared in the function call. :control source: - The index of the buffer to use as the source material to be described through the various descriptors. The different channels of multichannel buffers will be processing sequentially. + The index of the buffer to use as the source material to be analysed. The different channels of multichannel buffers will be processing sequentially. :control startFrame: - Where in the srcBuf should the process start, in sample. + Where in the ``source`` to begin the analysis, in samples. The default is 0. :control numFrames: - How many frames should be processed. + How many frames should be analysed, in samples. The default of -1 indicates to analyse to the end of the buffer. :control startChan: - For multichannel srcBuf, which channel should be processed first. + For a multichannel ``source``, which channel to begin analysis from. The default is 0. :control numChans: - For multichannel srcBuf, how many channel should be processed. + For multichannel ``source``, how many channels should be processed, starting from ``startChan`` and counting up. The default of -1 indicates to analyse through the last channel in the ``source``. :control features: - The destination buffer for the STRONG::numBands:: amplitudes describing the spectral shape. + The buffer to write the MelBands magnitudes into. :control numBands: - The number of bands that will be perceptually equally distributed between STRONG::minFreq:: and STRONG::maxFreq::. It will decide how many channels are produce per channel of the source. + The number of bands that will be returned. This determines how many channels are in the ``features`` buffer (``numBands`` * ``numChans``). The default is 40. :control minFreq: - The lower boundary of the lowest band of the model, in Hz. + The lower bound of the frequency band to use in analysis, in Hz. The default is 20. :control maxFreq: - The highest boundary of the highest band of the model, in Hz. - -:control maxNumBands: - - The maximum number of Mel bands that can be modelled. This sets the number of channels of the output, and therefore cannot be modulated. + The upper bound of the frequency band to use in analysis, in Hz. The default is 20000. :control normalize: - This flag enables the scaling of the output to preserve the energy of the window. It is on (1) by default. + This flag indicates whether to use normalized triangle filters, which account for the number of FFT magnitudes used to calculate the MelBands. When normalization is off (`normalize` = 0) the higher MelBands tend to be disproportionately large because they are summing more FFT magnitudes. The default is to have normalization on (`normalize` = 1). :control scale: - This flag sets the scaling of the output value. It is either linear (0, by default) or in dB (1). + This flag sets the scaling of the output value. It is either linear (0, by default) or in dB (1). :control windowSize: @@ -69,21 +68,16 @@ :control hopSize: - The window hop size. As spectral description relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts. + The window hop size. As this analysis relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts. The -1 default value will default to half of windowSize (overlap of 2). :control 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 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. :control padding: - Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centering the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. - -:control maxFFTSize: - - How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. + Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centring the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. :control action: A Function to be evaluated once the offline process has finished and all Buffer's instance variables have been updated on the client side. The function will be passed [features] as an argument. - diff --git a/doc/BufNoveltyFeature.rst b/doc/BufNoveltyFeature.rst new file mode 100644 index 0000000..08a5e6f --- /dev/null +++ b/doc/BufNoveltyFeature.rst @@ -0,0 +1,101 @@ +:digest: Buffer-Based Novelty Feature +:species: buffer-proc +:sc-categories: Libraries>FluidDecomposition, UGens>Buffer +:sc-related: Guides/FluidCorpusManipulationToolkit +:see-also: BufNoveltySlice, BufNoveltyFeature, BufAmpFeature, BufOnsetFeature +:description: Calculates the novelty feature of audio stored in a buffer. +:discussion: + Calculate novelty of audio stored in a buffer, the feature used by :fluid-obj:`BufNoveltySlice` to perform segmentation. + + Novelty is derived by running a kernel across the diagonal of the similarity matrix. It implements the seminal results published in 'Automatic Audio Segmentation Using a Measure of Audio Novelty' by J Foote. + + The process will return a buffer containing a time series that describes the novelty feature changing over time in the source buffer. + +:process: This is the method that calls for the slicing to be calculated on a given source buffer. +:output: Nothing, as the various destination buffers are declared in the function call. + +:control source: + + The index of the buffer to use as the source material to be sliced through novelty identification. The different channels of multichannel buffers will be summed. + +:control startFrame: + + Where in the srcBuf should the slicing process start, in sample. + +:control numFrames: + + How many frames should be processed. + +:control startChan: + + For multichannel srcBuf, which channel should be processed. + +:control numChans: + + For multichannel srcBuf, how many channel should be summed. + +:control features: + + The index of the buffer where the novelty feature will be written. + +:control algorithm: + + The feature on which novelty is computed. + + :enum: + + :0: + Spectrum – The magnitude of the full spectrum. + + :1: + MFCC – 13 Mel-Frequency Cepstrum Coefficients. + + :2: + Chroma - The contour of a 12-band chromagram. + + :3: + Pitch – The pitch and its confidence. + + :4: + Loudness – The true peak and loudness. + +:control kernelSize: + + The granularity of the window in which the algorithm looks for change, in samples. A small number will be sensitive to short term changes, and a large number should look for long term changes. + +:control filterSize: + + The size of a smoothing filter that is applied on the novelty curve. A larger filter filter size allows for cleaner cuts on very sharp changes. + +:control windowSize: + + The window size. As novelty estimation relies on spectral frames, we need to decide what precision we give it spectrally and temporally. + +:control hopSize: + + The window hop size. As novelty estimation relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts. + +:control 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. + +:control maxFFTSize: + + How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. + +:control maxKernelSize: + + This cannot be modulated. + +:control maxFilterSize: + + This cannot be modulated. + +:control padding: + + Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centering the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. + +:control action: + + 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. + diff --git a/doc/BufNoveltySlice.rst b/doc/BufNoveltySlice.rst index 9e41e25..eca824b 100644 --- a/doc/BufNoveltySlice.rst +++ b/doc/BufNoveltySlice.rst @@ -37,7 +37,7 @@ The index of the buffer where the indices (in sample) of the estimated starting points of slices will be written. The first and last points are always the boundary points of the analysis. -:control feature: +:control algorithm: The feature on which novelty is computed. diff --git a/doc/BufOnsetFeature.rst b/doc/BufOnsetFeature.rst new file mode 100644 index 0000000..9ed4e2a --- /dev/null +++ b/doc/BufOnsetFeature.rst @@ -0,0 +1,106 @@ +:digest: Buffer-Based Spectral Difference Feature +:species: buffer-proc +:sc-categories: Libraries>FluidDecomposition +:sc-related: Guides/FluidCorpusManipulationToolkit +:see-also: BufOnsetSlice, BufNoveltyFeature, BufAmpFeature, BufOnsetFeature +:description: Calculate the spectral difference feature used by :fluid-obj:`BufOnsetSlice`. +:discussion: + Given a source buffer, calculates the feature used by :fluid-obj:`BufOnsetSlice` and copies it to another buffer. + + The metric for calculating difference can be chosen from a curated selection, lending the algorithm toward slicing a broad range of musical materials. + +:process: This is the method that calls for the slicing to be calculated on a given source buffer. +:output: Nothing, as the various destination buffers are declared in the function call. + +:control source: + + The index of the buffer to use as the source material to be sliced through novelty identification. The different channels of multichannel buffers will be summed. + +:control startFrame: + + Where in the srcBuf should the slicing process start, in sample. + +:control numFrames: + + How many frames should be processed. + +:control startChan: + + For multichannel sources, which channel should be processed. + +:control numChans: + + For multichannel sources, how many channel should be summed. + +:control features: + + The index of the buffer where the onset features will be written to. + +:control metric: + + The metric used to derive a difference curve between spectral frames. It can be any of the following: + + :enum: + + :0: + **Energy** thresholds on (sum of squares of magnitudes / nBins) (like Onsets \power) + + :1: + **HFC** thresholds on (sum of (squared magnitudes * binNum) / nBins) + + :2: + **SpectralFlux** thresholds on (diffence in magnitude between consecutive frames, half rectified) + + :3: + **MKL** thresholds on (sum of log of magnitude ratio per bin) (or equivalently, sum of difference of the log magnitude per bin) (like Onsets mkl) + + :4: + **IS** (WILL PROBABLY BE REMOVED) Itakura - Saito divergence (see literature) + + :5: + **Cosine** thresholds on (cosine distance between comparison frames) + + :6: + **PhaseDev** takes the past 2 frames, projects to the current, as anticipated if it was a steady state, then compute the sum of the differences, on which it thresholds (like Onsets \phase) + + :7: + **WPhaseDev** same as PhaseDev, but weighted by the magnitude in order to remove chaos noise floor (like Onsets \wphase) + + :8: + **ComplexDev** same as PhaseDev, but in the complex domain - the anticipated amp is considered steady, and the phase is projected, then a complex subtraction is done with the actual present frame. The sum of magnitudes is used to threshold (like Onsets \complex) + + :9: + **RComplexDev** same as above, but rectified (like Onsets \rcomplex) + +:control filterSize: + + The size of a smoothing filter that is applied on the novelty curve. A larger filter filter size allows for cleaner cuts on very sharp changes. + +:control frameDelta: + + For certain metrics (HFC, SpectralFlux, MKL, Cosine), the distance does not have to be computed between consecutive frames. By default (0) it is, otherwise this sets the distane between the comparison window in samples. + +:control windowSize: + + The window size. As spectral differencing 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 + +:control hopSize: + + The window hop size. As spectral differencing relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts. The -1 default value will default to half of windowSize (overlap of 2). + +:control 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. + +:control maxFFTSize: + + How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. + +:control padding: + + Controls the zero-padding added to either end of the source buffer or segment. Possible values are 0 (no padding), 1 (default, half the window size), or 2 (window size - hop size). Padding ensures that all input samples are completely analysed: with no padding, the first analysis window starts at time 0, and the samples at either end will be tapered by the STFT windowing function. Mode 1 has the effect of centering the first sample in the analysis window and ensuring that the very start and end of the segment are accounted for in the analysis. Mode 2 can be useful when the overlap factor (window size / hop size) is greater than 2, to ensure that the input samples at either end of the segment are covered by the same number of analysis frames as the rest of the analysed material. + +:control action: + + 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. + diff --git a/doc/BufOnsetSlice.rst b/doc/BufOnsetSlice.rst index c01f914..aa63a08 100644 --- a/doc/BufOnsetSlice.rst +++ b/doc/BufOnsetSlice.rst @@ -3,16 +3,15 @@ :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit :see-also: OnsetSlice, BufAmpSlice, BufNoveltySlice, BufTransientSlice -:description: Implements many spectral-based onset detection metrics, most of them taken from the literature. -:discussion: - For an overview of onset detection metrics see (http://www.dafx.ca/proceedings/papers/p_133.pdf). Some are already available in SuperCollider's Onsets object, yet not as offline processes. - - The process will return a buffer which contains indices (in sample) of estimated starting points of different slices. +:description: Implements a selection of spectrum-based onset slicers +:discussion: + Performs segmentation based on the difference between spectral frames. + + The metric for calculating difference can be chosen from a curated selection, lending the algorithm toward slicing a broad range of musical materials. :process: This is the method that calls for the slicing to be calculated on a given source buffer. :output: Nothing, as the various destination buffers are declared in the function call. - :control source: The index of the buffer to use as the source material to be sliced through novelty identification. The different channels of multichannel buffers will be summed. diff --git a/doc/BufPitch.rst b/doc/BufPitch.rst index 2261376..78c9c74 100644 --- a/doc/BufPitch.rst +++ b/doc/BufPitch.rst @@ -1,13 +1,24 @@ -:digest: A Selection of Pitch Descriptors on a Buffer +:digest: Pitch Descriptor :species: buffer-proc :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit, Classes/SpecCentroid, Classes/SpecFlatness, Classes/SpecCentroid, Classes/SpecPcile :see-also: Pitch, BufLoudness, BufMelBands, BufMFCC, BufSpectralShape, BufStats -:description: Implements three pitch descriptors, computed as frequency and the confidence in its value. -:discussion: The process will return a multichannel buffer with two channels per input channel, one for pitch and one for the pitch tracking confidence. A pitch of 0 Hz is yield (or -999.0 when the unit is in MIDI note) when the algorithm cannot find a fundamental at all. Each sample represents a value, which is every hopSize. Its sampling rate is sourceSR / hopSize. -:process: This is the method that calls for the pitch descriptor to be calculated on a given source buffer. -:output: Nothing, as the destination buffer is declared in the function call. +:description: Three popular pitch descriptors, all of which compute frequency and the confidence that a pitch is present. +:discussion: + + :fluid-obj:`Pitch` returns both ``pitch`` and ``confidence`` values. When no pitch can be detected, a pitch of 0 Hz is returned (or -999.0 when the unit is in MIDI note mode). + + For information about the pitch descriptor algorithms, see the ``algorithm`` parameter below. + + The "confidence" output is a value between 0 and 1 indicating how confident the algorithm is in the pitch that it is reporting. In effect this can be an estimation of how "noisy" (closer to 0) or "harmonic" (closer to 1) the spectrum is. The confidence may also be low when a signal contains polyphony, as the algorithms are not intended for multiple pitch streams. + + The ``unit`` argument indicates whether the pitch output should be in hertz (indicated by 0) or MIDI note numbers (indicated by 1). MIDI note numbers may be useful, not only because of their direct relationship to MIDI-based synthesis systems, but also because of the logarithmic relationship to hertz, making them perceptually evenly-spaced units (1 MIDI note = 1 semitone). + For more information visit https://learn.flucoma.org/reference/pitch/. + +:process: This is the method that calls for the descriptor to be calculated on a given source buffer. + +:output: Nothing, as the destination buffer is declared in the function call. :control source: @@ -15,23 +26,23 @@ :control startFrame: - Where in the srcBuf should the process start, in sample. + Where in ``source`` to start the analysis, in samples. The default is 0. :control numFrames: - How many frames should be processed. + How many samples to analyse. The default of -1 indicates to analyse through to the end of the buffer. :control startChan: - For multichannel srcBuf, which channel should be processed first. + For multichannel ``source``, from which channel to begin analysing. The default is 0. :control numChans: - For multichannel srcBuf, how many channel should be processed. + For multichannel ``source``, how many channel should be processed. The default of -1 indicates to analyse through the last channel in the buffer. :control features: - The destination buffer for the pitch descriptors. + The destination buffer for the descriptors. :control algorithm: @@ -50,11 +61,11 @@ :control minFreq: - The minimum frequency that the algorithm will search for an estimated fundamental. This sets the lowest value that will be generated. + The minimum frequency that the algorithm will search for an estimated fundamental. This sets the lowest value that will be generated. The default is 20. :control maxFreq: - The maximum frequency that the algorithm will search for an estimated fundamental. This sets the highest value that will be generated. + The maximum frequency that the algorithm will search for an estimated fundamental. This sets the highest value that will be generated. The default is 10000. :control unit: @@ -83,4 +94,3 @@ :control action: A Function to be evaluated once the offline process has finished and all Buffer's instance variables have been updated on the client side. The function will be passed [features] as an argument. - diff --git a/doc/BufThresh.rst b/doc/BufThresh.rst index ec06345..1036c52 100644 --- a/doc/BufThresh.rst +++ b/doc/BufThresh.rst @@ -2,39 +2,35 @@ :species: buffer-proc :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit, Guides/FluidBufMultiThreading -:see-also: +:see-also: BufCompose, Gain, Stats :description: - This class implements a simple Buffer preprocessor, by replacing values under a threshold by 0s. It is part of the :fluid-topic:`CorpusManipulationToolkit`. For more explanations, learning material, and discussions on its musicianly uses, visit http://www.flucoma.org/ - - The process will return a buffer with the same size and shape than the requested range. - + Replace all values of a buffer under the given threshold with 0 and copy the result to a destination buffer. :control source: - The index of the buffer to use as the source material to be processed. + The buffer to process containing the values to compare against the threshold. :control startFrame: - The starting point (in samples) from which to copy in the source buffer. + The starting point (in samples) from which to process the ``source``. :control numFrames: - The duration (in samples) to copy from the source buffer. The default (-1) copies the full lenght of the buffer. + The duration (in samples) to process in the ``source``. The default (-1) indicates to process through the end of ``source``. :control startChan: - The first channel from which to copy in the source buffer. + The channel from which to begin the process in the ``source``. :control numChans: - The number of channels from which to copy in the source buffer. This parameter will wrap around the number of channels in the source buffer. The default (-1) copies all of the buffer's channel. + The number of channels to process in ``source``. The default of -1 indicates to process through the last channel in ``source``. :control destination: - The index of the buffer to use as the destination for the processed material. + The buffer to write the processed data into. :control threshold: - The threshold under which values will be zeroed - + Any values in ``source`` below this threshold will be written as 0 in ``destination``. diff --git a/doc/MFCC.rst b/doc/MFCC.rst index 8cdee16..e36579a 100644 --- a/doc/MFCC.rst +++ b/doc/MFCC.rst @@ -5,12 +5,25 @@ :see-also: BufMFCC, Pitch, MelBands, Loudness, SpectralShape :description: This class implements a classic spectral descriptor, the Mel-Frequency Cepstral Coefficients (MFCCs) :discussion: - See https://en.wikipedia.org/wiki/Mel-frequency_cepstrum. The input is first decomposed into perceptually spaced bands (the number of bands specified by numBands), just as in the MelBands object. It is then analysed in numCoefs number of cepstral coefficients. It has the avantage to be amplitude invarient, except for the first coefficient. - The process will return a multichannel control steam of maxNumCoeffs, which will be repeated if no change happens within the algorithm, i.e. when the hopSize is larger than the host vector size. + MFCC stands for Mel-Frequency Cepstral Coefficients ("cepstral" is pronounced like "kepstral"). This analysis is often used for timbral description and timbral comparison. It compresses the overall spectrum into a smaller number of coefficients that, when taken together, describe the general contour the the spectrum. + + The MFCC values are derived by first computing a mel-frequency spectrum, just as in :fluid-obj:`MelBands`. ``numCoeffs`` coefficients are then calculated by using that mel-frequency spectrum as input to the discrete cosine transform. This means that the shape of the mel-frequency spectrum is compared to a number of cosine wave shapes (different cosines shapes created from different different frequencies). Each MFCC value (i.e., "coefficient") represents how similar the mel-frequency spectrum is to one of these cosine shapes. + + Other that the 0th coefficient, MFCCs are unchanged by differences in the overall energy of the spectrum (which relates to how we perceive loudness). This means that timbres with similar spectral contours, but different volumes, will still have similar MFCC values, other than MFCC 0. To remove any indication of loudness but keep the information about timbre, we can ignore MFCC 0 by setting the parameter ``startCoeff`` to 1. + + .. only_in:: sc + + When ``numCoeffs`` is less than ``maxNumCoeffs`` the result will be zero-padded on the right so the control stream returned by this object is always ``maxNumCoeffs`` channels. + + For more information visit https://learn.flucoma.org/reference/mfcc/. + + For an interactive explanation of this relationship, visit https://learn.flucoma.org/reference/mfcc/explain. :process: The audio rate in, control rate out version of the object. -:output: A KR signal of STRONG::maxNumCoefs:: channels. The latency is windowSize. +:output: + + The process will return a stream of ``maxNumCoeffs`` MFCCs, which will be repeated if no change happens within the algorithm, i.e. when the hopSize is larger than the host vector size. When ``numCoeffs`` is less than ``maxNumCoeffs`` the result will be zero-padded on the right so the control stream returned by this object is always ``maxNumCoeffs`` channels. Latency is ``windowSize`` samples. :control in: @@ -19,23 +32,23 @@ :control numCoeffs: - The number of cepstral coefficients to be outputed. It is limited by the maxNumCoefs parameter. When the number is smaller than the maximum, the output is zero-padded. + The number of cepstral coefficients to output. It is limited by the ``maxNumCoeffs`` parameter. When the number is smaller than the maximum, the output is zero-padded. :control numBands: - The number of bands that will be perceptually equally distributed between minFreq and maxFreq to describe the spectral shape before it is converted to cepstral coefficients. + The number of mel-bands that will be perceptually equally distributed between ``minFreq`` and ``maxFreq`` to describe the spectral shape before the cepstral coefficients are computed. :control startCoeff: - The lowest index of the output cepstral coefficient, zero-counting. + The lowest index of the output cepstral coefficients to return, zero-counting. This can be useful to skip over the 0th coefficient (by indicating ``startCoeff`` = 1), because the 0th coefficient is representative of the overall energy in spectrum, while the rest of the coefficients are not affected by overall energy, only the mel-frequency spectral contour. :control minFreq: - The lower boundary of the lowest band of the model, in Hz. + The lower bound of the frequency band to use in analysis, in Hz. :control maxFreq: - The highest boundary of the highest band of the model, in Hz. + The upper bound of the frequency band to use in analysis, in Hz. :control maxNumCoeffs: @@ -56,4 +69,3 @@ :control maxFFTSize: How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. - diff --git a/doc/MelBands.rst b/doc/MelBands.rst index 1815800..5ae8d0b 100644 --- a/doc/MelBands.rst +++ b/doc/MelBands.rst @@ -1,19 +1,19 @@ -:digest: A Perceptually Spread Spectral Contour Descriptor in Real-Time +:digest: A Perceptually Spread Spectral Contour Descriptor :species: descriptor :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit, Classes/FluidMFCC :see-also: BufMelBands, Pitch, Loudness, MFCC, SpectralShape -:description: Amplitude for a number of equally spread perceptual bands. +:description: Magnitudes for a number of perceptually-evenly spaced bands. :discussion: - The spread is based on the Mel scale (https://en.wikipedia.org/wiki/Mel_scale) which was one of the first attempts to mimic pitch perception scientifically. This implementation allows to select the range and number of bands dynamically. - The process will return a multichannel control steam of size maxNumBands, which will be repeated if no change happens within the algorithm, i.e. when the hopSize is larger than the signal vector size. + :fluid-obj:`MelBands` returns a Mel-Frequency Spectrum comprised of the user-defined ``numBands``. The Mel-Frequency Spectrum is a histogram of FFT bins bundled according their relationship to the Mel scale (https://en.wikipedia.org/wiki/Mel_scale) which represents frequency space logarithmically, mimicking how humans perceive pitch distance. The name "Mel" derives from the word "melody". The Hz-to-Mel conversion used by :fluid-obj:`MelBands` is ``mel = 1127.01048 * log(hz / 700.0 + 1.0)``. This implementation allows to select the range and number of bands dynamically. When using a high value for ``numBands``, you may end up with empty channels (filled with zeros) in the MelBands output. This is because there is not enough information in the FFT analysis to properly calculate values for every MelBand. Increasing the ``fftSize`` will ensure you have values for all the MelBands. + Visit https://learn.flucoma.org/reference/melbands to learn more. + :process: The audio rate in, control rate out version of the object. -:output: A KR signal of maxNumBands channels, giving the measure amplitudes for each band. The latency is windowSize. - +:output: A KR signal of ``maxNumBands channels``, giving the measured magnitudes for each band. The latency is windowSize. :control in: @@ -21,23 +21,23 @@ :control numBands: - The number of bands that will be perceptually equally distributed between minFreq and maxFreq. It is limited by the maxNumBands parameter. When the number is smaller than the maximum, the output is zero-padded. + The number of bands that will be perceptually equally distributed between ``minFreq`` and ``maxFreq``. It is limited by the maxNumBands parameter. When the number is smaller than the maximum, the output is zero-padded. :control minFreq: - The lower boundary of the lowest band of the model, in Hz. + The lower bound of the frequency band to use in analysis, in Hz. The default is 20. :control maxFreq: - The highest boundary of the highest band of the model, in Hz. + The upper bound of the frequency band to use in analysis, in Hz. The default is 20000. :control maxNumBands: - The maximum number of Mel bands that can be modelled. This sets the number of channels of the output, and therefore cannot be modulated. + The maximum number of Mel bands that can be modelled. This sets the number of channels of the output, and therefore cannot be modulated. The default is 120. :control normalize: - This flag enables the scaling of the output to preserve the energy of the window. It is on (1) by default. + This flag indicates whether to use normalized triangle filters, which account for the number of FFT magnitudes used to calculate the MelBands. When normalization is off (`normalize` = 0) the higher MelBands tend to be disproportionately large because they are summing more FFT magnitudes. The default is to have normalization on (`normalize` = 1). :control scale: @@ -57,5 +57,4 @@ :control maxFFTSize: - How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. - + How large the FFT can be, by allocating memory at instantiation time. This cannot be modulated. diff --git a/doc/Normalize.rst b/doc/Normalize.rst index 8838807..f090ef7 100644 --- a/doc/Normalize.rst +++ b/doc/Normalize.rst @@ -2,9 +2,8 @@ :species: data :sc-categories: FluidManipulation :sc-related: Classes/FluidStandardize, Classes/FluidDataSet -:see-also: -:description: Normalize the entries of a :fluid-obj:`DataSet`, or normalize a data point according to the learned bounds of a data set. - +:see-also: Standardize, RobustScale +:description: Normalize a :fluid-obj:`DataSet` or single point of data according to learnt minimum and maximum values. :control min: @@ -23,7 +22,7 @@ :arg dataSet: The :fluid-obj:`DataSet` to normalize - Compute the normalization factors from a :fluid-obj:`DataSet` for later. + Compute the normalization factors from a :fluid-obj:`DataSet` and store them internally. :message transform: @@ -31,7 +30,7 @@ :arg destDataSet: The :fluid-obj:`DataSet` to populate with normalized data - Normalize a :fluid-obj:`DataSet` into another :fluid-obj:`DataSet`, using the learned extrema from a previous call to :fluid-obj:`Normalize#fit` + Transform a :fluid-obj:`DataSet` using learned extrema from :fluid-obj:`Normalize#fit` and copy the results to the destination :fluid-obj:`DataSet`. :message fitTransform: @@ -39,7 +38,7 @@ :arg destDataSet: The :fluid-obj:`DataSet` to populate with normalized data - Normalize a :fluid-obj:`DataSet` + Normalize a :fluid-obj:`DataSet` and copy the results to :fluid-obj:`DataSet`. :message transformPoint: @@ -47,4 +46,4 @@ :arg destBuffer: A |buffer| to contain the normalized value - Normalize a new data point, using the learned extrema from a previous call to :fluid-obj:`Normalize#fit` + Normalize a single data point, using the learned extrema from a previous call to :fluid-obj:`Normalize#fit` diff --git a/doc/NoveltyFeature.rst b/doc/NoveltyFeature.rst new file mode 100644 index 0000000..88f449c --- /dev/null +++ b/doc/NoveltyFeature.rst @@ -0,0 +1,66 @@ +:digest: Realtime Novelty Feature +:species: descriptor +:sc-categories: Libraries>FluidDecomposition, UGens>Buffer +:sc-related: Guides/FluidCorpusManipulationToolkit +:see-also: NoveltySlice, AmpFeature, OnsetFeature +:description: Calculates the novelty feature of audio in realtime. +:discussion: + Calculate novelty in realtime, the feature used by :fluid-obj:`NoveltySlice` to perform segmentation. + + Novelty derived by running a kernel across the diagonal of the similarity matrix. It implements the seminal results published in 'Automatic Audio Segmentation Using a Measure of Audio Novelty' by J Foote. + +:process: The audio rate version of the object. +:output: A KR signal of the feature. + +:control algorithm: + + The feature on which novelty is computed. + + :enum: + + :0: + Spectrum – The magnitude of the full spectrum. + + :1: + MFCC – 13 Mel-Frequency Cepstrum Coefficients. + + :2: + Chroma - The contour of a 12-band chromagram. + + :3: + Pitch – The pitch and its confidence. + + :4: + Loudness – The true peak and loudness. + +:control kernelSize: + + The granularity of the window in which the algorithm looks for change, in samples. A small number will be sensitive to short term changes, and a large number should look for long term changes. + +:control filterSize: + + The size of a smoothing filter that is applied on the novelty curve. A larger filter filter size allows for cleaner cuts on very sharp changes. + +:control windowSize: + + The window size. As novelty estimation relies on spectral frames, we need to decide what precision we give it spectrally and temporally. + +:control hopSize: + + The window hop size. As novelty estimation relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts. + +:control 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. + +:control maxFFTSize: + + How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. + +:control maxKernelSize: + + This cannot be modulated. + +:control maxFilterSize: + + This cannot be modulated. \ No newline at end of file diff --git a/doc/NoveltySlice.rst b/doc/NoveltySlice.rst index c8cd84a..7faef63 100644 --- a/doc/NoveltySlice.rst +++ b/doc/NoveltySlice.rst @@ -16,7 +16,7 @@ The audio to be processed. -:control feature: +:control algorithm: The feature on which novelty is computed. diff --git a/doc/OnsetFeature.rst b/doc/OnsetFeature.rst new file mode 100644 index 0000000..30647f6 --- /dev/null +++ b/doc/OnsetFeature.rst @@ -0,0 +1,73 @@ +:digest: Realtime Spectral Difference Feature +:species: descriptor +:sc-categories: Libraries>FluidDecomposition +:sc-related: Guides/FluidCorpusManipulationToolkit +:see-also: OnsetSlice, NoveltyFeature, AmpFeature +:description: Calculate the spectral difference feature used by :fluid-obj:`OnsetSlice`. +:discussion: + Calculates the feature used by :fluid-obj:`OnsetSlice` for slicing in realtime. + + The metric for calculating difference can be chosen from a curated selection, lending the algorithm toward slicing a broad range of musical materials. + +:process: The audio rate version of the object. +:output: A KR signal of the feature. + +:control metric: + + The metric used to derive a difference curve between spectral frames. It can be any of the following: + + :enum: + + :0: + **Energy** thresholds on (sum of squares of magnitudes / nBins) (like Onsets \power) + + :1: + **HFC** thresholds on (sum of (squared magnitudes * binNum) / nBins) + + :2: + **SpectralFlux** thresholds on (diffence in magnitude between consecutive frames, half rectified) + + :3: + **MKL** thresholds on (sum of log of magnitude ratio per bin) (or equivalently, sum of difference of the log magnitude per bin) (like Onsets mkl) + + :4: + **IS** (WILL PROBABLY BE REMOVED) Itakura - Saito divergence (see literature) + + :5: + **Cosine** thresholds on (cosine distance between comparison frames) + + :6: + **PhaseDev** takes the past 2 frames, projects to the current, as anticipated if it was a steady state, then compute the sum of the differences, on which it thresholds (like Onsets \phase) + + :7: + **WPhaseDev** same as PhaseDev, but weighted by the magnitude in order to remove chaos noise floor (like Onsets \wphase) + + :8: + **ComplexDev** same as PhaseDev, but in the complex domain - the anticipated amp is considered steady, and the phase is projected, then a complex subtraction is done with the actual present frame. The sum of magnitudes is used to threshold (like Onsets \complex) + + :9: + **RComplexDev** same as above, but rectified (like Onsets \rcomplex) + +:control filterSize: + + The size of a smoothing filter that is applied on the novelty curve. A larger filter filter size allows for cleaner cuts on very sharp changes. + +:control frameDelta: + + For certain metrics (HFC, SpectralFlux, MKL, Cosine), the distance does not have to be computed between consecutive frames. By default (0) it is, otherwise this sets the distane between the comparison window in samples. + +:control windowSize: + + The window size. As spectral differencing 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 + +:control hopSize: + + The window hop size. As spectral differencing relies on spectral frames, we need to move the window forward. It can be any size but low overlap will create audible artefacts. The -1 default value will default to half of windowSize (overlap of 2). + +:control 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. + +:control maxFFTSize: + + How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. \ No newline at end of file diff --git a/doc/OnsetSlice.rst b/doc/OnsetSlice.rst index 068475d..57fdee9 100644 --- a/doc/OnsetSlice.rst +++ b/doc/OnsetSlice.rst @@ -3,11 +3,11 @@ :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit :see-also: BufOnsetSlice, AmpSlice, NoveltySlice, TransientSlice -:description: Real-time onset detection against a choice of metrics -:discussion: - See http://www.dafx.ca/proceedings/papers/p_133.pdf for an overview of onset detection metrics. Some are already available in SuperCollider's Onsets object. - - The process will return an audio steam with sample-long impulses at estimated starting points of the different slices. +:description: Implements a selection of spectrum-based onset slicers +:discussion: + Performs segmentation based on the difference between spectral frames. + + The metric for calculating difference can be chosen from a curated selection, lending the algorithm toward slicing a broad range of musical materials. :process: The audio rate version of the object. :output: An audio stream with impulses at detected transients. The latency between the input and the output is windowSize at maximum. diff --git a/doc/Pitch.rst b/doc/Pitch.rst index 795ee07..3ab502c 100644 --- a/doc/Pitch.rst +++ b/doc/Pitch.rst @@ -1,13 +1,24 @@ -:digest: A Selection of Pitch Descriptors in Real-Time +:digest: Real-time Pitch Descriptor :species: descriptor :sc-categories: Libraries>FluidDecomposition :sc-related: Guides/FluidCorpusManipulationToolkit, Classes/Pitch :see-also: BufPitch, MFCC, MelBands, Loudness, SpectralShape -:description: Three popular pitch descriptors, computed as frequency and the confidence in its value. -:discussion: The process will return a multichannel control steam with [pitch, confidence] values, which will be repeated if no change happens within the algorithm, i.e. when the hopSize is larger than the signal vector size. A pitch of 0 Hz is yield (or -999.0 when the unit is in MIDI note) when the algorithm cannot find a fundamental at all. +:description: Three popular monophonic pitch descriptors, all of which compute frequency and confidence. +:discussion: + + :fluid-obj:`Pitch` returns both ``pitch`` and ``confidence`` values. When no pitch can be detected, a pitch of 0 Hz is returned (or -999.0 when the unit is in MIDI note mode). + + For information about the pitch descriptor algorithms, see the ``algorithm`` parameter below. + + The "confidence" output is a value between 0 and 1 indicating how confident the algorithm is in the pitch that it is reporting. In effect this can be an estimation of how "noisy" (closer to 0) or "harmonic" (closer to 1) the spectrum is. The confidence may also be low when a signal contains polyphony, as the algorithms are not intended for multiple pitch streams. + + The ``unit`` argument indicates whether the pitch output should be in hertz (indicated by 0) or MIDI note numbers (indicated by 1). MIDI note numbers may be useful, not only because of their direct relationship to MIDI-based synthesis systems, but also because of the logarithmic relationship to hertz, making them perceptually evenly-spaced units (1 MIDI note = 1 semitone). + + For more information visit https://learn.flucoma.org/reference/pitch/. + :process: The audio rate in, control rate out version of the object. -:output: A 2-channel KR signal with the [pitch, confidence] descriptors. The latency is windowSize. +:output: The two descriptors: [pitch, confidence]. The latency is windowSize. :control in: @@ -15,12 +26,12 @@ :control algorithm: - The algorithm to estimate the pitch. The options are: + The algorithm to estimate the pitch. (The default is 2.) The options are: :enum: :0: - Cepstrum: Returns a pitch estimate as the location of the second highest peak in the Cepstrum of the signal (after DC). + Cepstrum: Returns a pitch estimate as the location of the highest peak (not including DC) in the Cepstrum of the signal. :1: Harmonic Product Spectrum: Implements the Harmonic Product Spectrum algorithm for pitch detection . See e.g. A. Lerch, "An Introduction to Audio Content Analysis: Applications in Signal Processing and Music Informatics." John Wiley & Sons, 2012.https://onlinelibrary.wiley.com/doi/book/10.1002/9781118393550 @@ -30,15 +41,15 @@ :control minFreq: - The minimum frequency that the algorithm will search for an estimated fundamental. This sets the lowest value that will be generated. + The minimum frequency that the algorithm will search for. This sets the lowest value that can be generated. The default is 20. :control maxFreq: - The maximum frequency that the algorithm will search for an estimated fundamental. This sets the highest value that will be generated. + The maximum frequency that the algorithm will search for. This sets the highest value that can be generated. The default is 10000. :control unit: - The unit of the estimated value. The default of 0 is in Hz. A value of 1 will convert to MIDI note values. + The unit of the pitch output. The default of 0 indicates to output in Hz. A value of 1 will output MIDI note values. :control windowSize: @@ -55,4 +66,3 @@ :control maxFFTSize: How large can the FFT be, by allocating memory at instantiation time. This cannot be modulated. - diff --git a/doc/UMAP.rst b/doc/UMAP.rst index e49de94..2228024 100644 --- a/doc/UMAP.rst +++ b/doc/UMAP.rst @@ -3,7 +3,7 @@ :sc-categories: Dimensionality Reduction, Data Processing :sc-related: Classes/FluidMDS, Classes/FluidDataSet :see-also: -:description: Reduce the dimensions of a :fluid-obj:`DataSet` using the Uniform Manifold Approximation and Project (UMAP) algorithm. +:description: Reduce the dimensions of a :fluid-obj:`DataSet` using the Uniform Manifold Approximation and Projection (UMAP) algorithm. :discussion: Performs dimensionality reduction of a :fluid-obj:`DataSet` using Uniform Manifold Approximation and Projection (UMAP) diff --git a/example-code/sc/AmpFeature.scd b/example-code/sc/AmpFeature.scd new file mode 100644 index 0000000..e2ac382 --- /dev/null +++ b/example-code/sc/AmpFeature.scd @@ -0,0 +1,51 @@ +strong::Use the output as a stream of decibels to manipulate another (or the same) audio signal:: +code:: +~drums = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); + +// listen to the original +~drums.play; + +// add extra pop to the drums by using the AmpFeature envelope +( +{ + var sig = PlayBuf.ar(~drums.numChannels,~drums,BufRateScale.ir(~drums),loop:1); + var amp_feature = FluidAmpFeature.ar(sig,100,100,44100,44100,-40); + amp_feature.poll; + sig * amp_feature.dbamp * -30.dbamp; +}.play; +) + +// really suppress the amplitude peaks by inverting the feature +( +{ + var sig = PlayBuf.ar(~drums.numChannels,~drums,BufRateScale.ir(~drums),loop:1); + var amp_feature = FluidAmpFeature.ar(sig,100,100,44100,44100,-40) * -1; + amp_feature.poll; + sig * amp_feature.dbamp +}.play; +) + +:: +strong::Make your own threshold, similar to how FluidAmpSlice works:: +code:: + +~src = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); + +// listen to the original +~src.play; + +( +{ + var sig = PlayBuf.ar(~src.numChannels,~src,BufRateScale.ir(~src),loop:1); + var amp_feature = FluidAmpFeature.ar(sig,100,100,44100,44100,-40); + var trig = Schmidt.ar(amp_feature,0,6); + SendReply.ar(trig,"/amp_onset"); + sig; +}.play; + +OSCdef(\amp_onset,{ + arg msg; + "onset".postln; +},"/amp_onset"); +) +:: \ No newline at end of file diff --git a/example-code/sc/BufAmpFeature.scd b/example-code/sc/BufAmpFeature.scd new file mode 100644 index 0000000..02d890b --- /dev/null +++ b/example-code/sc/BufAmpFeature.scd @@ -0,0 +1,13 @@ +strong::Plot the BufAmpFeature curve along with the indices from BufAmpSlice:: +code:: +~drums = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); + +( +~indices = Buffer(s); +~feature = Buffer(s); +FluidBufAmpSlice.processBlocking(s,~drums,indices:~indices,fastRampUp:100,fastRampDown:100,slowRampUp:4410,slowRampDown:4410,onThreshold:10,offThreshold:0,floor:-40); +FluidBufAmpFeature.processBlocking(s,~drums,features:~feature,fastRampUp:10,fastRampDown:10,slowRampUp:4410,slowRampDown:4410,floor:-60); +FluidWaveform(~drums,~indices,~feature,bounds:Rect(0,0,1600,400)); +) + +:: \ No newline at end of file diff --git a/example-code/sc/BufFlatten.scd b/example-code/sc/BufFlatten.scd index d1cfca5..117e870 100644 --- a/example-code/sc/BufFlatten.scd +++ b/example-code/sc/BufFlatten.scd @@ -1,22 +1,74 @@ - +strong::Using FluidBufFlatten for adding points to a FluidDataSet:: code:: -//FluidBufPitch is useful to illustrate the effect of this, because the pitch and confidence values are easily distinguishable ( -~path = FluidFilesPath(); -~randomsoundfile = SoundFile.collect(~path +/+ '*').choose; -b = Buffer.read(s,~randomsoundfile.path,action:{"Sound Loaded".postln}); -~pitchdata = Buffer.new; -~flatdata = Buffer.new; +~buf = Buffer.readChannel(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"),channels:[0]); +~chromabuf = Buffer(s); // buffer for storing chroma analysis +~statsbuf = Buffer(s); // buffer for storing statistical analysis of chroma analysis +~flatbuf = Buffer(s); // buffer for storing the flattened data of the mean chroma values +~chroma_ds = FluidDataSet(s); // dataset for writing points into +) + +( +fork{ + ~n_analysis_frames = ~buf.sampleRate * 0.1; // analyze in 0.1 second windows + ~current_analysis_frame = 0; // start at 0 + i = 0; + while({ + // while the next frame that we would analyze doesn't go past the end of the buffer + (~current_analysis_frame + ~n_analysis_frames) < ~buf.numFrames; + },{ + // do the chroma analysis on this section of the buffer. this will return a buffer of 12 channels (one for each chroma) + // with as many frames as there are FFT windows in the 0.1 second slice we're analysing + FluidBufChroma.processBlocking(s,~buf,~current_analysis_frame,~n_analysis_frames,features:~chromabuf); + + // next, perform statistical analysis on each channel in chromabuf. this will return a buffer with however many + // channels are in chromabuf (12) and 7 frames, one for each statistical analysis + FluidBufStats.processBlocking(s,~chromabuf,stats:~statsbuf); + + // finally, since we want to have the mean value for each of the chroma we can ask FluidBufFlatten to just + // process the 0th frame (that has the mean values) of all the channels (so just the 0th column) into a flat + // buffer so it can be used in FluidDataSet.addPoint + FluidBufFlatten.processBlocking(s,~statsbuf,numFrames:1,destination:~flatbuf); + ~chroma_ds.addPoint("point-%".format(i),~flatbuf); + + ~current_analysis_frame = ~current_analysis_frame + ~n_analysis_frames; + i = i + 1; + }); + s.sync; + " \t\tnumFrames\tnumChannels".postln; + "shape of chromabuf:\t\t%\t\t\t%".format(~chromabuf.numFrames,~chromabuf.numChannels).postln; + "shape of statsbuf: \t\t%\t\t\t%".format(~statsbuf.numFrames,~statsbuf.numChannels).postln; + "shape of flatbuf: \t\t%\t\t\t%\n".format(~flatbuf.numFrames,~flatbuf.numChannels).postln; + ~chroma_ds.print; +} +) +:: +strong::FluidBufPitch is useful to illustrate the effect of this, because the pitch and confidence values are easily distinguishable:: +code:: +( +~buf = Buffer.readChannel(s,FluidFilesPath("Tremblay-CEL-GlitchyMusicBoxMelo.wav"),channels:[0]); +~pitchdata = Buffer(s); +~flatdata = Buffer(s); ) //Pitch analysis, writes pitches as frequencies to chan 0, confidences [0-1] to chan 1 -FluidBufPitch.process(s,b,numFrames:512 * 10,numChans:1,features:~pitchdata,action:{"Pitch Analysis Done".postln}); +// we'll only analyze the first 10 frames here so we can visually inspect the data more easily +FluidBufPitch.processBlocking(s,~buf,numFrames:512 * 9,numChans:1,features:~pitchdata,action:{"Pitch Analysis Done".postln}); + +//plot the original buffer to get a sense of what is in it: +( +"numFrames: %".format(~pitchdata.numFrames).postln; +"numChannels: %".format(~pitchdata.numChannels).postln; +~pitchdata.plot(separately:true); +) // Flatten and print the flat buffer. We expect to see larger numbers (20-2000) interleaved with smaller (0-1) ( FluidBufFlatten.process(s,~pitchdata, destination: ~flatdata, axis:1, action:{ ~flatdata.loadToFloatArray(action:{ |a| + "numFrames: %".format(~flatdata.numFrames).postln; + "numChannels: %".format(~flatdata.numChannels).postln; a.postln; }) }) @@ -26,27 +78,33 @@ FluidBufFlatten.process(s,~pitchdata, destination: ~flatdata, axis:1, action:{ ( FluidBufFlatten.process(s,~pitchdata, destination:~flatdata, axis:0, action:{ ~flatdata.loadToFloatArray(action:{ |a| + "numFrames: %".format(~flatdata.numFrames).postln; + "numChannels: %".format(~flatdata.numChannels).postln; a.postln; }) }) ) -//adding the source range make this processor very powerful, but can be quite confusing +//adding the source range (startFrame and numFrames) make this processor very powerful //here we take only one frame starting at the second one (0-counting) ( FluidBufFlatten.process(s,~pitchdata,startFrame: 1,numFrames: 1, destination:~flatdata, action:{ ~flatdata.loadToFloatArray(action:{ |a| + "numFrames: %".format(~flatdata.numFrames).postln; + "numChannels: %".format(~flatdata.numChannels).postln; a.postln; }) }) ) + //and here we take only the confidences ( FluidBufFlatten.process(s,~pitchdata, startChan: 1, destination:~flatdata, action:{ ~flatdata.loadToFloatArray(action:{ |a| + "numFrames: %".format(~flatdata.numFrames).postln; + "numChannels: %".format(~flatdata.numChannels).postln; a.postln; }) }) ) - -:: +:: \ No newline at end of file diff --git a/example-code/sc/BufMFCC.scd b/example-code/sc/BufMFCC.scd index 8f80582..694b371 100644 --- a/example-code/sc/BufMFCC.scd +++ b/example-code/sc/BufMFCC.scd @@ -1,50 +1,49 @@ - code:: -// create some buffers -( -b = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); -c = Buffer.new(s); -) -// run the process with basic parameters +// load a sound +~buf = Buffer.read(s,FluidFilesPath("Harker-DS-TenOboeMultiphonics-M.wav")); + +// do a FluidBufMFCC analysis ( -Routine{ - t = Main.elapsedTime; - FluidBufMFCC.process(s, b, features: c).wait; - (Main.elapsedTime - t).postln; -}.play +~mfccs = Buffer(s); +FluidBufMFCC.processBlocking(s,~buf,features:~mfccs,action:{"done".postln;}) ) -// listen to the source and look at the buffer -b.play; -c.plot(separately:true) +// plot it in FluidWaveform -- it's not *too* informative, but may be useful to get a sense of what these MFCC curves look like +FluidWaveform(~buf,featuresBuffer:~mfccs,stackFeatures:true,bounds:Rect(0,0,1600,400)); + :: +strong::Load a lot of MFCC analyses to a data set for later data processing:: +code:: -STRONG::A stereo buffer example.:: -CODE:: +// load a sound +~buf = Buffer.readChannel(s,FluidFilesPath("Tremblay-CF-ChurchBells.wav"),channels:[0]); -// load two very different files +// do a FluidBufMFCC analysis ( -b = Buffer.read(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav")); -c = Buffer.read(s,FluidFilesPath("Tremblay-AaS-AcousticStrums-M.wav")); +~mfccs = Buffer(s); +FluidBufMFCC.processBlocking(s,~buf,features:~mfccs,action:{"done".postln;}) ) -// composite one on left one on right as test signals -FluidBufCompose.process(s, c, numFrames:b.numFrames, startFrame:555000,destStartChan:1, destination:b) -b.play - -// create a buffer as destinations -c = Buffer.new(s); - -//run the process on them +// create a dataset to put the mfccs in ( -Routine{ - t = Main.elapsedTime; - FluidBufMFCC.process(s, b, numCoeffs:5, features: c).wait; - (Main.elapsedTime - t).postln; -}.play +~ds = FluidDataSet(s).fromBuffer(~mfccs); +~ds.print; ) -// 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) -:: +// dimensionally reduce the 13 MFCCs into 2D space +( // this will take a bit of time to process! +fork{ + ~umap = FluidUMAP(s); + ~norm = FluidNormalize(s); + s.sync; + ~umap.fitTransform(~ds,~ds); + ~norm.fitTransform(~ds,~ds); + ~dict = ~ds.dump({ + arg dict; + ~plotter = FluidPlotter(bounds:Rect(0,0,800,800),dict:dict); + }); +}; +) + +:: \ No newline at end of file diff --git a/example-code/sc/BufMelBands.scd b/example-code/sc/BufMelBands.scd index 2f0e57f..f3e0381 100644 --- a/example-code/sc/BufMelBands.scd +++ b/example-code/sc/BufMelBands.scd @@ -1,50 +1,64 @@ - +STRONG::Use a buffer of MelBands to drive a bank of oscillators:: code:: -// create some buffers ( -b = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); -c = Buffer.new(s); +~bells = Buffer.readChannel(s,FluidFilesPath("Tremblay-CF-ChurchBells.wav"),channels:[0]); +~melBands = Buffer(s); +~numBands = 100; ) -// run the process with basic parameters +// listen to the original +~bells.play; + +// analyse +FluidBufMelBands.processBlocking(s,~bells,features:~melBands,numBands:~numBands,action:{"done".postln}); + +// playback ( -Routine{ - t = Main.elapsedTime; - FluidBufMelBands.process(s, b, features: c, numBands:10).wait; - (Main.elapsedTime - t).postln; -}.play +x = { + arg rate = 0.1, freqMul = 1, freqAdd = 0; + var phs = Phasor.kr(0,rate,0,BufFrames.ir(~melBands)); + var melBands = BufRd.kr(~numBands,~melBands,phs,1,4); + var lowMel = 1127.010498 * ((20/700) + 1).log; // convert from hz to mels + var highMel = 1127.010498 * ((20000/700) + 1).log; // convert from hz to mels + var rangeMel = highMel - lowMel; + var stepMel = rangeMel / (~numBands+1); + var freqMel = Array.fill(~numBands,{arg i; (stepMel * (i+1)) + lowMel}); + var freqHz = ((freqMel/ 1127.01048).exp - 1) * 700; // convert from mel to hz + var sig = SinOsc.ar((freqHz * freqMul) + freqAdd,0,melBands); + Splay.ar(sig) * 24.dbamp; +}.play; ) -// listen to the source and look at the buffer -b.play; -c.plot -:: - -STRONG::A stereo buffer example.:: -CODE:: +// manipulate the oscillator bank +x.set(\rate,0.3); +x.set(\rate,0.04); +x.set(\freqMul,0.5); +x.set(\freqAdd,-2000); -// load two very different files +:: +STRONG::Look at the MelBands in FluidWaveform (as "features"):: +code:: +// create some buffers ( -b = Buffer.read(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav")); -c = Buffer.read(s,FluidFilesPath("Tremblay-AaS-AcousticStrums-M.wav")); +~src = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); +~melBands = Buffer.new(s); ) -// composite one on left one on right as test signals -FluidBufCompose.process(s, c, numFrames:b.numFrames, startFrame:555000,destStartChan:1, destination:b) -b.play - -// create a buffer as destinations -c = Buffer.new(s); +// run the process with basic parameters +FluidBufMelBands.processBlocking(s,~src,features:~melBands,action:{"done".postln}); -//run the process on them +// look at the mel bands as feature curves (a bit messy...) +FluidWaveform(~src,featuresBuffer:~melBands,bounds:Rect(0,0,1600,400),stackFeatures:true,normalizeFeaturesIndependently:false); +:: +STRONG::Do a higher resolution analysis and plot it as an image in FluidWaveform:: +code:: +// create some buffers ( -Routine{ - t = Main.elapsedTime; - FluidBufMelBands.process(s, b, features: c, numBands:10).wait; - (Main.elapsedTime - t).postln; -}.play +~src = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); +~melBands = Buffer.new(s); ) -// look at the buffer: 10 bands for left, then 10 bands for right -c.plot(separately:true) -:: +FluidBufMelBands.processBlocking(s,~src,features:~melBands,numBands:400,fftSize:4096,action:{"done".postln}); + +FluidWaveform(imageBuffer:~melBands,bounds:Rect(0,0,1600,400),imageColorScheme:1,imageColorScaling:1); +:: \ No newline at end of file diff --git a/example-code/sc/BufNoveltyFeature.scd b/example-code/sc/BufNoveltyFeature.scd new file mode 100644 index 0000000..847047b --- /dev/null +++ b/example-code/sc/BufNoveltyFeature.scd @@ -0,0 +1,13 @@ +strong::Plot the BufNoveltyFeature curve along with the indices from BufNoveltySlice:: +code:: + +~src = Buffer.read(s,FluidFilesPath("Tremblay-ASWINE-ScratchySynth-M.wav")); + +( +~indices = Buffer(s); +~feature = Buffer(s); +FluidBufNoveltySlice.processBlocking(s,~src,indices:~indices,algorithm:1,kernelSize:5,threshold:1.1); +FluidBufNoveltyFeature.processBlocking(s,~src,features:~feature,algorithm:1,kernelSize:5); +FluidWaveform(~src,~indices,~feature,bounds:Rect(0,0,1600,400)); +) +:: \ No newline at end of file diff --git a/example-code/sc/BufOnsetFeature.scd b/example-code/sc/BufOnsetFeature.scd new file mode 100644 index 0000000..26d81a2 --- /dev/null +++ b/example-code/sc/BufOnsetFeature.scd @@ -0,0 +1,13 @@ +strong::Plot the BufOnsetFeature curve along with the indices from BufOnsetSlice:: +code:: + +~src = Buffer.readChannel(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav"),channels:[0]); + +( +~indices = Buffer(s); +~feature = Buffer(s); +FluidBufOnsetSlice.processBlocking(s,~src,indices:~indices,metric:9,threshold:0.2); +FluidBufOnsetFeature.processBlocking(s,~src,features:~feature,metric:9); +FluidWaveform(~src,~indices,~feature,bounds:Rect(0,0,1600,400),lineWidth:2); +) +:: \ No newline at end of file diff --git a/example-code/sc/BufPitch.scd b/example-code/sc/BufPitch.scd index 84d0f44..84f2371 100644 --- a/example-code/sc/BufPitch.scd +++ b/example-code/sc/BufPitch.scd @@ -3,8 +3,10 @@ code:: ( // load a sound file ~scratchy = Buffer.read(s,FluidFilesPath("Tremblay-ASWINE-ScratchySynth-M.wav")); + // and a buffer to write the FluidBufPitch features into ~pitch_features_buf = Buffer.new(s); + // specify some params for the analysis (these are the defaults, but we'll specify them here so we can use them later) ~windowSize = 1024; ~hopSize = 512; @@ -15,14 +17,17 @@ code:: FluidBufPitch.processBlocking(s,~scratchy,features:~pitch_features_buf,windowSize:~windowSize,hopSize:~hopSize); ~pitch_features_buf.loadToFloatArray(action:{ arg fa; - ~pitch_features_array = fa.clump(2); + ~pitch_features_array = fa.clump(~pitch_features_buf.numChannels); + "done".postln; }); ) //look at the retrieved formatted array of [pitch,confidence] values ~pitch_features_array.postln -//iterate and make an array of the indices which are fitting the conditions +//iterate and make an array of the indices which are fitting the conditions: +// - pitch > 500 hz +// - confidence > 0.98 ( ~selected_indices = List.new; ~pitch_features_array.do({ @@ -36,7 +41,7 @@ FluidBufPitch.processBlocking(s,~scratchy,features:~pitch_features_buf,windowSiz ) ( -// In order to granulate the frames, we need to convert our indices to centerPos. +// In order to granulate the frames, we need to convert our indices to centerPos in seconds for TGrains to use. ~selected_center_pos = ~selected_indices.collect({arg i; (i * ~hopSize) / ~scratchy.sampleRate}); ~selected_center_pos.postln; // Load this list of center positions into a buffer so we can look them up later on the server @@ -67,8 +72,10 @@ CODE:: ) // composite one on left one on right as test signals +( FluidBufCompose.processBlocking(s,~piano, destination:~both,action:{"done".postln}); FluidBufCompose.processBlocking(s,~guitar,numFrames:~piano.numFrames,startFrame:555000,destStartChan:1,destination:~both,action:{"done".postln}); +) // listen ~both.play @@ -77,10 +84,10 @@ FluidBufCompose.processBlocking(s,~guitar,numFrames:~piano.numFrames,startFrame: ~pitch_analysis = Buffer(s); //run the process on them, with limited bandwidth -FluidBufPitch.process(s, ~both, features: ~pitch_analysis, minFreq:60, maxFreq:4000,action:{"done".postln}); +FluidBufPitch.processBlocking(s, ~both, features: ~pitch_analysis, minFreq:60, maxFreq:4000,action:{"done".postln}); // look at the buffer: [pitch,confidence] for left then [pitch,confidence] for right -FluidWaveform(~both,featureBuffer:~pitch_analysis,stackFeatures:true,bounds:Rect(0,0,1600,400)); +FluidWaveform(~both,featuresBuffer:~pitch_analysis,stackFeatures:true,bounds:Rect(0,0,1600,400)); // blue is piano pitch // orange is piano pitch confidence diff --git a/example-code/sc/BufThresh.scd b/example-code/sc/BufThresh.scd index b34d1c6..92abbcf 100644 --- a/example-code/sc/BufThresh.scd +++ b/example-code/sc/BufThresh.scd @@ -1,29 +1,89 @@ +strong::Use with the FluidBufStats `weights` argument.:: Using the pitch confidence value of the FluidBufPitch analysis to weight the statistical analysis of the pitch value can improve the estimation of pitch (as the mean or median). By using FluidBufThresh, we can ensure that any pitch confidence values below a specified threshold will be "zeroed out" so their weight will be zero when calculating FluidBufStats. +code:: + +~scratchy = Buffer.read(s,FluidFilesPath("Tremblay-ASWINE-ScratchySynth-M.wav")); + +~scratchy.play; + +( +~pitch_analysis = Buffer(s); +FluidBufPitch.processBlocking(s,~scratchy,features:~pitch_analysis); +) + +// look at the pitch analysis: +FluidWaveform(~scratchy,featuresBuffer:~pitch_analysis,stackFeatures:true,bounds:Rect(0,0,1600,400)); + +// get the median pitch +( +~pitch_stats = Buffer(s); +FluidBufStats.processBlocking(s,~pitch_analysis,numChans:1,stats:~pitch_stats); +~pitch_stats.loadToFloatArray(action:{ + arg fa; + ~median = fa[5]; + ~median.postln; +}); +) + +// how does the pitch match? (not great) +( +~scratchy.play; +{SinOsc.ar(~median,0,0.01)}.play; +) + +// use buf thresh to zero out all confidence values below a threshold: +( +~threshed_conf = Buffer(s); +FluidBufThresh.processBlocking(s,~pitch_analysis,startChan:1,destination:~threshed_conf,threshold:0.99); +) + +// look at the thresholded values. (some will appear to not actually reach above the threshold...this is due to +// the interpolation happening for the drawing) +FluidWaveform(~scratchy,featuresBuffer:~threshed_conf,bounds:Rect(0,0,1600,400)); +// now that anything below the threshold has become a zero, this will be useful for weighting the BufStats analysis +( +~pitch_stats = Buffer(s); +FluidBufStats.processBlocking(s,~pitch_analysis,numChans:1,stats:~pitch_stats,weights:~threshed_conf); +~pitch_stats.loadToFloatArray(action:{ + arg fa; + ~median = fa[5]; + ~median.postln; +}); +) + +// does it match better? (it does) +( +~scratchy.play; +{SinOsc.ar(~median,0,0.01)}.play; +) + +:: +strong::A basic example to look at the output:: code:: -// make a buffer of know qualities -b = Buffer.sendCollection(s,0.0.series(0.1,1.0)) -// and a destination buffer -c = Buffer(s) -// play with the threshold -FluidBufThresh.process(s, b, destination: c, threshold: 0.5) -// retrieve the buffer and enjoy the results. -c.getn(0,11,{|x|x.round(0.000001).postln;}) - -// also works in multichannel - explore the following buffer -b = Buffer.sendCollection(s,0.0.series(0.1,2.0).scramble,2) -b.plot.plotMode_(\points) -//process and keep just the top values -FluidBufThresh.process(s, b, destination: c, threshold: 1.6) -//enjoy -c.plot.plotMode_(\points) - -//also works with a subset of the input, resizing the output -b = Buffer.sendCollection(s,0.0.series(0.1,3.0).reshape(3,10).flop.flat,3) -b.plot(separately: true).plotMode_(\points) -//process and keep just the top values -FluidBufThresh.process(s, b,startFrame: 3,numFrames: 4,startChan: 1,numChans: 1,destination: c, threshold: 1.6) -//enjoy -c.plot(separately: true).plotMode_(\points) -c.query -c.getn(0,4,{|x|x.round(0.000001).postln;}) +// make a buffer with some values roughly 0 to 5 +// and a buffer to write the output of FluidBufThresh into +( +~hundred = Buffer.loadCollection(s,(1..100).log); +~threshed = Buffer(s); +) + +// take a look at the values +~hundred.plot; + +// apply a threshold of 3 +FluidBufThresh.processBlocking(s,~hundred,destination:~threshed,threshold:3); + +// take a look at the output +~threshed.plot; + +// composite them together (for looking at later) +( +~together = Buffer(s); +FluidBufCompose.processBlocking(s,~hundred,destination:~together); +FluidBufCompose.processBlocking(s,~threshed,destination:~together,destStartChan:1); +) + +// plot it +FluidWaveform(featuresBuffer:~together,bounds:Rect(0,0,1600,400),lineWidth:2,normalizeFeaturesIndependently:false); + :: diff --git a/example-code/sc/MFCC.scd b/example-code/sc/MFCC.scd index d571653..37d6a88 100644 --- a/example-code/sc/MFCC.scd +++ b/example-code/sc/MFCC.scd @@ -1,239 +1,155 @@ code:: -//create a monitoring window for the values +// a window to watch the MFCC analyses in real-time ( -b = Bus.new(\control,0,13); -w = Window("MFCCs Monitor", Rect(10, 10, 420, 320)).front; -a = MultiSliderView(w,Rect(10, 10, 400, 300)).elasticMode_(1).isFilled_(1); -a.reference_(Array.fill(13,{0.5})); //make a center line to show 0 -) - -//run the window updating routine. -( -~winRange = 20; - -r = Routine { - { - b.get({ arg val; - { - if(w.isClosed.not) { - //val.postln; - a.value = val.linlin(~winRange.neg,~winRange,0,1); - } - }.defer - }); - 0.01.wait; - }.loop -}.play +~win = Window("MFCCs Monitor",Rect(0,0,800,400)).front; +~ms = MultiSliderView(~win,Rect(0,0,~win.bounds.width,~win.bounds.height)).elasticMode_(1).isFilled_(1); +~ms.reference_(Array.fill(13,{0.5})); //make a center line to show 0 ) //play a simple sound to observe the values ( -x = {arg type = 0; +~synth = { + arg type = 0; var source = Select.ar(type,[SinOsc.ar(220),Saw.ar(220),Pulse.ar(220)]) * LFTri.kr(0.1).exprange(0.01,0.1); - Out.kr(b,FluidMFCC.kr(source,maxNumCoeffs:13)); + var mfccs = FluidMFCC.kr(source,numCoeffs:13,startCoeff:0,maxNumCoeffs:13); + SendReply.kr(Impulse.kr(30),"/mfccs",mfccs); source.dup; }.play; + +~mfccRange = 40; +OSCdef(\mfccs,{ + arg msg; + {~ms.value_(msg[3..].linlin(~mfccRange.neg,~mfccRange,0,1))}.defer; +},"/mfccs"); ) -// change the wave types, observe the amplitude invariance of the descriptors, apart from the leftmost coefficient -x.set(\type, 1) -~winRange = 40; //adjust the range above and below 0 to zoom in or out on the MFCC -x.set(\type, 2) -x.set(\type, 0) -// free this source -x.free +// change the wave types, observe that, apart from the 0th coefficient, different loudness does not change the values +~synth.set(\type, 1) // sawtooth wave +~synth.set(\type, 2) // pulse wave +~synth.set(\type, 0) // sine wave -// load a more exciting one -c = Buffer.read(s,FluidFilesPath("Tremblay-AaS-SynthTwoVoices-M.wav")); +~synth.free; -// analyse with parameters to be changed +// load a more complex souond +~tbone = Buffer.read(s,FluidFilesPath("Olencki-TenTromboneLongTones-M.wav")); + +// notice now that all these trombone sounds look relatively similar because they're the same timbre, even when the trombone changes pitches ( -x = {arg bands = 40, low = 20, high = 20000; - var source = PlayBuf.ar(1,c,loop:1); - Out.kr(b,FluidMFCC.kr(source, numCoeffs: 13, numBands: bands, minFreq: low, maxFreq: high, maxNumCoeffs: 13) / 10); +x = {arg bands = 40; + var source = PlayBuf.ar(1,~tbone,loop:1); + var mfccs = FluidMFCC.kr(source, numCoeffs: 13, numBands: bands, maxNumCoeffs: 13); + SendReply.kr(Impulse.kr(30),"/mfccs",mfccs); source.dup; }.play; -) -~winRange = 10; //adjust the range above and below 0 to zoom in or out on the MFCC -// observe the number of bands. The unused ones at the top are not updated -x.set(\bands,20) - -// back to the full range -x.set(\bands,40) +~mfccRange = 70; +OSCdef(\mfccs,{ + arg msg; + {~ms.value_(msg[3..].linlin(~mfccRange.neg,~mfccRange,0,1))}.defer; +},"/mfccs"); +) -// focus all the bands on a mid range -x.set(\low,320, \high, 800) +// compare with the timbres of oboe multiphonics +~oboe = Buffer.read(s,FluidFilesPath("Harker-DS-TenOboeMultiphonics-M.wav")); -// focusing on the low end shows the fft resolution issue. One could restart the analysis with a larger fft to show more precision -x.set(\low,20, \high, 160) +( +x = { + arg bands = 40; + var source = PlayBuf.ar(1,~oboe,loop:1); + var mfccs = FluidMFCC.kr(source, numCoeffs: 13, numBands: bands, maxNumCoeffs: 13); + SendReply.kr(Impulse.kr(30),"/mfccs",mfccs); + source.dup; +}.play; -// back to full range -x.set(\low,20, \high, 20000) +~mfccRange = 70; +OSCdef(\mfccs,{ + arg msg; + {~ms.value_(msg[3..].linlin(~mfccRange.neg,~mfccRange,0,1))}.defer; +},"/mfccs"); +) -// free everything -x.free;b.free;c.free;r.stop; :: - -STRONG::A musical example:: - +STRONG::Comparing MFCC Analyses in real-time:: 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, restart = 1; - var sound, mfcc, mfccFreeze0, mfccFreeze1, dist0, dist1, closest, slice; - - sound = SelectX.ar(source, [ - SinOsc.ar(freq, 0, 0.1), - LFTri.ar(freq, 0, 0.1), - LFSaw.ar(freq, 0, 0.1), - Pulse.ar(freq, 0.5, 0.1), - WhiteNoise.ar(0.1), - PinkNoise.ar(0.1), - PlayBuf.ar(1, buffer, 1, loop:1, trigger:restart) - ]); - slice = FluidOnsetSlice.ar(sound); //onset detection for mfcc freeze on onset +// we'll compare trombone to trombone (but at different playback rates to fake 2 different players +~buf = Buffer.read(s,FluidFilesPath("Olencki-TenTromboneLongTones-M.wav")); - mfcc = FluidMFCC.kr(sound,maxNumCoeffs:13); - mfccFreeze0 = Latch.kr(mfcc, t_freeze0+(slice*onsetsOn0)); - mfccFreeze1 = Latch.kr(mfcc, t_freeze1+(slice*onsetsOn1)); - - Out.kr(mfccBus,mfcc.addAll(mfccFreeze0).addAll(mfccFreeze1)); +// the more similar the timbres of the "2" trombonists, the lower the measured "distance" between them will be +// here, MFCC's timbre measure captures differences in timbre across the trombone range +// watch for how the more similar the trombone sound, the smaller distance measurement between the 2 analyses +( +{ + var sigA = PlayBuf.ar(1,~buf,BufRateScale.ir(~buf) * 0.9,loop:1); + var sigB = PlayBuf.ar(1,~buf,BufRateScale.ir(~buf),loop:1); + + var mfccA = FluidMFCC.kr(sigA,startCoeff:1); + var mfccB = FluidMFCC.kr(sigB,startCoeff:1); + var dist = Mix((mfccA - mfccB).squared).sqrt; + SendReply.kr(Impulse.kr(30),"/dists",dist); + [sigA,sigB]; +}.play; - //distance calculations +OSCdef(\dists,{ + arg msg; + "\ndistance:\t%\t".format(msg[3].round).post; + {"*".post} ! (msg[3] / 5); +},"/dists"); +) - dist0 = Mix((mfcc.copyRange(1,12) - mfccFreeze0.copyRange(1,12)).squared).sqrt; - dist1 = Mix((mfcc.copyRange(1,12) - mfccFreeze1.copyRange(1,12)).squared).sqrt; +:: +STRONG::Using Dimensionality Reduction to plot MFCCs in 2D Space:: - Out.kr(distBus, [dist0, dist1]); +CODE:: - //sends a trigger when the item with a closer euclidean distance changes - SendTrig.kr(Trig1.kr(dist1-dist0, 0.001)+Trig1.kr(dist0-dist1, 0.001), 0, dist1 0.98).lag(0.01),0.5,0.1,3); + sig = CombC.ar(src * (conf > 0.99).lag(0.005),0.5,0.1,3); [src,sig]; }.play; ) diff --git a/flucoma/MakeRef.py b/flucoma/MakeRef.py index 720b16e..bbe07ba 100644 --- a/flucoma/MakeRef.py +++ b/flucoma/MakeRef.py @@ -42,7 +42,7 @@ def main(passed_args): parser = argparse.ArgumentParser( description='Generate FluCoMa documentation for a given host, using input JSON and YAML data and a jinja template') - parser.add_argument('host', choices=['max','pd','cli','sc']) + parser.add_argument('host', choices=['max','pd','cli','sc','raw']) parser.add_argument('json_path', type=Path, help='Path to generated JSON client data') @@ -84,16 +84,19 @@ def main(passed_args): **host_settings) ) ) for c in clients - } + } - for c in index: - render.client(c, index, args, host_settings) + if host_settings.get('template'): + for c in index: + render.client(c, index, args, host_settings) - if host_settings['post']: host_settings['post'](index,args) - - topics = list(Path('topics/').resolve().glob('*.yaml')) - for t in topics: - render.topic(load_topic_data(t),index, args, host_settings) + if host_settings['post']: + host_settings['post'](index,args) + + if host_settings.get('topic_template'): + topics = list(Path('topics/').resolve().glob('*.yaml')) + for t in topics: + render.topic(load_topic_data(t),index, args, host_settings) if __name__ == '__main__': main(sys.argv[1:]) diff --git a/flucoma/doc/raw/driver.py b/flucoma/doc/raw/driver.py new file mode 100644 index 0000000..2b524cc --- /dev/null +++ b/flucoma/doc/raw/driver.py @@ -0,0 +1,30 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +import json +from .. transformers import default_transform + +def transform_data(client, data): + return default_transform(client, data) + +def write_index(idx,program_args): + + path = program_args.output_path + path.mkdir(exist_ok=True) + apifile = path / 'api.json' + with open(apifile,'w') as f: + json.dump(idx,f,sort_keys=True, indent=0) + + maxdb_objs = {'maxdb':{'externals':{}}} + +settings = { + 'glob': '**/*.json', + 'transform': default_transform, + 'post': write_index, + 'defaults': None, +} diff --git a/src/clients/AmpFeature/AmpFeature.cpp b/src/clients/AmpFeature/AmpFeature.cpp new file mode 100644 index 0000000..86e32b0 --- /dev/null +++ b/src/clients/AmpFeature/AmpFeature.cpp @@ -0,0 +1,19 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright 2017-2019 University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#include +#include +int main(int argc, char *argv[]) { + using namespace fluid::client; + if (!argc) std::cerr << "Please pass a folder to write to"; + std::cout << "Write JSON to " << argv[1]; + ParameterDump::dump("AmpFeature", argv[1]); + return 0; +} diff --git a/src/clients/AmpFeature/CMakeLists.txt b/src/clients/AmpFeature/CMakeLists.txt new file mode 100644 index 0000000..b07cf17 --- /dev/null +++ b/src/clients/AmpFeature/CMakeLists.txt @@ -0,0 +1,16 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +cmake_minimum_required(VERSION 3.11) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-pretarget.cmake) +add_executable( + ${PROJECT_NAME} + ${PROJECT_NAME}.cpp +) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-posttarget.cmake) diff --git a/src/clients/BufAmpFeature/BufAmpFeature.cpp b/src/clients/BufAmpFeature/BufAmpFeature.cpp new file mode 100644 index 0000000..13ca288 --- /dev/null +++ b/src/clients/BufAmpFeature/BufAmpFeature.cpp @@ -0,0 +1,19 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright 2017-2019 University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#include +#include +int main(int argc, char *argv[]) { + using namespace fluid::client; + if (!argc) std::cerr << "Please pass a folder to write to"; + std::cout << "Write JSON to " << argv[1]; + ParameterDump::dump("BufAmpFeature", argv[1]); + return 0; +} diff --git a/src/clients/BufAmpFeature/CMakeLists.txt b/src/clients/BufAmpFeature/CMakeLists.txt new file mode 100644 index 0000000..b07cf17 --- /dev/null +++ b/src/clients/BufAmpFeature/CMakeLists.txt @@ -0,0 +1,16 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +cmake_minimum_required(VERSION 3.11) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-pretarget.cmake) +add_executable( + ${PROJECT_NAME} + ${PROJECT_NAME}.cpp +) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-posttarget.cmake) diff --git a/src/clients/BufNoveltyFeature/BufNoveltyFeature.cpp b/src/clients/BufNoveltyFeature/BufNoveltyFeature.cpp new file mode 100644 index 0000000..c016b8a --- /dev/null +++ b/src/clients/BufNoveltyFeature/BufNoveltyFeature.cpp @@ -0,0 +1,19 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright 2017-2019 University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#include +#include +int main(int argc, char *argv[]) { + using namespace fluid::client; + if (!argc) std::cerr << "Please pass a folder to write to"; + std::cout << "Write JSON to " << argv[1]; + ParameterDump::dump("BufNoveltyFeature", argv[1]); + return 0; +} diff --git a/src/clients/BufNoveltyFeature/CMakeLists.txt b/src/clients/BufNoveltyFeature/CMakeLists.txt new file mode 100644 index 0000000..b07cf17 --- /dev/null +++ b/src/clients/BufNoveltyFeature/CMakeLists.txt @@ -0,0 +1,16 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +cmake_minimum_required(VERSION 3.11) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-pretarget.cmake) +add_executable( + ${PROJECT_NAME} + ${PROJECT_NAME}.cpp +) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-posttarget.cmake) diff --git a/src/clients/BufOnsetFeature/BufOnsetFeature.cpp b/src/clients/BufOnsetFeature/BufOnsetFeature.cpp new file mode 100644 index 0000000..7bb5968 --- /dev/null +++ b/src/clients/BufOnsetFeature/BufOnsetFeature.cpp @@ -0,0 +1,19 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright 2017-2019 University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#include +#include +int main(int argc, char *argv[]) { + using namespace fluid::client; + if (!argc) std::cerr << "Please pass a folder to write to"; + std::cout << "Write JSON to " << argv[1]; + ParameterDump::dump("BufOnsetFeature", argv[1]); + return 0; +} diff --git a/src/clients/BufOnsetFeature/CMakeLists.txt b/src/clients/BufOnsetFeature/CMakeLists.txt new file mode 100644 index 0000000..b07cf17 --- /dev/null +++ b/src/clients/BufOnsetFeature/CMakeLists.txt @@ -0,0 +1,16 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +cmake_minimum_required(VERSION 3.11) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-pretarget.cmake) +add_executable( + ${PROJECT_NAME} + ${PROJECT_NAME}.cpp +) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-posttarget.cmake) diff --git a/src/clients/NoveltyFeature/CMakeLists.txt b/src/clients/NoveltyFeature/CMakeLists.txt new file mode 100644 index 0000000..b07cf17 --- /dev/null +++ b/src/clients/NoveltyFeature/CMakeLists.txt @@ -0,0 +1,16 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +cmake_minimum_required(VERSION 3.11) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-pretarget.cmake) +add_executable( + ${PROJECT_NAME} + ${PROJECT_NAME}.cpp +) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-posttarget.cmake) diff --git a/src/clients/NoveltyFeature/NoveltyFeature.cpp b/src/clients/NoveltyFeature/NoveltyFeature.cpp new file mode 100644 index 0000000..9c97da6 --- /dev/null +++ b/src/clients/NoveltyFeature/NoveltyFeature.cpp @@ -0,0 +1,19 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright 2017-2019 University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#include +#include +int main(int argc, char *argv[]) { + using namespace fluid::client; + if (!argc) std::cerr << "Please pass a folder to write to"; + std::cout << "Write JSON to " << argv[1]; + ParameterDump::dump("NoveltyFeature", argv[1]); + return 0; +} diff --git a/src/clients/OnsetFeature/CMakeLists.txt b/src/clients/OnsetFeature/CMakeLists.txt new file mode 100644 index 0000000..b07cf17 --- /dev/null +++ b/src/clients/OnsetFeature/CMakeLists.txt @@ -0,0 +1,16 @@ +# Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +# Copyright 2017-2019 University of Huddersfield. +# Licensed under the BSD-3 License. +# See license.md file in the project root for full license information. +# This project has received funding from the European Research Council (ERC) +# under the European Union’s Horizon 2020 research and innovation programme +# (grant agreement No 725899). + +cmake_minimum_required(VERSION 3.11) +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-pretarget.cmake) +add_executable( + ${PROJECT_NAME} + ${PROJECT_NAME}.cpp +) + +include(${CMAKE_CURRENT_SOURCE_DIR}/../../../script/dump-posttarget.cmake) diff --git a/src/clients/OnsetFeature/OnsetFeature.cpp b/src/clients/OnsetFeature/OnsetFeature.cpp new file mode 100644 index 0000000..630a621 --- /dev/null +++ b/src/clients/OnsetFeature/OnsetFeature.cpp @@ -0,0 +1,19 @@ +/* +Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) +Copyright 2017-2019 University of Huddersfield. +Licensed under the BSD-3 License. +See license.md file in the project root for full license information. +This project has received funding from the European Research Council (ERC) +under the European Union’s Horizon 2020 research and innovation programme +(grant agreement No 725899). +*/ + +#include +#include +int main(int argc, char *argv[]) { + using namespace fluid::client; + if (!argc) std::cerr << "Please pass a folder to write to"; + std::cout << "Write JSON to " << argv[1]; + ParameterDump::dump("OnsetFeature", argv[1]); + return 0; +}