[Release] 1.0.1 (#125)

* ignore more varieties of build folder

* deal with some warnings

* FluidWaveform 'lineWidth' argument now also affects feature lines

* add back the nmf-jit-classifier example

* novelty interface change in example

* resizable and layoutable guis (#83)

* resizable and layoutable guis

* FluidWaveform: rename 'win' to 'parent'

* FluidWaveform/FluidPlotter: update help

* FluidWaveform/Plotter: make views before forking

This way views are immediately available upon creation,
for example to be added to layouts.
Views are still correctly updated with data from within the fork,
whenever they are ready.

* Thanks @elgiano! + a few small edits

Co-authored-by: Ted Moore <ted@tedmooremusic.com>

* slicers: add enums for algorithms (#86)

* typo

* FluidBufNMF class: add resynthMode argument

* add PCA whitening parameter (#65)

* add PCA whitening parameter

* FluidPCA: Ensure whiten parameter is sent to kr query UGen

Co-authored-by: Gerard <gerard@bumblebee.lan>
Co-authored-by: weefuzzy <gungwho@gmail.com>

* Enhance/optional message args (#77)

* optional args: sc wrapper updates

* optional args: KDTree try out

* Enhance/choices param (#78)

* NRTWrapper: Add choices param (long <-> bitset)

* Update `FluidBufStats` with `select` control

* BufStats class: Fix bitfield for `select` and warn on duplicate items

* Update SpectralShape classes for new param

* `PCA.sc`: add batch `inverseTranform` method

* Wrapper: integer sign warnings

* Enhance/max params (#93)

* CMake: Centralise C++ version and set to 17

* Wrapper: handle new LongRuntimeMax param type

* POC for new LongRuntimeMax param with MFCC numCoeffs

* Wrapper: Make MSVC happy about constexpr lambda capture

* All scalers: replace 'invert' parameter with `inverseTransform` messages

* Wrapper: Work around 32 char limit for plugin commands

If too long, remove vowels. 
Sorry. 
Better ideas welcome

* fix #96

* typo

* Update SC classes for new style `max<X>` parameters

* SpectralShape SC class: maxFFT

* RealTime wrapper: play it safer with output channel count

This really relies on the SC class being correct, but then everything 
ultimately does...

* RT FFT Object SC Classes: Provide maxFFTSize default

* BufSTFT SC class: Add maxFFT (now needed due to core type change)

* Add select param to Loudness and Pitch SC clases (#101)

* Wrapper: workaround scsynth 32 char cmd length limit with extra dispatch layer 

also avoids need for formerly truncated plugin names in some cases

* removed invert from scalers class definitions (#102)

* Enhance/generate stubs (#104)

* CMake: generate .cpp stubs

* Remove old cpp stubs

* Ensure correct MSVC runtime by default

* CMake: invoke docs properly

* CMake: Tidy up

* CMake: Tidy up

* CMake: typo

* CI: Update nightly

* CI: remove lingering references to docs job

* CMake: belatedly add branch selection for flucoma deps upon which CI relies

* CMake: Actually commit important code for best collaborative results

* CMake: This file is now redundant, in fact

* cmake: missing slash in install

* bufnmf: added the maxFFTsize parameter in the server call

* FluidStats: Change where output Array reshape happens to keep SynthDescLib happy

* FluidBufNNDSVD: maxfftsize now needed in server call, or booooom

fixes #161

* BufNMFCross: Needs MaxFFTSize

* BufNNDSVD: Ensure activations buffer is queried at finish

* FluidBufToKr ensure that numFrames is an int (not a float)

* Added *(Buf)Feature objects to guide (and deleted old guide)

NNDSVD --> NMFSeed in Guide

fixed bad links in Guide

* change interface and file name (#113)

* hidden --> hiddenLayers in class definition (#114)

* reordered some max<X> arguments

* change interp to interpolation in nmfmorph class (#115)

* Feature/skmeans (#66)

* add PCA whitening parameter

* add FluidSKMeans

* SKMeans correction

* added RT query

* <fit>transform<point> -> <fit>encode<point>

* added to overview

Co-authored-by: Gerard <gerard@bumblebee.lan>
Co-authored-by: tremblap <info@pierrealexandretremblay.com>

* [CI] Update Release Workflow (#118)

* cleanup nightly.yaml

* use new release style

* refactor release

* remove workflow dispatch variables

* interface changes in 8c

* knearest interface change in 10a

* waveform help nmf interface change

* capitalise beatRemember

* two more changes of interface

* typo

* sign binaries

* add -nightly affix

* sign releases too

* enforce concurrency of jobs

* UMAP kr method should not allow user to pass numDimensions

* slicers: change algo/metric select to symbols (#103)

* slicers: change algo/metric selection to symbols

* slicers: algo/metric accept UGen

* FluidDataSetWr example code (#124)
nix
James Bradbury 4 years ago committed by GitHub
parent 3fd541feaf
commit 322c4454df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,37 +1,48 @@
name: Nightly Releases
name: nightly
on:
workflow_dispatch:
push:
branches: [ dev, ci/** ]
concurrency:
group: environment-${{ github.ref }}
cancel-in-progress: true
jobs:
macbuild:
runs-on: macos-11
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- uses: flucoma/actions/env@v5
- uses: flucoma/actions/sc@v5
- uses: actions/checkout@v3
- uses: flucoma/actions/env@main
- uses: flucoma/actions/sc@main
with:
branch: origin/dev
- name: compress archive
run: zip -r FluCoMa-SC-Mac-nightly.zip FluidCorpusManipulation
working-directory: install
- uses: actions/upload-artifact@v2
- name: sign binaries
uses: flucoma/actions/distribution@main
with:
name: macbuild
path: install/FluCoMa-SC-Mac-nightly.zip
glob: '-e scx'
package: 'install'
output_type: 'dmg'
output: FluCoMa-SC-Mac-nightly
cert: ${{ secrets.CERT }}
certpwd: ${{ secrets.CERTPWD }}
teamid: ${{ secrets.WWDRTEAMID }}
apppwd: ${{ secrets.APPSTORECONNECTPWD }}
appusr: ${{ secrets.APPSTORECONNECTUSERNAME }}
- uses: actions/upload-artifact@v3
with:
name: macbuild
path: install/FluCoMa-SC-Mac-nightly.dmg
winbuild:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: flucoma/actions/env@v5
- uses: flucoma/actions/sc@v5
- uses: actions/checkout@v3
- uses: flucoma/actions/env@main
- uses: flucoma/actions/sc@main
with:
branch: origin/dev
@ -42,25 +53,25 @@ jobs:
run: 7z a FluCoMa-SC-Windows-nightly.zip FluidCorpusManipulation
working-directory: install
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: winbuild
path: install/FluCoMa-SC-Windows-nightly.zip
linuxbuild:
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: flucoma/actions/env@v5
- uses: flucoma/actions/sc@v5
- uses: actions/checkout@v3
- uses: flucoma/actions/env@main
- uses: flucoma/actions/sc@main
with:
branch: origin/dev
- name: compress archive
run: tar -zcvf FluCoMa-SC-Linux-nightly.tar.gz FluidCorpusManipulation
working-directory: install
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: linuxbuild
path: install/FluCoMa-SC-Linux-nightly.tar.gz
@ -94,7 +105,7 @@ jobs:
with:
name: FluCoMa SuperCollider Nightly Release
body: "This is a nightly build of the FluCoMa SuperCollider package. As such, be warned there may be bugs or other unexpected behaviour. The build hash is ${{ github.sha }}"
files: FluCoMa-SC-*
files: FluCoMa*
prerelease: true
tag_name: nightly
draft: false

@ -1,33 +1,42 @@
name: Release
name: release
on:
workflow_dispatch:
jobs:
macbuild:
runs-on: macos-11
runs-on: macos-latest
steps:
- uses: actions/checkout@v2
- uses: flucoma/actions/env@v5
- uses: flucoma/actions/sc@v5
- uses: actions/checkout@v3
- uses: flucoma/actions/env@main
- uses: flucoma/actions/sc@main
with:
branch: origin/main
- name: compress archive
run: zip -r FluCoMa-SC-Mac.zip FluidCorpusManipulation
working-directory: install
- name: sign binaries
uses: flucoma/actions/distribution@main
with:
glob: '-e scx'
package: 'install'
output_type: 'dmg'
output: FluCoMa-SC-Mac
cert: ${{ secrets.CERT }}
certpwd: ${{ secrets.CERTPWD }}
teamid: ${{ secrets.WWDRTEAMID }}
apppwd: ${{ secrets.APPSTORECONNECTPWD }}
appusr: ${{ secrets.APPSTORECONNECTUSERNAME }}
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: macbuild
path: install/FluCoMa-SC-Mac.zip
path: install/FluCoMa-SC-Mac.dmg
winbuild:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: flucoma/actions/env@v5
- uses: flucoma/actions/sc@v5
- uses: actions/checkout@v3
- uses: flucoma/actions/env@main
- uses: flucoma/actions/sc@main
with:
branch: origin/main
@ -38,19 +47,19 @@ jobs:
run: 7z a FluCoMa-SC-Windows.zip FluidCorpusManipulation
working-directory: install
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: winbuild
path: install/FluCoMa-SC-Windows.zip
linuxbuild:
runs-on: ubuntu-18.04
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get-version.outputs.version }}
steps:
- uses: actions/checkout@v2
- uses: flucoma/actions/env@v5
- uses: flucoma/actions/sc@v5
- uses: actions/checkout@v3
- uses: flucoma/actions/env@main
- uses: flucoma/actions/sc@main
with:
branch: origin/main
@ -58,7 +67,7 @@ jobs:
run: tar -zcvf FluCoMa-SC-Linux.tar.gz FluidCorpusManipulation
working-directory: install
- uses: actions/upload-artifact@v2
- uses: actions/upload-artifact@v3
with:
name: linuxbuild
path: install/FluCoMa-SC-Linux.tar.gz

@ -6,6 +6,10 @@ FluidBufNoveltyFeature : FluidBufProcessor {
source = source.asUGenInput;
features = features.asUGenInput;
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm) ?? {
("FluidBufNoveltySlice: % is not a recognised algorithm")
.format(algorithm).throw;
};
source.isNil.if {"FluidBufNoveltyFeature: Invalid source buffer".throw};
features.isNil.if {"FluidBufNoveltyFeature: Invalid features buffer".throw};
@ -20,6 +24,11 @@ FluidBufNoveltyFeature : FluidBufProcessor {
source = source.asUGenInput;
features = features.asUGenInput;
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm);
if (algorithm.isNil or: algorithm.isUGen) {
("FluidBufNoveltySlice: % is not a recognised algorithm")
.format(algorithm).throw;
};
source.isNil.if {"FluidBufNoveltyFeature: Invalid source buffer".throw};
features.isNil.if {"FluidBufNoveltyFeature: Invalid features buffer".throw};
@ -40,6 +49,11 @@ FluidBufNoveltyFeature : FluidBufProcessor {
source.isNil.if {"FluidBufNoveltyFeature: Invalid source buffer".throw};
features.isNil.if {"FluidBufNoveltyFeature: Invalid features buffer".throw};
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm);
if (algorithm.isNil or: algorithm.isUGen) {
("FluidBufNoveltySlice: % is not a recognised algorithm")
.format(algorithm).throw;
};
^this.new(
server, nil, [features]

@ -1,11 +1,15 @@
FluidBufNoveltySlice : FluidBufProcessor {
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, algorithm = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, minSliceLength = 2, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1 , blocking = 0|
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, algorithm = 0, kernelSize = 3, threshold = 0.5, filterSize = 1, minSliceLength = 2, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1 , blocking = 0|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
source = source.asUGenInput;
indices = indices.asUGenInput;
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm) ?? {
("FluidBufNoveltySlice: % is not a recognised algorithm")
.format(algorithm).throw;
};
source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw};
indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw};
@ -15,15 +19,20 @@ FluidBufNoveltySlice : FluidBufProcessor {
}
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, algorithm= 0, kernelSize = 3, threshold = 0.5, filterSize = 1, minSliceLength = 2, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action |
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
source = source.asUGenInput;
indices = indices.asUGenInput;
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm);
if (algorithm.isNil or: algorithm.isUGen) {
("FluidBufNoveltySlice: % is not a recognised algorithm")
.format(algorithm).throw;
};
source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw};
indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw};
^this.new(
server, nil, [indices]
).processList(
@ -32,15 +41,20 @@ FluidBufNoveltySlice : FluidBufProcessor {
}
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, algorithm= 0, kernelSize = 3, threshold = 0.5, filterSize = 1, minSliceLength = 2, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action |
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
source = source.asUGenInput;
indices = indices.asUGenInput;
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm);
if (algorithm.isNil or: algorithm.isUGen) {
("FluidBufNoveltySlice: % is not a recognised algorithm")
.format(algorithm).throw;
};
source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw};
indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw};
^this.new(
server, nil, [indices]
).processList(

@ -5,6 +5,10 @@ FluidBufOnsetFeature : FluidBufProcessor {
source = source.asUGenInput;
features = features.asUGenInput;
metric = FluidOnsetSlice.prSelectMetric(metric) ?? {
("FluidBufOnsetSlice: % is not a recognised metric")
.format(metric).throw;
};
source.isNil.if {"FluidBufOnsetFeature: Invalid source buffer".throw};
features.isNil.if {"FluidBufOnsetFeature: Invalid features buffer".throw};
@ -18,6 +22,11 @@ FluidBufOnsetFeature : FluidBufProcessor {
source = source.asUGenInput;
features = features.asUGenInput;
metric = FluidOnsetSlice.prSelectMetric(metric);
if (metric.isNil or: metric.isUGen) {
("FluidBufOnsetSlice: % is not a recognised metric")
.format(metric).throw;
};
source.isNil.if {"FluidBufOnsetFeature: Invalid source buffer".throw};
features.isNil.if {"FluidBufOnsetFeature: Invalid features buffer".throw};
@ -35,6 +44,11 @@ FluidBufOnsetFeature : FluidBufProcessor {
source = source.asUGenInput;
features = features.asUGenInput;
metric = FluidOnsetSlice.prSelectMetric(metric);
if (metric.isNil or: metric.isUGen) {
("FluidBufOnsetSlice: % is not a recognised metric")
.format(metric).throw;
};
source.isNil.if {"FluidBufOnsetFeature: Invalid source buffer".throw};
features.isNil.if {"FluidBufOnsetFeature: Invalid features buffer".throw};

@ -1,27 +1,37 @@
FluidBufOnsetSlice : FluidBufProcessor {
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0|
*kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
source = source.asUGenInput;
indices = indices.asUGenInput;
metric = FluidOnsetSlice.prSelectMetric(metric) ?? {
("FluidBufOnsetSlice: % is not a recognised metric")
.format(metric).throw;
};
source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw};
indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw};
^FluidProxyUgen.kr(\FluidBufOnsetSliceTrigger, -1, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking);
}
*process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
source = source.asUGenInput;
indices = indices.asUGenInput;
metric = FluidOnsetSlice.prSelectMetric(metric);
if (metric.isNil or: metric.isUGen) {
("FluidBufOnsetSlice: % is not a recognised metric")
.format(metric).throw;
};
source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw};
indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw};
^this.new(
server, nil, [indices]
).processList(
@ -30,15 +40,20 @@ FluidBufOnsetSlice : FluidBufProcessor {
}
*processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action|
var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize};
source = source.asUGenInput;
indices = indices.asUGenInput;
metric = FluidOnsetSlice.prSelectMetric(metric);
if (metric.isNil or: metric.isUGen) {
("FluidBufOnsetSlice: % is not a recognised metric")
.format(metric).throw;
};
source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw};
indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw};
^this.new(
server, nil, [indices]
).processList(

@ -1,13 +1,19 @@
FluidNoveltyFeature : FluidRTUGen {
*kr { arg in = 0, algorithm = 0, kernelSize = 3, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1, maxKernelSize, maxFilterSize;
maxKernelSize = maxKernelSize ? kernelSize;
maxFilterSize = maxFilterSize ? filterSize;
maxKernelSize = maxKernelSize ? kernelSize;
maxFilterSize = maxFilterSize ? filterSize;
algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm) ?? {
("FluidNoveltySlice: % is not a recognised algorithm").format(algorithm);
};
^this.multiNew('control', in.asAudioRateInput(this), algorithm, kernelSize, maxKernelSize, filterSize, maxFilterSize, windowSize, hopSize, fftSize, maxFFTSize)
}
checkInputs {
if([\scalar, \control].includes(inputs.at(1).rate).not) {
^(": invalid algorithm");
};
if(inputs.at(9).rate != 'scalar') {
^(": maxFFTSize cannot be modulated.");
};

@ -1,20 +1,35 @@
FluidNoveltySlice : FluidRTUGen {
const <spectrum = 0;
const <mfcc = 1;
const <chroma = 2;
const <pitch = 3;
const <loudness = 4;
const <algorithms = #[\spectrum, \mfcc, \chroma, \pitch, \loudness];
*prSelectAlgorithm { |sym|
if (sym.isUGen) { ^sym };
if (sym.isNumber) {
if (sym >= 0 && (sym < algorithms.size)) {
^sym
} {
^nil
}
};
^algorithms.indexOf(sym.asSymbol)
}
*ar { arg in = 0, algorithm = 0, kernelSize = 3, threshold = 0.8, filterSize = 1, minSliceLength = 2, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1, maxKernelSize, maxFilterSize;
maxKernelSize = maxKernelSize ? kernelSize;
maxFilterSize = maxFilterSize ? filterSize;
maxFilterSize = maxFilterSize ? filterSize;
algorithm = this.prSelectAlgorithm(algorithm) ?? {
("FluidNoveltySlice: % is not a recognised algorithm").format(algorithm);
};
^this.multiNew('audio', in.asAudioRateInput(this), algorithm, kernelSize, maxKernelSize, threshold, filterSize, maxFilterSize, minSliceLength, windowSize, hopSize, fftSize, maxFFTSize)
}
checkInputs {
if([\scalar, \control].includes(inputs.at(1).rate).not) {
^(": invalid algorithm");
};
if(inputs.at(11).rate != 'scalar') {
^(": maxFFTSize cannot be modulated.");
};

@ -1,8 +1,16 @@
FluidOnsetFeature : FluidRTUGen {
*kr { arg in = 0, metric = 0, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1;
metric = FluidOnsetSlice.prSelectMetric(metric) ?? {
("% is not a recognised metric").format(metric);
};
^this.multiNew('control', in.asAudioRateInput(this), metric, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize)
}
checkInputs {
if([\scalar, \control].includes(inputs.at(1).rate).not) {
^(": invalid metric");
};
if(inputs.at(7).rate != 'scalar') {
^(": maxFFTSize cannot be modulated.");
};

@ -1,20 +1,42 @@
FluidOnsetSlice : FluidRTUGen {
const <power = 0;
const <hfc = 1;
const <flux = 2;
const <mkl = 3;
const <is = 4;
const <cosine = 5;
const <phase = 6;
const <wphase = 7;
const <complex = 8;
const <rcomplex = 9;
const <metrics = #[
\power,
\hfc,
\flux,
\mkl,
\is,
\cosine,
\phase,
\wphase,
\complex,
\rcomplex,
];
*prSelectMetric { |sym|
if (sym.isUGen) { ^sym };
if (sym.isNumber) {
if (sym >= 0 && (sym < metrics.size)) {
^sym
} {
^nil
}
};
^metrics.indexOf(sym.asSymbol)
}
*ar { arg in = 0, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1;
metric = this.prSelectMetric(metric) ?? {
("% is not a recognised metric").format(metric);
};
^this.multiNew('audio', in.asAudioRateInput(this), metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize)
}
checkInputs {
if([\scalar, \control].includes(inputs.at(1).rate).not) {
^(": invalid metric");
};
if(inputs.at(9).rate != 'scalar') {
^(": maxFFTSize cannot be modulated.");
};

@ -87,7 +87,7 @@ FluidPlotter : FluidViewer {
if(dict_internal.at(identifier).notNil,{
"FluidPlotter::addPoint_ There already exists a point with identifier %. Point not added. Use setPoint_ to overwrite existing points.".format(identifier).warn;
},{
this.setPoint_(identifier,x,y,size,color);
this.setPoint_(identifier,x,y,color,size);
});
}

@ -63,10 +63,7 @@ FluidUMAP : FluidModelObject {
this.prSendMsg(this.transformPointMsg(sourceBuffer,destBuffer));
}
kr{|trig, inputBuffer,outputBuffer,numDimensions|
numDimensions = numDimensions ? this.numDimensions;
this.numDimensions_(numDimensions);
kr{|trig, inputBuffer,outputBuffer|
^FluidUMAPQuery.kr(trig,
this,

@ -17,7 +17,7 @@ y = {
)
// isolate just sines or residual;
~song = Buffer.readChannel(s,FluidFilesPath("Tremblay-beatRemember.wav"),channels:[0]);
~song = Buffer.readChannel(s,FluidFilesPath("Tremblay-BeatRemember.wav"),channels:[0]);
(
y = {
@ -37,7 +37,7 @@ y.set(\mix,0);
y.set(\mix,1);
// a stereo example
~song = Buffer.read(s,FluidFilesPath("Tremblay-beatRemember.wav"));
~song = Buffer.read(s,FluidFilesPath("Tremblay-BeatRemember.wav"));
(
y = {
@ -85,7 +85,7 @@ FluidHPSS separates a sound into "harmonic" and "percussive" components. This ca
*/
//load a soundfile to play
~buf = Buffer.readChannel(s,FluidFilesPath("Tremblay-beatRemember.wav"),channels:[0]);
~buf = Buffer.readChannel(s,FluidFilesPath("Tremblay-BeatRemember.wav"),channels:[0]);
// run with basic parameters (left is harmonic, right is percussive)
{FluidHPSS.ar(PlayBuf.ar(1,~buf,loop:1))}.play

@ -59,7 +59,7 @@ Routine{
Routine{
var drums = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav"));
var voice = Buffer.read(s,FluidFilesPath("Tremblay-AaS-VoiceQC-B2K-M.wav"));
var song = Buffer.read(s,FluidFilesPath("Tremblay-beatRemember.wav"));
var song = Buffer.read(s,FluidFilesPath("Tremblay-BeatRemember.wav"));
s.sync;
"drums through the drums bases as filters".postln;

@ -74,8 +74,6 @@ FluidBufMelBands.process(s,~audio, features: ~melfeatures,action: {\done.postln;
//prepare the normalizers and the neural net for inverse query
(
~normalView.invert = 1;
~normalizer.invert = 1;
~mlp.tapIn = 2;
~mlp.tapOut = -1;
)
@ -114,9 +112,9 @@ v.mouseMoveAction = {|view, x, y|
~kdtree.kNearest(~queryPoint, action: {|nearest| //retrieve the nearest point
~norm.getPoint(nearest, ~dpN, action: { //get the normalised 40d
~raw.getPoint(nearest, ~datapoint, action: { // get the original 40d
~normalView.transformPoint(~queryPoint, ~dQueryPoint, action: { //denormalise the 2d coordinate to get the right range of values for the MLP
~normalView.inverseTransformPoint(~queryPoint, ~dQueryPoint, action: { //denormalise the 2d coordinate to get the right range of values for the MLP
~mlp.predictPoint(~dQueryPoint, ~dpMLPn, action: { //predict from the middle (2d) to the normalised output (40d)
~normalizer.transformPoint(~dpMLPn, ~dpMLP, action: { //denormalised the 40d
~normalizer.inverseTransformPoint(~dpMLPn, ~dpMLP, action: { //denormalised the 40d
~datapoint.getn(0,40,{|x|~arrayRawN = x; //retrieve the nearest
~dpN.getn(0,40,{|x|~arrayRawNn = x; // retrieve the normalised nearest
~dpMLPn.getn(0,40,{|x|~arrayMLPn = x; //retrieve the predicted normalised 40d
@ -158,4 +156,4 @@ w.drawFunc = {
};
w.refresh;
w.front;
)
)

@ -425,7 +425,7 @@ FluidWaveform(featureBuffer:~bases,bounds:Rect(0,0,1200,300));
// if we play a different source through FluidNMFFilter, it will try to decompose that real-time signal according to the bases
// it is given (in our case the bases from the drum loop)
~song = Buffer.readChannel(s,FluidFilesPath("Tremblay-beatRemember.wav"),channels:[0]);
~song = Buffer.readChannel(s,FluidFilesPath("Tremblay-BeatRemember.wav"),channels:[0]);
(
{

@ -1,7 +1,7 @@
TITLE:: FluidDataSetWr
summary:: Write to FluidDataSet on the server
categories:: Libraries>FluidCorpusManipulation
related:: Classes/FLuidDataSet
related:: Classes/FluidDataSet
DESCRIPTION::
A UGen that adds data points with associated identifiers to a link::Classes/FluidDataSet:: Internally, this calls code::setPoint::, so IDs that already exist will be overwritten, and new IDs will be added. The actual work is done on the server's command queue, rather than the real-thread.
@ -21,10 +21,10 @@ CLASSMETHODS::
private:: *new1
METHOD:: kr
The equivalent of calling link::Classes/FluidDataSet#-addPoint::, but within a link::Classes/Synth::
The equivalent of calling link::Classes/FluidDataSet#-setPoint::, but within a link::Classes/Synth::
ARGUMENT:: dataset
An instance of link::Classes/FluidDataSet:: or an instance's name.
An instance of link::Classes/FluidDataSet::
ARGUMENT:: idPrefix
A string or symbol with a prefix for generated identifiers.
@ -67,58 +67,38 @@ s.reboot;
(
~ds.clear;
OSCFunc({
"FluidDataSetWr help: all points written".postln;
~ds.print
"FluidDataSetWr help: all points written".postln;
~ds.print
},'/datasetwrdone').oneShot;
{ |n|
var b = LocalBuf.newFrom([0,1,2,3]);
var trig = Impulse.kr(ControlRate.ir / 8);
var idx = Stepper.kr(trig,min:-1, max:n); //we need to start at -1 to catch the first increment
4.collect{|i| BufWr.kr([(4 * idx) + i],b,i)};
FluidDataSetWr.kr(~ds,idNumber:idx,buf:b,trig:trig);
SendReply.kr(idx >= (n-1), '/datasetwrdone');
FreeSelf.kr(idx >= (n-1));
}.play(s,args:[n:100]);
{
arg n;
var buf = LocalBuf(4);
var trig = Impulse.kr(ControlRate.ir / 8); // can't go any faster
var idx = Stepper.kr(trig,min:-1, max:n); //we need to start at -1 to catch the first increment
FluidKrToBuf.kr((idx * 4) + [0,1,2,3],buf);
FluidDataSetWr.kr(~ds,"point-",idNumber:idx,buf:buf,trig:trig);
SendReply.kr(idx >= (n-1), '/datasetwrdone');
FreeSelf.kr(idx >= (n-1));
}.play(args:[\n,100]);
)
::
//it printed with the return function
//Again, but as fast as possible using a feedback of the trigger we are given when the writing is done
(
~ds.clear;
OSCFunc({
"FluidDataSetWr help: all points written".postln;
~ds.print
},'/datasetwrdone').oneShot;
{ |n|
var b = LocalBuf.newFrom([0,1,2,3]);
var trig = LocalIn.kr(1,1);
var idx = Stepper.kr(trig,min:-1, max:n);
var wr = FluidDataSetWr.kr(~ds,idNumber:idx,buf:b,trig:trig);
4.collect{|i| BufWr.kr([(4 * idx) + i],b,i)};
LocalOut.kr(Done.kr(wr));
SendReply.kr(idx >= (n-1), '/datasetwrdone');
FreeSelf.kr(idx >= (n-1));
}.play(s,args:[n:100]);
)
strong::incremental buffer writing - sky is the limit::
code::
// incremental buffer writing - sky is the limit
~ds.clear
// start the entry maker, trigging twice a second
(
~ds.clear;
{
var buf = LocalBuf.newFrom([0,1,2,3]);
var noise = 4.collect{WhiteNoise.kr()};
var trig = Impulse.kr(2);
var count = PulseCount.kr(trig);
4.do{|i|
BufWr.kr(noise[i], buf, DC.kr(i));
};
FluidDataSetWr.kr(~ds, idNumber: count, trig: trig, buf:buf);
}.play(s);
var buf = LocalBuf(4);
var trig = Impulse.kr(30);
var count = PulseCount.kr(trig) - 1;
FluidKrToBuf.kr(WhiteNoise.kr(1.dup(4)),buf);
FluidDataSetWr.kr(~ds,"point-",idNumber: count, trig: trig, buf:buf);
}.play;
)
//print a few times
@ -132,18 +112,24 @@ OSCFunc({
~ds.print;
~ds.clear
// circular writing
::
strong::circular writing::
Each time link::Classes/FluidDataSetWr:: is triggered it is like the link::Classes/FluidDataSet#-setPoint:: method so if the identifier does not exist it creates it. If the identifier does it exist then it updates it with the new values.
By looping code::idNumber:: values, we can use a link::Classes/FluidDataSet:: similar to a "circle buffer", always have the most recent code::n:: points in it that we want.
code::
// always have only the most recent 10 points in the buffer
(
{
var buf = LocalBuf.newFrom([0,1,2,3]);
var noise = 4.collect{WhiteNoise.kr()};
var noise = WhiteNoise.kr(1.dup(4)) + Sweep.kr(1,1);
var trig = Impulse.kr(2);
var count = Stepper.kr(trig, min: 0, max: 9, resetval: -1); //0 to 9, starting at -1 to catch the first entry
4.do{|i|
BufWr.kr(noise[i], buf, DC.kr(i));
};
FluidDataSetWr.kr(~ds, idNumber: count, trig: trig, buf:buf);
}.play(s);
FluidKrToBuf.kr(noise,buf);
FluidDataSetWr.kr(~ds, "point-",idNumber: count, trig: trig, buf:buf);
}.play;
)
//print regularly to see a specific identifier being overwritten

@ -293,7 +293,7 @@ s.waitForBoot{
~resynths = {Buffer(s)} ! ~n_components;
s.sync;
FluidBufNMF.processBlocking(s,~audio,resynth:~resynth,activations:~activations,components:~n_components);
FluidBufNMF.processBlocking(s,~audio,resynth:~resynth,resynthMode: 1,activations:~activations,components:~n_components);
~n_components.do{
arg i;

@ -166,10 +166,10 @@ FluidBufCompose.process(s,~loader.buffer,a,(b-a),numChans: 1, destination: ~targ
~flatbuf[1].getn(0,182,{|x|~curatedWBuf = Buffer.loadCollection(s, x[[0,1,4,6,7,8,11,13].collect{|x|var y=x*13+1;(y..(y+11))}.flat].postln)})
//find its nearest neighbours
~tree.kNearest(~flatbuf[0],{|x| ~friends = x.postln;})
~treeW.kNearest(~flatbuf[1],{|x| ~friendsW = x.postln;})
~treeC.kNearest(~curatedBuf,{|x| ~friendsC = x.postln;})
~treeCW.kNearest(~curatedWBuf,{|x| ~friendsCW = x.postln;})
~tree.kNearest(~flatbuf[0],action:{|x| ~friends = x.postln;})
~treeW.kNearest(~flatbuf[1],action:{|x| ~friendsW = x.postln;})
~treeC.kNearest(~curatedBuf,action:{|x| ~friendsC = x.postln;})
~treeCW.kNearest(~curatedWBuf,action:{|x| ~friendsCW = x.postln;})
// play them in a row

@ -4,7 +4,7 @@
//slightly oversegment with novelty
//segments should still make sense but might cut a few elements in 2 or 3
~slicer = FluidSliceCorpus({ |src,start,num,dest| FluidBufNoveltySlice.kr(src,start,num,indices:dest, feature: 1, kernelSize: 29, threshold: 0.1, filterSize: 5, hopSize: 128, blocking: 1)});
~slicer = FluidSliceCorpus({ |src,start,num,dest| FluidBufNoveltySlice.kr(src, start, num, indices:dest, algorithm:1, kernelSize:29, threshold:0.1, filterSize:5, hopSize:128, blocking:1)});
~slicer.play(s, ~loader.buffer,~loader.index);
//test the segmentation by looping them

@ -297,7 +297,7 @@ FluidBufMelBands.process(s, ~inBuf, features: ~inBufMels, action: {
FluidBufFlatten.process(s, ~inBufStats, destination:~inBufFlat, action: {
FluidBufCompose.process(s, ~inBufFlat, numFrames: ~numMelBands, destination: ~inBufComp, action: {
~standardizer.transformPoint(~inBufComp, ~inBufStand, {
~tree.kNearest(~inBufStand,{ |a|a.postln;~nearest = a;})
~tree.kNearest(~inBufStand,action:{ |a|a.postln;~nearest = a;})
})
})
})

@ -74,8 +74,6 @@ FluidBufMelBands.process(s,~audio, features: ~melfeatures,action: {\done.postln;
//prepare the normalizers and the neural net for inverse query
(
~normalView.invert = 1;
~normalizer.invert = 1;
~mlp.tapIn = 2;
~mlp.tapOut = -1;
)
@ -114,9 +112,9 @@ v.mouseMoveAction = {|view, x, y|
~kdtree.kNearest(~queryPoint, action: {|nearest| //retrieve the nearest point
~norm.getPoint(nearest, ~dpN, action: { //get the normalised 40d
~raw.getPoint(nearest, ~datapoint, action: { // get the original 40d
~normalView.transformPoint(~queryPoint, ~dQueryPoint, action: { //denormalise the 2d coordinate to get the right range of values for the MLP
~normalView.inverseTransformPoint(~queryPoint, ~dQueryPoint, action: { //denormalise the 2d coordinate to get the right range of values for the MLP
~mlp.predictPoint(~dQueryPoint, ~dpMLPn, action: { //predict from the middle (2d) to the normalised output (40d)
~normalizer.transformPoint(~dpMLPn, ~dpMLP, action: { //denormalised the 40d
~normalizer.inverseTransformPoint(~dpMLPn, ~dpMLP, action: { //denormalised the 40d
~datapoint.getn(0,40,{|x|~arrayRawN = x; //retrieve the nearest
~dpN.getn(0,40,{|x|~arrayRawNn = x; // retrieve the normalised nearest
~dpMLPn.getn(0,40,{|x|~arrayMLPn = x; //retrieve the predicted normalised 40d

Loading…
Cancel
Save