diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 2a3bd70..a9a8d24 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -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 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2e33692..c54d4d4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -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 diff --git a/release-packaging/Classes/FluidBufNoveltyFeature.sc b/release-packaging/Classes/FluidBufNoveltyFeature.sc index 868c37a..1fca9ac 100644 --- a/release-packaging/Classes/FluidBufNoveltyFeature.sc +++ b/release-packaging/Classes/FluidBufNoveltyFeature.sc @@ -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] diff --git a/release-packaging/Classes/FluidBufNoveltySlice.sc b/release-packaging/Classes/FluidBufNoveltySlice.sc index b53820e..82952fe 100644 --- a/release-packaging/Classes/FluidBufNoveltySlice.sc +++ b/release-packaging/Classes/FluidBufNoveltySlice.sc @@ -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( diff --git a/release-packaging/Classes/FluidBufOnsetFeature.sc b/release-packaging/Classes/FluidBufOnsetFeature.sc index 6ea08b0..1b3235c 100644 --- a/release-packaging/Classes/FluidBufOnsetFeature.sc +++ b/release-packaging/Classes/FluidBufOnsetFeature.sc @@ -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}; diff --git a/release-packaging/Classes/FluidBufOnsetSlice.sc b/release-packaging/Classes/FluidBufOnsetSlice.sc index 2f9a754..0a3f6d7 100644 --- a/release-packaging/Classes/FluidBufOnsetSlice.sc +++ b/release-packaging/Classes/FluidBufOnsetSlice.sc @@ -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( diff --git a/release-packaging/Classes/FluidNoveltyFeature.sc b/release-packaging/Classes/FluidNoveltyFeature.sc index ddb6313..a83df30 100644 --- a/release-packaging/Classes/FluidNoveltyFeature.sc +++ b/release-packaging/Classes/FluidNoveltyFeature.sc @@ -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."); }; diff --git a/release-packaging/Classes/FluidNoveltySlice.sc b/release-packaging/Classes/FluidNoveltySlice.sc index 9dd78df..da43d54 100644 --- a/release-packaging/Classes/FluidNoveltySlice.sc +++ b/release-packaging/Classes/FluidNoveltySlice.sc @@ -1,20 +1,35 @@ FluidNoveltySlice : FluidRTUGen { - const = 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."); }; diff --git a/release-packaging/Classes/FluidOnsetFeature.sc b/release-packaging/Classes/FluidOnsetFeature.sc index 894b3e9..d5b7786 100644 --- a/release-packaging/Classes/FluidOnsetFeature.sc +++ b/release-packaging/Classes/FluidOnsetFeature.sc @@ -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."); }; diff --git a/release-packaging/Classes/FluidOnsetSlice.sc b/release-packaging/Classes/FluidOnsetSlice.sc index 91dd2c8..507e128 100644 --- a/release-packaging/Classes/FluidOnsetSlice.sc +++ b/release-packaging/Classes/FluidOnsetSlice.sc @@ -1,20 +1,42 @@ FluidOnsetSlice : FluidRTUGen { - const = 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."); }; diff --git a/release-packaging/Classes/FluidPlotter.sc b/release-packaging/Classes/FluidPlotter.sc index d78a474..579c538 100644 --- a/release-packaging/Classes/FluidPlotter.sc +++ b/release-packaging/Classes/FluidPlotter.sc @@ -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); }); } diff --git a/release-packaging/Classes/FluidUMAP.sc b/release-packaging/Classes/FluidUMAP.sc index 878ee99..24f632c 100644 --- a/release-packaging/Classes/FluidUMAP.sc +++ b/release-packaging/Classes/FluidUMAP.sc @@ -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, diff --git a/release-packaging/Examples/Guides/Decomposition Examples.scd b/release-packaging/Examples/Guides/Decomposition Examples.scd index 44c8cec..84e06d1 100644 --- a/release-packaging/Examples/Guides/Decomposition Examples.scd +++ b/release-packaging/Examples/Guides/Decomposition Examples.scd @@ -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 diff --git a/release-packaging/Examples/Guides/NMF Overview.scd b/release-packaging/Examples/Guides/NMF Overview.scd index d75c22e..8c82510 100644 --- a/release-packaging/Examples/Guides/NMF Overview.scd +++ b/release-packaging/Examples/Guides/NMF Overview.scd @@ -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; diff --git a/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd b/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd index 10e8ff3..3663601 100644 --- a/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd +++ b/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd @@ -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; -) +) \ No newline at end of file diff --git a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp index d5fae68..3497c2b 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp @@ -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]); ( { diff --git a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp index ba674ab..ef71b59 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp @@ -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 diff --git a/release-packaging/HelpSource/Classes/FluidWaveform.schelp b/release-packaging/HelpSource/Classes/FluidWaveform.schelp index 71466f5..7de7f4c 100644 --- a/release-packaging/HelpSource/Classes/FluidWaveform.schelp +++ b/release-packaging/HelpSource/Classes/FluidWaveform.schelp @@ -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; diff --git a/test/10a-weighted-MFCCs-comparison.scd b/test/10a-weighted-MFCCs-comparison.scd index 38088b7..db3f0a6 100644 --- a/test/10a-weighted-MFCCs-comparison.scd +++ b/test/10a-weighted-MFCCs-comparison.scd @@ -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 diff --git a/test/12-windowed-clustered-segmentation.scd b/test/12-windowed-clustered-segmentation.scd index ac2b8ba..95dad07 100644 --- a/test/12-windowed-clustered-segmentation.scd +++ b/test/12-windowed-clustered-segmentation.scd @@ -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 diff --git a/test/13-massive-parallelisation-example.scd b/test/13-massive-parallelisation-example.scd index 294a041..e642eac 100644 --- a/test/13-massive-parallelisation-example.scd +++ b/test/13-massive-parallelisation-example.scd @@ -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;}) }) }) }) diff --git a/test/8c-mlp-regressor-as-dim-redux.scd b/test/8c-mlp-regressor-as-dim-redux.scd index 4d9ee1f..3663601 100644 --- a/test/8c-mlp-regressor-as-dim-redux.scd +++ b/test/8c-mlp-regressor-as-dim-redux.scd @@ -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