├── .clang-format ├── .gitattributes ├── .github └── workflows │ ├── feature.yml │ ├── nightly.yaml │ └── release.yml ├── .gitignore ├── CMakeLists.txt ├── LICENSE.md ├── QuickStart.md ├── README.md ├── icon.png ├── include ├── FluidSCWrapper.hpp ├── SCBufferAdaptor.hpp ├── clients │ └── rt │ │ └── FluidDataSetWr.hpp └── wrapper │ ├── ArgsFromClient.hpp │ ├── ArgsToClient.hpp │ ├── BufferFuncs.hpp │ ├── CopyReplyAddress.cpp │ ├── CopyReplyAddress.hpp │ ├── DeriveBaseClass.hpp │ ├── Messaging.hpp │ ├── Meta.hpp │ ├── NonRealtime.hpp │ ├── RealTimeBase.hpp │ ├── Realtime.hpp │ └── SCWorldAllocator.hpp ├── release-packaging ├── Classes │ ├── FluidAmpFeature.sc │ ├── FluidAmpGate.sc │ ├── FluidAmpSlice.sc │ ├── FluidAudioTransport.sc │ ├── FluidBufAmpFeature.sc │ ├── FluidBufAmpGate.sc │ ├── FluidBufAmpSlice.sc │ ├── FluidBufAudioTransport.sc │ ├── FluidBufChroma.sc │ ├── FluidBufCompose.sc │ ├── FluidBufFlatten.sc │ ├── FluidBufHPSS.sc │ ├── FluidBufLoudness.sc │ ├── FluidBufMFCC.sc │ ├── FluidBufMelBands.sc │ ├── FluidBufNMF.sc │ ├── FluidBufNMFCross.sc │ ├── FluidBufNMFSeed.sc │ ├── FluidBufNoveltyFeature.sc │ ├── FluidBufNoveltySlice.sc │ ├── FluidBufOnsetFeature.sc │ ├── FluidBufOnsetSlice.sc │ ├── FluidBufPitch.sc │ ├── FluidBufSTFT.sc │ ├── FluidBufScale.sc │ ├── FluidBufSelect.sc │ ├── FluidBufSelectEvery.sc │ ├── FluidBufSineFeature.sc │ ├── FluidBufSines.sc │ ├── FluidBufSpectralShape.sc │ ├── FluidBufStats.sc │ ├── FluidBufThreadDemo.sc │ ├── FluidBufThresh.sc │ ├── FluidBufToKr.sc │ ├── FluidBufTransientSlice.sc │ ├── FluidBufTransients.sc │ ├── FluidChroma.sc │ ├── FluidCorpusBuilders.sc │ ├── FluidDataSet.sc │ ├── FluidDataSetQuery.sc │ ├── FluidDataSetWr.sc │ ├── FluidFilesPath.sc │ ├── FluidGain.sc │ ├── FluidGrid.sc │ ├── FluidHPSS.sc │ ├── FluidKDTree.sc │ ├── FluidKMeans.sc │ ├── FluidKNNClassifier.sc │ ├── FluidKNNRegressor.sc │ ├── FluidLabelSet.sc │ ├── FluidLoudness.sc │ ├── FluidMDS.sc │ ├── FluidMFCC.sc │ ├── FluidMLP.sc │ ├── FluidManipulationJSON.sc │ ├── FluidMelBands.sc │ ├── FluidMessageResponse.sc │ ├── FluidNMFFilter.sc │ ├── FluidNMFMatch.sc │ ├── FluidNMFMorph.sc │ ├── FluidNRTProcess.sc │ ├── FluidNormalize.sc │ ├── FluidNoveltyFeature.sc │ ├── FluidNoveltySlice.sc │ ├── FluidOnsetFeature.sc │ ├── FluidOnsetSlice.sc │ ├── FluidPCA.sc │ ├── FluidPitch.sc │ ├── FluidPlotter.sc │ ├── FluidRobustScale.sc │ ├── FluidSKMeans.sc │ ├── FluidSTFTPass.sc │ ├── FluidServerCache.sc │ ├── FluidServerObject.sc │ ├── FluidSineFeature.sc │ ├── FluidSines.sc │ ├── FluidSpectralShape.sc │ ├── FluidStandardize.sc │ ├── FluidStats.sc │ ├── FluidTransientSlice.sc │ ├── FluidTransients.sc │ ├── FluidUMAP.sc │ └── FluidWaveform.sc ├── Examples │ ├── Guides │ │ ├── Audio Query (Replace Drum Sounds with other Sounds, with Scalers).scd │ │ ├── Buffer Slicing Analysis and Plotting.scd │ │ ├── Classify Timbre with a Neural Network.scd │ │ ├── DataSetQuery to Filter Out some Data Points.scd │ │ ├── Decomposition Examples.scd │ │ ├── Dimensionality Reduction (2D sound browsing).scd │ │ ├── NMF Overview.scd │ │ ├── Neural Network Controls Synth from 2D space (all on server).scd │ │ ├── Neural Network Predicts FM Params from Audio Analysis.scd │ │ └── Weighted Statistical Analysis.scd │ ├── buffer_compositing │ │ ├── bufcompose-MS-FIR.scd │ │ └── bufcomposemacros.scd │ ├── dataset │ │ └── 1-learning examples │ │ │ ├── 10b-weighted-pitch-comparison.scd │ │ │ ├── 7a-making-datasets-with-json.scd │ │ │ ├── 8a-mlp-didactic.scd │ │ │ ├── 8c-mlp-regressor-as-dim-redux.scd │ │ │ └── 9-regressor-comparison.scd │ ├── nmf │ │ ├── JiT-NMF-classifier.scd │ │ ├── JiT-NMF.scd │ │ ├── nmfmatch-object-finding.scd │ │ └── nmfmatch-pretrained-piano.scd │ └── segmenting │ │ └── nb_of_slices.scd └── HelpSource │ ├── Classes │ ├── FluidBufToKr.schelp │ ├── FluidDataSetWr.schelp │ ├── FluidFilesPath.schelp │ ├── FluidKrToBuf.schelp │ ├── FluidLoadFolder.schelp │ ├── FluidManipulationClient.schelp │ ├── FluidPlotter.schelp │ ├── FluidProcessSlices.schelp │ ├── FluidSliceCorpus.schelp │ └── FluidWaveform.schelp │ └── Guides │ ├── FluidBufMultiThreading.schelp │ └── FluidCorpusManipulation.schelp ├── sc-resources ├── bufToKrExample.json └── color-schemes │ ├── -credits.txt │ ├── CET-C1.csv │ ├── CET-C1s.csv │ ├── CET-C2.csv │ ├── CET-C2s.csv │ ├── CET-C3.csv │ ├── CET-C3s.csv │ ├── CET-C4.csv │ ├── CET-C4s.csv │ ├── CET-C5.csv │ ├── CET-C5s.csv │ ├── CET-C6.csv │ ├── CET-C6s.csv │ ├── CET-C7.csv │ ├── CET-C7s.csv │ ├── CET-CBC1.csv │ ├── CET-CBC2.csv │ ├── CET-CBD1.csv │ ├── CET-CBL1.csv │ ├── CET-CBL2.csv │ ├── CET-D01.csv │ ├── CET-D01A.csv │ ├── CET-D02.csv │ ├── CET-D03.csv │ ├── CET-D04.csv │ ├── CET-D06.csv │ ├── CET-D07.csv │ ├── CET-D08.csv │ ├── CET-D09.csv │ ├── CET-D10.csv │ ├── CET-D11.csv │ ├── CET-D12.csv │ ├── CET-D13.csv │ ├── CET-I1.csv │ ├── CET-I2.csv │ ├── CET-I3.csv │ ├── CET-L01.csv │ ├── CET-L02.csv │ ├── CET-L03.csv │ ├── CET-L04.csv │ ├── CET-L05.csv │ ├── CET-L06.csv │ ├── CET-L07.csv │ ├── CET-L08.csv │ ├── CET-L09.csv │ ├── CET-L10.csv │ ├── CET-L11.csv │ ├── CET-L12.csv │ ├── CET-L13.csv │ ├── CET-L14.csv │ ├── CET-L15.csv │ ├── CET-L16.csv │ ├── CET-L17.csv │ ├── CET-L18.csv │ ├── CET-L19.csv │ ├── CET-L20.csv │ ├── CET-R1.csv │ ├── CET-R2.csv │ ├── CET-R3.csv │ └── CET-R4.csv ├── scripts ├── MakeDevTree.cmake ├── MakePluginSources.cmake └── settings │ └── FluidManipulation.cpp.in └── test ├── 10a-weighted-MFCCs-comparison.scd ├── 10b-weighted-pitch-comparison.scd ├── 12-windowed-clustered-segmentation.scd ├── 13-massive-parallelisation-example.scd ├── 8b-mlp-synth-control.scd ├── 8c-mlp-regressor-as-dim-redux.scd ├── FluidBufToKr test.scd ├── FluidFilesPath_test.scd ├── FluidPlotter_test.scd ├── FluidWaveform raster scratch paper.scd ├── FluidWaveform_test.scd └── PCA_inverse_test.scd /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.cmake text 4 | *.cpp text 5 | *.csv text 6 | *.gitignore text 7 | *.hpp text 8 | *.in text 9 | *.json text 10 | *.md text 11 | *.sc text 12 | *.scd text 13 | *.schelp text 14 | *.txt text 15 | *.yaml text 16 | *.yml text 17 | 18 | *.png binary 19 | -------------------------------------------------------------------------------- /.github/workflows/feature.yml: -------------------------------------------------------------------------------- 1 | name: feature 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | 7 | concurrency: 8 | group: environment-${{ github.ref }} 9 | cancel-in-progress: true 10 | 11 | jobs: 12 | macbuild: 13 | runs-on: macos-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - uses: flucoma/actions/env@main 17 | - uses: flucoma/actions/sc@main 18 | with: 19 | branch: origin/main 20 | core_branch: origin/${{ github.ref_name }} 21 | build_type: "Test" 22 | 23 | - name: sign binaries 24 | uses: flucoma/actions/distribution@main 25 | with: 26 | glob: '-e scx' 27 | package: 'install' 28 | output_type: 'dmg' 29 | output: FluCoMa-SC-Mac-nightly 30 | cert: ${{ secrets.CERT }} 31 | certpwd: ${{ secrets.CERTPWD }} 32 | teamid: ${{ secrets.WWDRTEAMID }} 33 | apppwd: ${{ secrets.APPSTORECONNECTPWD }} 34 | appusr: ${{ secrets.APPSTORECONNECTUSERNAME }} 35 | 36 | - uses: actions/upload-artifact@v4.3.6 37 | with: 38 | name: macbuild 39 | path: install/FluCoMa-SC-Mac-nightly.dmg 40 | 41 | winbuild: 42 | runs-on: windows-latest 43 | steps: 44 | - uses: actions/checkout@v3 45 | - uses: flucoma/actions/env@main 46 | - uses: flucoma/actions/sc@main 47 | with: 48 | branch: origin/main 49 | core_branch: origin/${{ github.ref_name }} 50 | build_type: "Test" 51 | 52 | - name: remove pdb files 53 | run: Remove-Item install -Recurse -Include *.pdb 54 | 55 | - name: compress archive 56 | run: 7z a FluCoMa-SC-Windows-x64-nightly.zip FluidCorpusManipulation 57 | working-directory: install 58 | 59 | - uses: actions/upload-artifact@v4.3.6 60 | with: 61 | name: winbuild 62 | path: install/FluCoMa-SC-Windows-x64-nightly.zip 63 | 64 | 65 | linuxbuild: 66 | runs-on: ubuntu-22.04 67 | steps: 68 | - uses: actions/checkout@v3 69 | - uses: flucoma/actions/env@main 70 | - uses: flucoma/actions/sc@main 71 | with: 72 | branch: origin/main 73 | core_branch: origin/${{ github.ref_name }} 74 | build_type: "Test" 75 | 76 | - name: compress archive 77 | run: tar -zcvf FluCoMa-SC-Linux-x64-nightly.tar.gz FluidCorpusManipulation 78 | working-directory: install 79 | - uses: actions/upload-artifact@v4.3.6 80 | with: 81 | name: linuxbuild 82 | path: install/FluCoMa-SC-Linux-x64-nightly.tar.gz -------------------------------------------------------------------------------- /.github/workflows/nightly.yaml: -------------------------------------------------------------------------------- 1 | name: nightly 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ main, ci/** ] 7 | 8 | concurrency: 9 | group: environment-${{ github.ref }} 10 | cancel-in-progress: true 11 | 12 | jobs: 13 | macbuild: 14 | runs-on: macos-latest 15 | steps: 16 | - uses: actions/checkout@v3 17 | - uses: flucoma/actions/env@main 18 | - uses: flucoma/actions/sc@main 19 | with: 20 | branch: origin/main 21 | 22 | - name: sign binaries 23 | uses: flucoma/actions/distribution@main 24 | with: 25 | glob: '-e scx' 26 | package: 'install' 27 | output_type: 'dmg' 28 | output: FluCoMa-SC-Mac-nightly 29 | cert: ${{ secrets.CERT }} 30 | certpwd: ${{ secrets.CERTPWD }} 31 | teamid: ${{ secrets.WWDRTEAMID }} 32 | apppwd: ${{ secrets.APPSTORECONNECTPWD }} 33 | appusr: ${{ secrets.APPSTORECONNECTUSERNAME }} 34 | 35 | - uses: actions/upload-artifact@v4.3.6 36 | with: 37 | name: macbuild 38 | path: install/FluCoMa-SC-Mac-nightly.dmg 39 | 40 | winbuild: 41 | runs-on: windows-latest 42 | steps: 43 | - uses: actions/checkout@v3 44 | - uses: flucoma/actions/env@main 45 | - uses: flucoma/actions/sc@main 46 | with: 47 | branch: origin/main 48 | 49 | - name: remove pdb files 50 | run: Remove-Item install -Recurse -Include *.pdb 51 | 52 | - name: compress archive 53 | run: 7z a FluCoMa-SC-Windows-x64-nightly.zip FluidCorpusManipulation 54 | working-directory: install 55 | 56 | - uses: actions/upload-artifact@v4.3.6 57 | with: 58 | name: winbuild 59 | path: install/FluCoMa-SC-Windows-x64-nightly.zip 60 | 61 | 62 | linuxbuild: 63 | runs-on: ubuntu-22.04 64 | steps: 65 | - uses: actions/checkout@v3 66 | - uses: flucoma/actions/env@main 67 | - uses: flucoma/actions/sc@main 68 | with: 69 | branch: origin/main 70 | 71 | - name: compress archive 72 | run: tar -zcvf FluCoMa-SC-Linux-x64-nightly.tar.gz FluidCorpusManipulation 73 | working-directory: install 74 | - uses: actions/upload-artifact@v4.3.6 75 | with: 76 | name: linuxbuild 77 | path: install/FluCoMa-SC-Linux-x64-nightly.tar.gz 78 | 79 | release: 80 | runs-on: ubuntu-22.04 81 | needs: [macbuild, winbuild, linuxbuild] 82 | steps: 83 | 84 | - uses: actions/download-artifact@v4.1.7 85 | with: 86 | name: macbuild 87 | 88 | - uses: actions/download-artifact@v4.1.7 89 | with: 90 | name: winbuild 91 | 92 | - uses: actions/download-artifact@v4.1.7 93 | with: 94 | name: linuxbuild 95 | 96 | - uses: dev-drprasad/delete-tag-and-release@v0.2.1 97 | with: 98 | delete_release: true # default: false 99 | tag_name: nightly # tag name to delete 100 | env: 101 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 102 | 103 | - name: create release 104 | uses: ncipollo/release-action@v1 105 | with: 106 | name: FluCoMa SuperCollider Nightly Release 107 | artifacts: "FluCoMa*" 108 | 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 }}" 109 | tag: nightly 110 | prerelease: true 111 | draft: false 112 | allowUpdates: true 113 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | macbuild: 8 | runs-on: macos-latest 9 | steps: 10 | - uses: actions/checkout@v3 11 | - uses: flucoma/actions/env@main 12 | - uses: flucoma/actions/sc@main 13 | with: 14 | branch: origin/${{ github.ref_name }} 15 | 16 | - name: sign binaries 17 | uses: flucoma/actions/distribution@main 18 | with: 19 | glob: '-e scx' 20 | package: 'install' 21 | output_type: 'dmg' 22 | output: FluCoMa-SC-Mac 23 | cert: ${{ secrets.CERT }} 24 | certpwd: ${{ secrets.CERTPWD }} 25 | teamid: ${{ secrets.WWDRTEAMID }} 26 | apppwd: ${{ secrets.APPSTORECONNECTPWD }} 27 | appusr: ${{ secrets.APPSTORECONNECTUSERNAME }} 28 | 29 | - uses: actions/upload-artifact@v4.3.6 30 | with: 31 | name: macbuild 32 | path: install/FluCoMa-SC-Mac.dmg 33 | 34 | winbuild: 35 | runs-on: windows-latest 36 | steps: 37 | - uses: actions/checkout@v3 38 | - uses: flucoma/actions/env@main 39 | - uses: flucoma/actions/sc@main 40 | with: 41 | branch: origin/${{ github.ref_name }} 42 | 43 | - name: remove pdb files 44 | run: Remove-Item install -Recurse -Include *.pdb 45 | 46 | - name: compress archive 47 | run: 7z a FluCoMa-SC-Windows-x64.zip FluidCorpusManipulation 48 | working-directory: install 49 | 50 | - uses: actions/upload-artifact@v4.3.6 51 | with: 52 | name: winbuild 53 | path: install/FluCoMa-SC-Windows-x64.zip 54 | 55 | linuxbuild: 56 | runs-on: ubuntu-22.04 57 | outputs: 58 | version: ${{ steps.get-version.outputs.version }} 59 | steps: 60 | - uses: actions/checkout@v3 61 | - uses: flucoma/actions/env@main 62 | - uses: flucoma/actions/sc@main 63 | with: 64 | branch: origin/${{ github.ref_name }} 65 | 66 | - name: compress archive 67 | run: tar -zcvf FluCoMa-SC-Linux-x64.tar.gz FluidCorpusManipulation 68 | working-directory: install 69 | 70 | - uses: actions/upload-artifact@v4.3.6 71 | with: 72 | name: linuxbuild 73 | path: install/FluCoMa-SC-Linux-x64.tar.gz 74 | 75 | - id: get-version 76 | run: echo "version=$(cat flucoma.version.rc)" >> $GITHUB_OUTPUT 77 | working-directory: build/_deps/flucoma-core-src 78 | 79 | release: 80 | runs-on: ubuntu-22.04 81 | needs: [macbuild, winbuild, linuxbuild] 82 | 83 | steps: 84 | - uses: actions/download-artifact@v4.1.7 85 | with: 86 | name: macbuild 87 | 88 | - uses: actions/download-artifact@v4.1.7 89 | with: 90 | name: winbuild 91 | 92 | - uses: actions/download-artifact@v4.1.7 93 | with: 94 | name: linuxbuild 95 | 96 | - name: delete pre-existing release 97 | uses: dev-drprasad/delete-tag-and-release@v0.2.1 98 | with: 99 | delete_release: true # default: false 100 | tag_name: ${{ needs.linuxbuild.outputs.version }} # tag name to delete 101 | env: 102 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 103 | 104 | - name: package and upload 105 | uses: softprops/action-gh-release@v1 106 | with: 107 | name: ${{ needs.linuxbuild.outputs.version }} 108 | body: "This is a release build of the FluCoMa SuperCollider package. The build hash is ${{ github.sha }}" 109 | files: FluCoMa* 110 | prerelease: true 111 | tag_name: ${{ needs.linuxbuild.outputs.version }} 112 | target_commitish: ${{ github.sha }} 113 | draft: false 114 | 115 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build* 2 | **/build/* 3 | **/.DS_Store 4 | release-packaging/Plugins 5 | release-packaging/AudioFiles 6 | release-packaging/Resources 7 | *.scx 8 | .vs/ 9 | Darwin/* 10 | Linux/* 11 | Windows/* 12 | install/ 13 | .vscode 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright University of Huddersfield 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /QuickStart.md: -------------------------------------------------------------------------------- 1 | # Instructions for the SuperCollider version of the Fluid Corpus Manipulation toolbox 2 | 3 | ## How to start: 4 | 5 | 1) move the full FluidCorpusManipulation folder in your Extensions folder (see the 'Using Extensions' Guide in the documentation), and restart SuperCollider. 6 | 7 | There is a Guide giving the overview of the toolbox. Full documentation is also available, as well as an Examples folder in the package. 8 | 9 | #### Enjoy! 10 | 11 | > 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). 12 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/flucoma/flucoma-sc/8d39e678469f09b50b501fdd0c6ff5f74adecdbc/icon.png -------------------------------------------------------------------------------- /include/clients/rt/FluidDataSetWr.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace fluid { 20 | namespace client { 21 | namespace datasetwr { 22 | 23 | enum { kDataSet, kIDPrefix, kIDNumber, kBuffer }; 24 | 25 | constexpr std::initializer_list idNumberDefaults{0, 0}; 26 | 27 | constexpr auto DataSetWrParams = defineParameters( 28 | DataSetClientRef::makeParam("dataSet", "DataSet ID"), 29 | StringParam("idPrefix", "ID Prefix"), 30 | LongArrayParam("idNumber", "ID Counter Offset", idNumberDefaults), 31 | BufferParam("buf", "Data Buffer")); 32 | 33 | class DataSetWriterClient : public FluidBaseClient, OfflineIn, OfflineOut { 34 | 35 | public: 36 | using ParamDescType = decltype(DataSetWrParams); 37 | 38 | using ParamSetViewType = ParameterSetView; 39 | std::reference_wrapper mParams; 40 | 41 | void setParams(ParamSetViewType &p) { mParams = p; } 42 | 43 | template auto &get() const { 44 | return mParams.get().template get(); 45 | } 46 | 47 | static constexpr auto &getParameterDescriptors() { return DataSetWrParams; } 48 | 49 | DataSetWriterClient(ParamSetViewType &p, FluidContext&) : mParams(p) {} 50 | 51 | template Result process(FluidContext &) { 52 | auto dataset = get().get(); 53 | if (auto datasetPtr = dataset.lock()) { 54 | std::string idPrefix = std::string(get()); 55 | auto &idNumberArr = get(); 56 | if (idNumberArr.size() != 2) 57 | return {Result::Status::kError, "ID number malformed"}; 58 | if (idPrefix.size() == 0 && idNumberArr[0] == 0) 59 | return {Result::Status::kError, "No ID supplied"}; 60 | 61 | std::string id = idPrefix; 62 | 63 | if (idNumberArr[0] > 0) 64 | id += std::to_string(idNumberArr[1]); 65 | 66 | auto buf = get(); 67 | return datasetPtr->setPoint(id, buf); 68 | } else 69 | return {Result::Status::kError, "No DataSet"}; 70 | } 71 | }; 72 | } // namespace datasetwr 73 | 74 | using NRTThreadedDataSetWriter = 75 | NRTThreadingAdaptor>; 76 | } // namespace client 77 | } // namespace fluid 78 | -------------------------------------------------------------------------------- /include/wrapper/BufferFuncs.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SCBufferAdaptor.hpp" 4 | 5 | namespace fluid { 6 | namespace client { 7 | namespace impl { 8 | 9 | template 10 | struct AssignBuffer 11 | { 12 | void operator()(const typename BufferT::type& p, World* w) 13 | { 14 | if (auto b = static_cast(p.get())) b->assignToRT(w); 15 | } 16 | }; 17 | 18 | template 19 | struct CleanUpBuffer 20 | { 21 | void operator()(const typename BufferT::type& p) 22 | { 23 | if (auto b = static_cast(p.get())) b->cleanUp(); 24 | } 25 | }; 26 | 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /include/wrapper/CopyReplyAddress.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "CopyReplyAddress.hpp" 3 | #include 4 | #include 5 | 6 | namespace fluid{ 7 | namespace client{ 8 | 9 | void* copyReplyAddress(InterfaceTable* ft, World* inWorld, void* inreply) 10 | { 11 | 12 | if(! inreply) return nullptr; 13 | 14 | ReplyAddress* reply = (ReplyAddress*)ft->fRTAlloc(inWorld, sizeof(ReplyAddress)); 15 | 16 | *reply = *(static_cast(inreply)); 17 | 18 | return reply; 19 | } 20 | 21 | void deleteReplyAddress(InterfaceTable* ft, World* inWorld, void* inreply) 22 | { 23 | if(! inreply) return; 24 | ft->fRTFree(inWorld,(ReplyAddress*)inreply); 25 | } 26 | 27 | void* copyReplyAddress(void* inreply) 28 | { 29 | 30 | if(! inreply) return nullptr; 31 | 32 | ReplyAddress* reply = new ReplyAddress(); 33 | 34 | *reply = *(static_cast(inreply)); 35 | 36 | return reply; 37 | } 38 | 39 | void deleteReplyAddress(void* inreply) 40 | { 41 | if(! inreply) return; 42 | delete (ReplyAddress*)inreply; 43 | } 44 | 45 | void SendReply(void* inReplyAddr, char* inBuf, int inSize) { 46 | SendReply(static_cast(inReplyAddr),inBuf,inSize); 47 | } 48 | 49 | 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /include/wrapper/CopyReplyAddress.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace fluid{ 6 | namespace client{ 7 | 8 | void* copyReplyAddress(InterfaceTable* ft, World* inWorld, void* inreply); 9 | void deleteReplyAddress(InterfaceTable* ft, World* inWorld, void* inreply); 10 | void* copyReplyAddress(void* inreply); 11 | void deleteReplyAddress(void* inreply); 12 | void SendReply(void* inReplyAddr, char* inBuf, int inSize); 13 | 14 | 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /include/wrapper/DeriveBaseClass.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NonRealtime.hpp" 4 | #include "Realtime.hpp" 5 | 6 | namespace fluid { 7 | namespace client { 8 | 9 | template class FluidSCWrapper; 10 | 11 | namespace impl { 12 | 13 | template struct ChooseRTOrNRT; 14 | 15 | template<> 16 | struct ChooseRTOrNRT 17 | { 18 | template 19 | using type = NonRealTime; 20 | }; 21 | 22 | template<> 23 | struct ChooseRTOrNRT 24 | { 25 | template 26 | using type = RealTime; 27 | }; 28 | 29 | 30 | template 31 | struct BaseChooser 32 | { 33 | using RT = typename Client::isRealTime; 34 | 35 | static constexpr bool UseRealTime = RT::value && !IsModel_t::value; 36 | 37 | using type = typename ChooseRTOrNRT::template type; 38 | }; 39 | 40 | 41 | template 42 | using BaseChooser_t = typename BaseChooser::type; 43 | 44 | 45 | template 46 | using FluidSCWrapperBase = BaseChooser_t>; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /include/wrapper/Meta.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | namespace fluid { 8 | namespace client { 9 | namespace impl { 10 | /// Named, shared clients already have a lookup table in their adaptor class 11 | template 12 | struct IsNamedShared 13 | { 14 | using type = std::false_type; 15 | }; 16 | 17 | //TODO: make less tied to current implementation 18 | template 19 | struct IsNamedShared>> 20 | { 21 | using type = std::true_type; 22 | }; 23 | 24 | template 25 | using IsNamedShared_t = typename IsNamedShared::type; 26 | 27 | template 28 | constexpr bool IsNamedShared_v = IsNamedShared_t::value; 29 | 30 | /// Models don't, but still need to survive CMD-. 31 | template 32 | struct IsModel 33 | { 34 | using type = std::false_type; 35 | }; 36 | 37 | template 38 | struct IsModel>> 39 | { 40 | using type = typename ClientWrapper::isModelObject; 41 | }; 42 | 43 | template 44 | struct IsModel> 45 | { 46 | using type = typename ClientWrapper::isModelObject; 47 | }; 48 | 49 | template 50 | using IsModel_t = typename IsModel::type; 51 | 52 | template 53 | constexpr bool IsModel_v = IsModel_t::value; 54 | 55 | 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /include/wrapper/Realtime.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "ArgsFromClient.hpp" 4 | #include "Meta.hpp" 5 | #include "RealTimeBase.hpp" 6 | #include "SCWorldAllocator.hpp" 7 | #include 8 | #include 9 | 10 | // Real Time Processor 11 | namespace fluid { 12 | namespace client { 13 | namespace impl { 14 | 15 | template 16 | class RealTime : public SCUnit 17 | { 18 | 19 | using Delegate = impl::RealTimeBase; 20 | using Params = typename Client::ParamSetType; 21 | 22 | public: 23 | 24 | // static index ControlOffset(Unit* unit) { return Delegate::ControlOffset(unit); } 25 | // static index ControlSize(Unit* unit) { return Delegate::ControlSize(unit); } 26 | 27 | static index ControlOffset(Unit* unit) { return unit->mSpecialIndex + 1; } 28 | static index ControlSize(Unit* unit) 29 | { 30 | return static_cast(unit->mNumInputs) 31 | - unit->mSpecialIndex 32 | - 1 33 | - (IsModel_t::value ? 1 : 0); 34 | } 35 | 36 | static void setup(InterfaceTable* ft, const char* name) 37 | { 38 | 39 | registerUnit(ft,name); 40 | ft->fDefineUnitCmd(name, "latency", doLatency); 41 | } 42 | 43 | static void doLatency(Unit* unit, sc_msg_iter*) 44 | { 45 | float l[]{ 46 | static_cast(static_cast(unit)->mClient.latency()) 47 | }; 48 | auto ft = Wrapper::getInterfaceTable(); 49 | 50 | std::stringstream ss; 51 | ss << '/' << Wrapper::getName() << "_latency"; 52 | // std::cout << ss.str() << ": " << l[0] << std::endl; 53 | ft->fSendNodeReply(&unit->mParent->mNode, -1, ss.str().c_str(), 1, l); 54 | } 55 | 56 | RealTime() 57 | : 58 | mSCAlloc{mWorld, Wrapper::getInterfaceTable()}, 59 | mAlloc{foonathan::memory::make_allocator_reference(mSCAlloc)}, 60 | mContext{fullBufferSize(), mAlloc}, 61 | mControls{mInBuf + ControlOffset(this),ControlSize(this)}, 62 | mParams{Client::getParameterDescriptors(), mAlloc}, 63 | mClient{Wrapper::setParams(this, mParams, mControls, mAlloc,true), mContext} 64 | { 65 | init(); 66 | } 67 | 68 | void init() 69 | { 70 | mDelegate.init(*this,mClient,mControls,mAlloc); 71 | mCalcFunc = make_calc_function(); 72 | Wrapper::getInterfaceTable()->fClearUnitOutputs(this, 1); 73 | 74 | 75 | } 76 | 77 | void next(int) 78 | { 79 | mControls.reset(mInBuf + ControlOffset(this)); 80 | mDelegate.next(*this,mClient,mParams,mControls, mAlloc); 81 | } 82 | private: 83 | SCRawAllocator mSCAlloc; 84 | Allocator mAlloc; 85 | FluidContext mContext; 86 | Delegate mDelegate; 87 | FloatControlsIter mControls; 88 | Params mParams; 89 | Client mClient; 90 | Wrapper* mWrapper{static_cast(this)}; 91 | }; 92 | 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /include/wrapper/SCWorldAllocator.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) 3 | Copyright University of Huddersfield. 4 | Licensed under the BSD-3 License. 5 | See license.md file in the project root for full license information. 6 | This project has received funding from the European Research Council (ERC) 7 | under the European Union’s Horizon 2020 research and innovation programme 8 | (grant agreement No 725899). 9 | */ 10 | #pragma once 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | 18 | namespace fluid { 19 | 20 | template 21 | class SCWorldAllocator 22 | { 23 | World* mWorld; 24 | InterfaceTable* mInterface; 25 | 26 | public: 27 | using propagate_on_container_move_assignment = std::true_type; 28 | using value_type = T; 29 | 30 | template 31 | friend class SCWorldAllocator; 32 | 33 | SCWorldAllocator(World* w, InterfaceTable* interface) 34 | : mWorld{w}, mInterface{interface} 35 | {} 36 | 37 | template 38 | SCWorldAllocator(const SCWorldAllocator& other) noexcept 39 | { 40 | mWorld = other.mWorld; 41 | mInterface = other.mInterface; 42 | } 43 | 44 | T* allocate(std::size_t n) 45 | { 46 | if (n > std::numeric_limits::max() / sizeof(T)) 47 | throw std::bad_array_new_length(); 48 | 49 | if (mWorld && mInterface) 50 | if (auto p = static_cast(mInterface->fRTAlloc(mWorld, n * sizeof(T)))) 51 | return p; 52 | 53 | throw std::bad_alloc(); 54 | } 55 | 56 | void deallocate(T* p, std::size_t /*n*/) noexcept 57 | { 58 | if (mWorld && mInterface) mInterface->fRTFree(mWorld, p); 59 | } 60 | }; 61 | 62 | //foonathan::memory RawAllocator with SC rtalloc 63 | struct SCRawAllocator 64 | { 65 | using is_stateful = std::true_type; 66 | 67 | SCRawAllocator(World* w, InterfaceTable* interface) 68 | : mWorld{w}, mInterface{interface} 69 | {} 70 | 71 | void* allocate_node(std::size_t size, std::size_t) 72 | { 73 | if(auto res = mInterface->fRTAlloc(mWorld,size)) 74 | { 75 | // std::cout << "Allocated " << res << " with " << size << '\n'; 76 | return res; 77 | } 78 | throw std::bad_alloc(); 79 | } 80 | 81 | void deallocate_node(void* node, std::size_t /*size*/, std::size_t) noexcept 82 | { 83 | mInterface->fRTFree(mWorld, node); 84 | // std::cout << "Freed " << node << " with " << size << '\n'; 85 | } 86 | private: 87 | World* mWorld; 88 | InterfaceTable* mInterface; 89 | }; 90 | 91 | } // namespace fluid 92 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidAmpFeature.sc: -------------------------------------------------------------------------------- 1 | FluidAmpFeature : FluidRTUGen { 2 | *ar { arg in = 0, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, floor = -144, highPassFreq = 85; 3 | 4 | ^this.multiNew('audio', in.asAudioRateInput(this), fastRampUp, fastRampDown, slowRampUp, slowRampDown, floor, highPassFreq) 5 | } 6 | checkInputs { 7 | ^this.checkValidInputs; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidAmpGate.sc: -------------------------------------------------------------------------------- 1 | FluidAmpGate : FluidRTUGen { 2 | *ar { arg in = 0, rampUp = 10, rampDown = 10, onThreshold = -90, offThreshold = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, highPassFreq = 85, maxSize = 88200; 3 | ^this.multiNew('audio', in.asAudioRateInput(this), rampUp, rampDown, onThreshold, offThreshold, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, highPassFreq, maxSize) 4 | } 5 | checkInputs { 6 | if(inputs.at(12).rate != 'scalar') { 7 | ^(": maxSize cannot be modulated."); 8 | }; 9 | ^this.checkValidInputs; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidAmpSlice.sc: -------------------------------------------------------------------------------- 1 | FluidAmpSlice : FluidRTUGen { 2 | *ar { arg in = 0, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, onThreshold = -144, offThreshold = -144, floor = -144, minSliceLength = 2, highPassFreq = 85; 3 | 4 | ^this.multiNew('audio', in.asAudioRateInput(this), fastRampUp, fastRampDown, slowRampUp, slowRampDown, onThreshold, offThreshold, floor, minSliceLength, highPassFreq) 5 | } 6 | checkInputs { 7 | ^this.checkValidInputs; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidAudioTransport.sc: -------------------------------------------------------------------------------- 1 | FluidAudioTransport : FluidRTUGen { 2 | 3 | init { |...theInputs| 4 | theInputs; 5 | inputs = theInputs; 6 | this.specialIndex = 1; //two audio inputs 7 | // ^this.initOutputs(1,rate); 8 | } 9 | 10 | *ar { arg in = 0, in2 = 0, interpolation = 0.0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 11 | ^this.multiNew('audio', in.asAudioRateInput, in2, interpolation, windowSize, hopSize, fftSize, maxFFTSize) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufAmpFeature.sc: -------------------------------------------------------------------------------- 1 | FluidBufAmpFeature : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, floor = -144, highPassFreq = 85, trig = 1, blocking = 0| 4 | 5 | source = source.asUGenInput; 6 | features = features.asUGenInput; 7 | 8 | source.isNil.if {"FluidBufAmpFeature: Invalid source buffer".throw}; 9 | features.isNil.if {"FluidBufAmpFeature: Invalid features buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufAmpFeatureTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, fastRampUp, fastRampDown, slowRampUp, slowRampDown, floor, highPassFreq, trig, blocking); 12 | } 13 | 14 | *process { |server,source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, floor = -144, highPassFreq = 85, freeWhenDone = true, action | 15 | 16 | source = source.asUGenInput; 17 | features = features.asUGenInput; 18 | 19 | source.isNil.if {"FluidBufAmpFeature: Invalid source buffer".throw}; 20 | features.isNil.if {"FluidBufAmpFeature: Invalid features buffer".throw}; 21 | 22 | ^this.new(server, nil, [features]).processList( 23 | [source, startFrame, numFrames, startChan, numChans, features, fastRampUp, fastRampDown, slowRampUp, slowRampDown, floor, highPassFreq,0],freeWhenDone, action 24 | ); 25 | } 26 | 27 | *processBlocking { |server,source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, floor = -144, highPassFreq = 85, freeWhenDone = true, action | 28 | 29 | source = source.asUGenInput; 30 | features = features.asUGenInput; 31 | 32 | source.isNil.if {"FluidBufAmpFeature: Invalid source buffer".throw}; 33 | features.isNil.if {"FluidBufAmpFeature: Invalid features buffer".throw}; 34 | 35 | ^this.new(server, nil, [features]).processList( 36 | [source, startFrame, numFrames, startChan, numChans, features, fastRampUp, fastRampDown, slowRampUp, slowRampDown, floor, highPassFreq,1],freeWhenDone, action 37 | ); 38 | } 39 | } 40 | FluidBufAmpFeatureTrigger : FluidProxyUgen {} 41 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufAmpGate.sc: -------------------------------------------------------------------------------- 1 | FluidBufAmpGate : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, rampUp = 10, rampDown = 10, onThreshold = -90, offThreshold = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, highPassFreq = 85, trig = 1, blocking = 0| 4 | 5 | var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); 6 | 7 | source = source.asUGenInput; 8 | indices = indices.asUGenInput; 9 | 10 | ^FluidProxyUgen.kr(\FluidBufAmpGateTrigger,-1, source, startFrame, numFrames, startChan, numChans, indices, rampUp, rampDown, onThreshold, offThreshold, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, highPassFreq,maxSize, trig, blocking); 11 | } 12 | 13 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, rampUp = 10, rampDown = 10, onThreshold = -90, offThreshold = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, highPassFreq = 85, freeWhenDone = true, action | 14 | 15 | 16 | var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); 17 | 18 | source = source ? -1; 19 | indices = indices ? -1; 20 | 21 | ^this.new( 22 | server, nil, [indices] 23 | ).processList( 24 | [source, startFrame, numFrames, startChan, numChans, indices, rampUp, rampDown, onThreshold, offThreshold, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, highPassFreq, maxSize, 0],freeWhenDone,action 25 | ); 26 | } 27 | 28 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, rampUp = 10, rampDown = 10, onThreshold = -90, offThreshold = -90, minSliceLength = 1, minSilenceLength = 1, minLengthAbove = 1, minLengthBelow = 1, lookBack = 0, lookAhead = 0, highPassFreq = 85, freeWhenDone = true, action | 29 | 30 | 31 | var maxSize = max(minLengthAbove + lookBack, max(minLengthBelow,lookAhead)); 32 | 33 | source = source ? -1; 34 | indices = indices ? -1; 35 | 36 | ^this.new( 37 | server, nil, [indices] 38 | ).processList( 39 | [source, startFrame, numFrames, startChan, numChans, indices, rampUp, rampDown, onThreshold, offThreshold, minSliceLength, minSilenceLength, minLengthAbove, minLengthBelow, lookBack, lookAhead, highPassFreq, maxSize, 1],freeWhenDone,action 40 | ); 41 | } 42 | 43 | } 44 | FluidBufAmpGateTrigger : FluidProxyUgen {} 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufAmpSlice.sc: -------------------------------------------------------------------------------- 1 | FluidBufAmpSlice : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, onThreshold = -144, offThreshold = -144, floor = -144, minSliceLength = 2, highPassFreq = 85, trig = 1, blocking = 0| 4 | 5 | source = source.asUGenInput; 6 | indices = indices.asUGenInput; 7 | 8 | source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; 9 | indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufAmpSliceTrigger, -1, source, startFrame, numFrames, startChan, numChans, indices, fastRampUp, fastRampDown, slowRampUp, slowRampDown, onThreshold, offThreshold, floor, minSliceLength, highPassFreq, trig, blocking); 12 | } 13 | 14 | *process { |server,source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, onThreshold = -144, offThreshold = -144, floor = -144, minSliceLength = 2, highPassFreq = 85, freeWhenDone = true, action | 15 | 16 | source = source.asUGenInput; 17 | indices = indices.asUGenInput; 18 | 19 | source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; 20 | indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; 21 | 22 | ^this.new(server, nil, [indices]).processList( 23 | [source, startFrame, numFrames, startChan, numChans, indices, fastRampUp, fastRampDown, slowRampUp, slowRampDown, onThreshold, offThreshold, floor, minSliceLength, highPassFreq,0],freeWhenDone, action 24 | ); 25 | } 26 | 27 | *processBlocking { |server,source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, fastRampUp = 1, fastRampDown = 1, slowRampUp = 100, slowRampDown = 100, onThreshold = -144, offThreshold = -144, floor = -144, minSliceLength = 2, highPassFreq = 85, freeWhenDone = true, action | 28 | 29 | source = source.asUGenInput; 30 | indices = indices.asUGenInput; 31 | 32 | source.isNil.if {"FluidBufAmpSlice: Invalid source buffer".throw}; 33 | indices.isNil.if {"FluidBufAmpSlice: Invalid features buffer".throw}; 34 | 35 | ^this.new(server, nil, [indices]).processList( 36 | [source, startFrame, numFrames, startChan, numChans, indices, fastRampUp, fastRampDown, slowRampUp, slowRampDown, onThreshold, offThreshold, floor, minSliceLength, highPassFreq,1],freeWhenDone, action 37 | ); 38 | } 39 | } 40 | FluidBufAmpSliceTrigger : FluidProxyUgen {} 41 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufAudioTransport.sc: -------------------------------------------------------------------------------- 1 | FluidBufAudioTransport : FluidBufProcessor { 2 | 3 | *kr { |sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destination, interpolation = 0.0, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | sourceA.isNil.if {"FluidAudioTransport: Invalid source 1 buffer".throw}; 7 | sourceB.isNil.if {"FluidAudioTransport: Invalid source 2 buffer".throw}; 8 | sourceA = sourceA.asUGenInput; 9 | sourceB = sourceB.asUGenInput; 10 | 11 | destination.isNil.if {"FluidAudioTransport: Invalid destination buffer".throw}; 12 | destination = destination.asUGenInput; 13 | 14 | 15 | ^FluidProxyUgen.kr(this.objectClassName++\Trigger,-1, sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameA, numFramesA, startChanB, numChansB, destination, interpolation, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 16 | } 17 | 18 | 19 | *process { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destination, interpolation=0.0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 20 | 21 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 22 | sourceA.isNil.if {"FluidAudioTransport: Invalid source 1 buffer".throw}; 23 | sourceB.isNil.if {"FluidAudioTransport: Invalid source 2 buffer".throw}; 24 | sourceA = sourceA.asUGenInput; 25 | sourceB = sourceB.asUGenInput; 26 | 27 | destination.isNil.if {"FluidAudioTransport: Invalid destination buffer".throw}; 28 | destination = destination.asUGenInput; 29 | 30 | ^this.new( 31 | server, nil, [destination] 32 | ).processList( 33 | [sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destination, interpolation, windowSize, hopSize, fftSize,maxFFTSize,0], freeWhenDone, action 34 | ) 35 | } 36 | 37 | *processBlocking { |server, sourceA, startFrameA = 0, numFramesA = -1, startChanA = 0, numChansA = -1, sourceB, startFrameB = 0, numFramesB = -1, startChanB = 0, numChansB = -1, destination, interpolation=0.0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 38 | 39 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 40 | sourceA.isNil.if {"FluidAudioTransport: Invalid source 1 buffer".throw}; 41 | sourceB.isNil.if {"FluidAudioTransport: Invalid source 2 buffer".throw}; 42 | sourceA = sourceA.asUGenInput; 43 | sourceB = sourceB.asUGenInput; 44 | 45 | destination.isNil.if {"FluidAudioTransport: Invalid destination buffer".throw}; 46 | destination = destination.asUGenInput; 47 | 48 | ^this.new( 49 | server, nil, [destination] 50 | ).processList( 51 | [sourceA, startFrameA, numFramesA, startChanA, numChansA, sourceB, startFrameB, numFramesB, startChanB, numChansB, destination, interpolation, windowSize, hopSize, fftSize,maxFFTSize,1], freeWhenDone, action 52 | ) 53 | } 54 | } 55 | FluidBufAudioTransportTrigger : FluidProxyUgen {} 56 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufChroma.sc: -------------------------------------------------------------------------------- 1 | FluidBufChroma : FluidBufProcessor { 2 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numChroma = 12, ref = 440, normalize = 0,minFreq = 0,maxFreq = -1, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 3 | 4 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 5 | 6 | source = source.asUGenInput; 7 | features = features.asUGenInput; 8 | 9 | source.isNil.if {"FluidBufChroma: Invalid source buffer".throw}; 10 | features.isNil.if {"FluidBufChroma: Invalid features buffer".throw}; 11 | 12 | ^FluidProxyUgen.kr(\FluidBufChromaTrigger,-1, source, startFrame, numFrames, startChan, numChans, features, padding, numChroma, numChroma, ref, normalize, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 13 | } 14 | 15 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numChroma = 12, ref = 440, normalize = 0,minFreq = 0,maxFreq = -1, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 16 | 17 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 18 | 19 | source = source.asUGenInput; 20 | features = features.asUGenInput; 21 | 22 | source.isNil.if {"FluidBufChroma: Invalid source buffer".throw}; 23 | features.isNil.if {"FluidBufChroma: Invalid features buffer".throw}; 24 | 25 | ^this.new( 26 | server, nil, [features] 27 | ).processList( 28 | [source, startFrame, numFrames, startChan, numChans, features, padding, numChroma, numChroma, ref, normalize, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize, 0],freeWhenDone,action 29 | ); 30 | } 31 | 32 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numChroma = 12, ref = 440, normalize = 0,minFreq = 0,maxFreq = -1, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 33 | 34 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 35 | 36 | source = source.asUGenInput; 37 | features = features.asUGenInput; 38 | 39 | source.isNil.if {"FluidBufChroma: Invalid source buffer".throw}; 40 | features.isNil.if {"FluidBufChroma: Invalid features buffer".throw}; 41 | 42 | ^this.new( 43 | server, nil, [features] 44 | ).processList( 45 | [source, startFrame, numFrames, startChan, numChans, features, padding, numChroma, numChroma, ref, normalize, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize, 1],freeWhenDone,action 46 | ); 47 | } 48 | } 49 | FluidBufChromaTrigger : FluidProxyUgen {} 50 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufCompose.sc: -------------------------------------------------------------------------------- 1 | FluidBufCompose : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, trig = 1, blocking = 1| 4 | 5 | source = source.asUGenInput; 6 | destination = destination.asUGenInput; 7 | 8 | source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; 9 | destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufComposeTrigger,-1, source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, trig, blocking); 12 | } 13 | 14 | 15 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, freeWhenDone = true, action| 16 | 17 | source = source.asUGenInput; 18 | destination = destination.asUGenInput; 19 | 20 | source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; 21 | destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; 22 | 23 | ^this.new( server, nil, [destination]).processList([source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, 1], freeWhenDone, action);//NB always blocking 24 | } 25 | 26 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, gain = 1, destination, destStartFrame = 0, destStartChan = 0, destGain = 0, freeWhenDone = true, action| 27 | 28 | source = source.asUGenInput; 29 | destination = destination.asUGenInput; 30 | 31 | source.isNil.if {"FluidBufCompose: Invalid source buffer".throw}; 32 | destination.isNil.if {"FluidBufCompose: Invalid destination buffer".throw}; 33 | 34 | ^this.new( 35 | server, nil, [destination] 36 | ).processList([source, startFrame, numFrames, startChan, numChans, gain, destination, destStartFrame, destStartChan, destGain, 1], freeWhenDone, action); 37 | } 38 | } 39 | FluidBufComposeTrigger : FluidProxyUgen {} 40 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufFlatten.sc: -------------------------------------------------------------------------------- 1 | FluidBufFlatten : FluidBufProcessor { 2 | 3 | 4 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, axis = 1, trig = 1, blocking = 1| 5 | 6 | source = source.asUGenInput; 7 | destination = destination.asUGenInput; 8 | 9 | source.isNil.if {"FluidBufFlatten: Invalid source buffer".throw}; 10 | destination.isNil.if {"FluidBufFlatten: Invalid destination buffer".throw}; 11 | 12 | ^FluidProxyUgen.kr(\FluidBufFlattenTrigger,-1, source, startFrame, numFrames, startChan, numChans, destination, axis, trig, blocking); 13 | } 14 | 15 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, axis = 1, freeWhenDone = true, action| 16 | 17 | source = source.asUGenInput; 18 | destination = destination.asUGenInput; 19 | 20 | source.isNil.if {"FluidBufFlatten: Invalid source buffer".throw}; 21 | destination.isNil.if {"FluidBufFlatten: Invalid destination buffer".throw}; 22 | 23 | ^this.new( 24 | server, nil, [destination], 25 | ).processList( 26 | [source, startFrame, numFrames, startChan, numChans, destination, axis,0],freeWhenDone,action 27 | ); 28 | 29 | } 30 | 31 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, axis = 1, freeWhenDone = true, action| 32 | 33 | source = source.asUGenInput; 34 | destination = destination.asUGenInput; 35 | 36 | source.isNil.if {"FluidBufFlatten: Invalid source buffer".throw}; 37 | destination.isNil.if {"FluidBufFlatten: Invalid destination buffer".throw}; 38 | 39 | ^this.new( 40 | server, nil, [destination], 41 | ).processList( 42 | [source, startFrame, numFrames, startChan, numChans, destination, axis,1],freeWhenDone,action 43 | ); 44 | 45 | } 46 | } 47 | FluidBufFlattenTrigger : FluidProxyUgen {} 48 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufHPSS.sc: -------------------------------------------------------------------------------- 1 | FluidBufHPSS : FluidBufProcessor { 2 | 3 | *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | harmonic = harmonic ? -1; 8 | percussive = percussive ? -1; 9 | residual = residual ? -1; 10 | source.isNil.if {"FluidBufHPSS: Invalid source buffer".throw}; 11 | 12 | ^FluidProxyUgen.kr(\FluidBufHPSSTrigger, -1, source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, harmFilterSize, percFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking 13 | ); 14 | } 15 | 16 | *process {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone=true, action| 17 | 18 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 19 | 20 | harmonic = harmonic ? -1; 21 | percussive = percussive ? -1; 22 | residual = residual ? -1; 23 | source.isNil.if {"FluidBufHPSS: Invalid source buffer".throw}; 24 | 25 | 26 | ^this.new( 27 | server, nil, [harmonic, percussive, residual].select{|x| x!= -1} 28 | ).processList( 29 | [source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, harmFilterSize, percFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone,action 30 | ); 31 | 32 | } 33 | 34 | *processBlocking {|server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, harmonic = -1, percussive = -1, residual = -1, harmFilterSize = 17, percFilterSize = 31, maskingMode = 0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone=true, action| 35 | 36 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 37 | 38 | harmonic = harmonic ? -1; 39 | percussive = percussive ? -1; 40 | residual = residual ? -1; 41 | source.isNil.if {"FluidBufHPSS: Invalid source buffer".throw}; 42 | 43 | 44 | ^this.new( 45 | server, nil, [harmonic, percussive, residual].select{|x| x!= -1} 46 | ).processList( 47 | [source, startFrame, numFrames, startChan, numChans, harmonic, percussive, residual, harmFilterSize, harmFilterSize, percFilterSize, percFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone,action 48 | ); 49 | 50 | } 51 | } 52 | FluidBufHPSSTrigger : FluidProxyUgen {} 53 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufLoudness.sc: -------------------------------------------------------------------------------- 1 | FluidBufLoudness : FluidBufProcessor{ 2 | 3 | const (1< 1) { ("Option '" ++ item ++ "' is repeated").warn}; 16 | }; 17 | bits = a.collect{ |sym| 18 | (featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0}) 19 | }.reduce{|x,y| x | y}; 20 | ^bits 21 | } 22 | 23 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, padding = 1, trig = 1, blocking = 0| 24 | 25 | var maxwindowSize = windowSize.nextPowerOfTwo; 26 | 27 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 28 | 29 | source = source.asUGenInput; 30 | features = features.asUGenInput; 31 | 32 | source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw}; 33 | features.isNil.if {"%: Invalid features buffer".format(this.class.name).throw}; 34 | 35 | ^FluidProxyUgen.kr(\FluidBufLoudnessTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, kWeighting, truePeak, windowSize, hopSize, maxwindowSize, trig, blocking); 36 | } 37 | 38 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, padding = 1, freeWhenDone = true, action| 39 | 40 | var maxwindowSize = windowSize.nextPowerOfTwo; 41 | 42 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 43 | 44 | source = source.asUGenInput; 45 | features = features.asUGenInput; 46 | 47 | source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw}; 48 | features.isNil.if {"%: Invalid features buffer".format(this.class.name).throw}; 49 | 50 | ^this.new( 51 | server, nil, [features] 52 | ).processList( 53 | [source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, kWeighting, truePeak, windowSize, hopSize, maxwindowSize,0],freeWhenDone,action 54 | ); 55 | } 56 | 57 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, padding = 1, freeWhenDone = true, action| 58 | 59 | var maxwindowSize = windowSize.nextPowerOfTwo; 60 | 61 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 62 | 63 | source = source.asUGenInput; 64 | features = features.asUGenInput; 65 | 66 | source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw}; 67 | features.isNil.if {"%: Invalid features buffer".format(this.class.name).throw}; 68 | 69 | ^this.new( 70 | server, nil, [features] 71 | ).processList( 72 | [source, startFrame, numFrames, startChan, numChans, features,padding, selectbits, kWeighting, truePeak, windowSize, hopSize, maxwindowSize,1],freeWhenDone,action 73 | ); 74 | } 75 | } 76 | FluidBufLoudnessTrigger : FluidProxyUgen {} 77 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufMFCC.sc: -------------------------------------------------------------------------------- 1 | FluidBufMFCC : FluidBufProcessor{ 2 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, startCoeff = 0, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 3 | 4 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 5 | source = source.asUGenInput; 6 | features = features.asUGenInput; 7 | 8 | source.isNil.if {"FluidBufMFCC: Invalid source buffer".throw}; 9 | features.isNil.if {"FluidBufMFCC: Invalid features buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufMFCCTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, numCoeffs, numCoeffs, numBands, numBands, startCoeff, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize,trig, blocking); 12 | } 13 | 14 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, startCoeff = 0, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone=true, action | 15 | 16 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 17 | source = source.asUGenInput; 18 | features = features.asUGenInput; 19 | 20 | source.isNil.if {"FluidBufMFCC: Invalid source buffer".throw}; 21 | features.isNil.if {"FluidBufMFCC: Invalid features buffer".throw}; 22 | 23 | ^this.new( 24 | server, nil,[features] 25 | ).processList( 26 | [source, startFrame, numFrames, startChan, numChans, features, padding, numCoeffs, numCoeffs, numBands, numBands, startCoeff, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize,0],freeWhenDone,action 27 | ); 28 | } 29 | 30 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numCoeffs = 13, numBands = 40, startCoeff = 0, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone=true, action | 31 | 32 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 33 | source = source.asUGenInput; 34 | features = features.asUGenInput; 35 | 36 | source.isNil.if {"FluidBufMFCC: Invalid source buffer".throw}; 37 | features.isNil.if {"FluidBufMFCC: Invalid features buffer".throw}; 38 | 39 | ^this.new( 40 | server, nil,[features] 41 | ).processList( 42 | [source, startFrame, numFrames, startChan, numChans, features, padding, numCoeffs, numCoeffs, numBands, numBands, startCoeff, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize,1],freeWhenDone,action 43 | ); 44 | } 45 | } 46 | FluidBufMFCCTrigger : FluidProxyUgen {} 47 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufMelBands.sc: -------------------------------------------------------------------------------- 1 | FluidBufMelBands : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, normalize = 1, scale = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | source = source.asUGenInput; 8 | features = features.asUGenInput; 9 | 10 | source.isNil.if {"FluidBufMelBands: Invalid source buffer".throw}; 11 | features.isNil.if {"FluidBufMelBands: Invalid features buffer".throw}; 12 | 13 | 14 | ^FluidProxyUgen.kr(\FluidBufMelBandsTrigger,-1, source, startFrame, numFrames, startChan, numChans, features, padding, numBands, numBands, minFreq, maxFreq, normalize, scale, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 15 | } 16 | 17 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, normalize = 1, scale = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 18 | 19 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 20 | 21 | source = source.asUGenInput; 22 | features = features.asUGenInput; 23 | 24 | source.isNil.if {"FluidBufMelBands: Invalid source buffer".throw}; 25 | features.isNil.if {"FluidBufMelBands: Invalid features buffer".throw}; 26 | 27 | ^this.new( 28 | server, nil, [features] 29 | ).processList( 30 | [source, startFrame, numFrames, startChan, numChans, features, padding, numBands, numBands, minFreq, maxFreq, normalize, scale, windowSize, hopSize, fftSize, maxFFTSize, 0],freeWhenDone,action 31 | ); 32 | } 33 | 34 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, numBands = 40, minFreq = 20, maxFreq = 20000, normalize = 1, scale = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 35 | 36 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 37 | 38 | source = source.asUGenInput; 39 | features = features.asUGenInput; 40 | 41 | source.isNil.if {"FluidBufMelBands: Invalid source buffer".throw}; 42 | features.isNil.if {"FluidBufMelBands: Invalid features buffer".throw}; 43 | 44 | ^this.new( 45 | server, nil, [features] 46 | ).processList( 47 | [source, startFrame, numFrames, startChan, numChans, features, padding, numBands, numBands, minFreq, maxFreq, normalize, scale, windowSize, hopSize, fftSize, maxFFTSize, 1],freeWhenDone,action 48 | ); 49 | } 50 | } 51 | FluidBufMelBandsTrigger : FluidProxyUgen {} 52 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufNMF.sc: -------------------------------------------------------------------------------- 1 | FluidBufNMF : FluidBufProcessor 2 | { 3 | *kr {|source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, resynth, resynthMode = 0, bases, basesMode = 0, activations, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0| 4 | 5 | source.isNil.if {"FluidBufNMF: Invalid source buffer".throw}; 6 | resynth = resynth ? -1; 7 | bases = bases ? -1; 8 | activations = activations ? -1; 9 | 10 | ^FluidProxyUgen.kr(\FluidBufNMFTrigger,-1,source.asUGenInput, startFrame, numFrames, startChan, numChans, resynth.asUGenInput, resynthMode, bases.asUGenInput, basesMode, activations.asUGenInput, actMode, components, iterations, windowSize, hopSize, fftSize, fftSize, trig, blocking); 11 | } 12 | 13 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, resynth = -1, resynthMode = 0, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1,freeWhenDone = true, action| 14 | 15 | source.isNil.if {"FluidBufNMF: Invalid source buffer".throw}; 16 | resynth = resynth ? -1; 17 | bases = bases ? -1; 18 | activations = activations ? -1; 19 | 20 | ^this.new( 21 | server,nil,[resynth, bases, activations].select{|x| x!= -1} 22 | ).processList([source, startFrame, numFrames, startChan, numChans, resynth, resynthMode, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, fftSize, 0],freeWhenDone,action); 23 | } 24 | 25 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, resynth = -1, resynthMode = 0, bases = -1, basesMode = 0, activations = -1, actMode = 0, components = 1, iterations = 100, windowSize = 1024, hopSize = -1, fftSize = -1,freeWhenDone = true, action| 26 | 27 | source.isNil.if {"FluidBufNMF: Invalid source buffer".throw}; 28 | resynth = resynth ? -1; 29 | bases = bases ? -1; 30 | activations = activations ? -1; 31 | 32 | ^this.new( 33 | server,nil,[resynth, bases, activations].select{|x| x!= -1} 34 | ).processList([source, startFrame, numFrames, startChan, numChans, resynth, resynthMode, bases, basesMode, activations, actMode, components,iterations, windowSize, hopSize, fftSize, fftSize, 1],freeWhenDone,action); 35 | } 36 | } 37 | FluidBufNMFTrigger : FluidProxyUgen {} 38 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufNMFCross.sc: -------------------------------------------------------------------------------- 1 | FluidBufNMFCross : FluidBufProcessor { 2 | 3 | *kr { |source, target, output , timeSparsity = 7, polyphony = 10, continuity = 7, iterations = 50, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0| 4 | 5 | source = source.asUGenInput; 6 | target = target.asUGenInput; 7 | output = output.asUGenInput; 8 | source.isNil.if {"FluidBufNMFCross: Invalid source buffer".throw}; 9 | target.isNil.if {"FluidBufNMFCross: Invalid target buffer".throw}; 10 | output.isNil.if {"FluidBufNMFCross: Invalid output buffer".throw}; 11 | 12 | ^FluidProxyUgen.kr(\FluidBufNMFCrossTrigger, -1, source, target, output, timeSparsity, polyphony, continuity, iterations, windowSize, hopSize, fftSize, fftSize, trig, blocking); 13 | } 14 | 15 | *process { |server, source, target, output , timeSparsity = 7, polyphony = 10, continuity = 7, iterations = 50, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 16 | 17 | source = source.asUGenInput; 18 | target = target.asUGenInput; 19 | output = output.asUGenInput; 20 | source.isNil.if {"FluidBufNMFCross: Invalid source buffer".throw}; 21 | target.isNil.if {"FluidBufNMFCross: Invalid target buffer".throw}; 22 | output.isNil.if {"FluidBufNMFCross: Invalid output buffer".throw}; 23 | 24 | 25 | ^this.new( 26 | server, nil, [output] 27 | ).processList( 28 | [source, target, output, timeSparsity, polyphony, continuity, iterations, windowSize, hopSize, fftSize, fftSize, 0],freeWhenDone, action 29 | ); 30 | } 31 | 32 | *processBlocking { |server, source, target, output , timeSparsity = 7, polyphony = 10, continuity = 7, iterations = 50, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 33 | 34 | source = source.asUGenInput; 35 | target = target.asUGenInput; 36 | output = output.asUGenInput; 37 | source.isNil.if {"FluidBufNMFCross: Invalid source buffer".throw}; 38 | target.isNil.if {"FluidBufNMFCross: Invalid target buffer".throw}; 39 | output.isNil.if {"FluidBufNMFCross: Invalid output buffer".throw}; 40 | 41 | 42 | ^this.new( 43 | server, nil, [output] 44 | ).processList( 45 | [source, target, output, timeSparsity, polyphony, continuity, iterations, windowSize, hopSize, fftSize, fftSize, 1],freeWhenDone, action 46 | ); 47 | } 48 | } 49 | FluidBufNMFCrossTrigger : FluidProxyUgen {} 50 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufNMFSeed.sc: -------------------------------------------------------------------------------- 1 | FluidBufNMFSeed : FluidBufProcessor{ 2 | 3 | *kr { |source, bases, activations, minComponents = 1, maxComponents = 200, coverage = 0.5, method = 0, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0| 4 | 5 | source.isNil.if {"FluidBufNMFSeed: Invalid source buffer".throw}; 6 | bases.isNil.if {"FluidBufNMFSeed: Invalid bases buffer".throw}; 7 | activations.isNil.if {"FluidBufNMFSeed: Invalid bases buffer".throw}; 8 | source = source.asUGenInput; 9 | bases = bases.asUGenInput; 10 | activations = activations.asUGenInput; 11 | 12 | ^FluidProxyUgen.kr1(\FluidBufNMFSeedTrigger, -1, source, bases, activations, minComponents, maxComponents, coverage, method, windowSize, hopSize, fftSize, fftSize, trig, blocking); 13 | } 14 | 15 | 16 | *process { |server, source, bases, activations, minComponents = 1, maxComponents = 200, coverage = 0.5, method = 0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 17 | 18 | source.isNil.if {"FluidBufNMFSeed: Invalid source buffer".throw}; 19 | bases.isNil.if {"FluidBufNMFSeed: Invalid bases buffer".throw}; 20 | activations.isNil.if {"FluidBufNMFSeed: Invalid bases buffer".throw}; 21 | source = source.asUGenInput; 22 | bases = bases.asUGenInput; 23 | activations = activations.asUGenInput; 24 | 25 | ^this.new( 26 | server, nil, [bases,activations] 27 | ).processList( 28 | [source, bases, activations, minComponents, maxComponents, coverage, method, windowSize, hopSize, fftSize, fftSize, 0],freeWhenDone, action 29 | ) 30 | } 31 | 32 | *processBlocking { |server, source, bases, activations, minComponents = 1, maxComponents = 200, coverage = 0.5, method = 0, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 33 | 34 | source.isNil.if {"FluidBufNMFSeed: Invalid source buffer".throw}; 35 | bases.isNil.if {"FluidBufNMFSeed: Invalid bases buffer".throw}; 36 | activations.isNil.if {"FluidBufNMFSeed: Invalid bases buffer".throw}; 37 | source = source.asUGenInput; 38 | bases = bases.asUGenInput; 39 | activations = activations.asUGenInput; 40 | 41 | ^this.new( 42 | server, nil, [bases,activations] 43 | ).processList( 44 | [source, bases, activations, minComponents, maxComponents, coverage, method, windowSize, hopSize, fftSize, fftSize, 1],freeWhenDone, action 45 | ) 46 | } 47 | } 48 | FluidBufNMFSeedTrigger : FluidProxyUgen {} 49 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufNoveltyFeature.sc: -------------------------------------------------------------------------------- 1 | FluidBufNoveltyFeature : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm = 0, kernelSize = 3, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | source = source.asUGenInput; 8 | features = features.asUGenInput; 9 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm) ?? { 10 | ("FluidBufNoveltySlice: % is not a recognised algorithm") 11 | .format(algorithm).throw; 12 | }; 13 | 14 | source.isNil.if {"FluidBufNoveltyFeature: Invalid source buffer".throw}; 15 | features.isNil.if {"FluidBufNoveltyFeature: Invalid features buffer".throw}; 16 | 17 | ^FluidProxyUgen.kr(\FluidBufNoveltyFeatureTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, algorithm, kernelSize, kernelSize, filterSize, filterSize, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 18 | 19 | } 20 | 21 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm= 0, kernelSize = 3, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action | 22 | 23 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 24 | 25 | source = source.asUGenInput; 26 | features = features.asUGenInput; 27 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm); 28 | if (algorithm.isNil or: algorithm.isUGen) { 29 | ("FluidBufNoveltySlice: % is not a recognised algorithm") 30 | .format(algorithm).throw; 31 | }; 32 | 33 | source.isNil.if {"FluidBufNoveltyFeature: Invalid source buffer".throw}; 34 | features.isNil.if {"FluidBufNoveltyFeature: Invalid features buffer".throw}; 35 | 36 | ^this.new( 37 | server, nil, [features] 38 | ).processList( 39 | [source, startFrame, numFrames, startChan, numChans, features, padding, algorithm, kernelSize, kernelSize, filterSize, filterSize, windowSize, hopSize, fftSize, maxFFTSize, 0],freeWhenDone,action 40 | ); 41 | } 42 | 43 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, algorithm= 0, kernelSize = 3, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action | 44 | 45 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 46 | 47 | source = source.asUGenInput; 48 | features = features.asUGenInput; 49 | 50 | source.isNil.if {"FluidBufNoveltyFeature: Invalid source buffer".throw}; 51 | features.isNil.if {"FluidBufNoveltyFeature: Invalid features buffer".throw}; 52 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm); 53 | if (algorithm.isNil or: algorithm.isUGen) { 54 | ("FluidBufNoveltySlice: % is not a recognised algorithm") 55 | .format(algorithm).throw; 56 | }; 57 | 58 | ^this.new( 59 | server, nil, [features] 60 | ).processList( 61 | [source, startFrame, numFrames, startChan, numChans, features, padding, algorithm, kernelSize, kernelSize, filterSize, filterSize, windowSize, hopSize, fftSize, maxFFTSize, 1],freeWhenDone,action 62 | ); 63 | } 64 | } 65 | FluidBufNoveltyFeatureTrigger : FluidProxyUgen {} 66 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufNoveltySlice.sc: -------------------------------------------------------------------------------- 1 | FluidBufNoveltySlice : FluidBufProcessor { 2 | 3 | *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| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | source = source.asUGenInput; 8 | indices = indices.asUGenInput; 9 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm) ?? { 10 | ("FluidBufNoveltySlice: % is not a recognised algorithm") 11 | .format(algorithm).throw; 12 | }; 13 | 14 | source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; 15 | indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; 16 | 17 | ^FluidProxyUgen.kr(\FluidBufNoveltySliceTrigger, -1, source, startFrame, numFrames, startChan, numChans, indices, algorithm, kernelSize, kernelSize, threshold, filterSize, filterSize, minSliceLength, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 18 | 19 | } 20 | 21 | *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 | 22 | 23 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 24 | 25 | source = source.asUGenInput; 26 | indices = indices.asUGenInput; 27 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm); 28 | if (algorithm.isNil or: algorithm.isUGen) { 29 | ("FluidBufNoveltySlice: % is not a recognised algorithm") 30 | .format(algorithm).throw; 31 | }; 32 | 33 | source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; 34 | indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; 35 | 36 | ^this.new( 37 | server, nil, [indices] 38 | ).processList( 39 | [source, startFrame, numFrames, startChan, numChans, indices, algorithm, kernelSize, kernelSize, threshold, filterSize, filterSize, minSliceLength, windowSize, hopSize, fftSize, maxFFTSize, 0],freeWhenDone,action 40 | ); 41 | } 42 | 43 | *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 | 44 | 45 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 46 | 47 | source = source.asUGenInput; 48 | indices = indices.asUGenInput; 49 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm); 50 | if (algorithm.isNil or: algorithm.isUGen) { 51 | ("FluidBufNoveltySlice: % is not a recognised algorithm") 52 | .format(algorithm).throw; 53 | }; 54 | 55 | source.isNil.if {"FluidBufNoveltySlice: Invalid source buffer".throw}; 56 | indices.isNil.if {"FluidBufNoveltySlice: Invalid features buffer".throw}; 57 | 58 | ^this.new( 59 | server, nil, [indices] 60 | ).processList( 61 | [source, startFrame, numFrames, startChan, numChans, indices, algorithm, kernelSize, kernelSize, threshold, filterSize, filterSize, minSliceLength, windowSize, hopSize, fftSize, maxFFTSize, 1],freeWhenDone,action 62 | ); 63 | } 64 | } 65 | FluidBufNoveltySliceTrigger : FluidProxyUgen {} 66 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufOnsetFeature.sc: -------------------------------------------------------------------------------- 1 | FluidBufOnsetFeature : FluidBufProcessor { 2 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, metric = 0, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 3 | 4 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 5 | 6 | source = source.asUGenInput; 7 | features = features.asUGenInput; 8 | metric = FluidOnsetSlice.prSelectMetric(metric) ?? { 9 | ("FluidBufOnsetSlice: % is not a recognised metric") 10 | .format(metric).throw; 11 | }; 12 | 13 | source.isNil.if {"FluidBufOnsetFeature: Invalid source buffer".throw}; 14 | features.isNil.if {"FluidBufOnsetFeature: Invalid features buffer".throw}; 15 | 16 | ^FluidProxyUgen.kr(\FluidBufOnsetFeatureTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, metric, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 17 | } 18 | 19 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, metric = 0, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 20 | 21 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 22 | 23 | source = source.asUGenInput; 24 | features = features.asUGenInput; 25 | metric = FluidOnsetSlice.prSelectMetric(metric); 26 | if (metric.isNil or: metric.isUGen) { 27 | ("FluidBufOnsetSlice: % is not a recognised metric") 28 | .format(metric).throw; 29 | }; 30 | 31 | source.isNil.if {"FluidBufOnsetFeature: Invalid source buffer".throw}; 32 | features.isNil.if {"FluidBufOnsetFeature: Invalid features buffer".throw}; 33 | 34 | ^this.new( 35 | server, nil, [features] 36 | ).processList( 37 | [source, startFrame, numFrames, startChan, numChans, features, padding, metric, filterSize, frameDelta, windowSize, hopSize, fftSize,maxFFTSize,0],freeWhenDone,action 38 | ); 39 | } 40 | 41 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, metric = 0, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1,padding = 1, freeWhenDone = true, action| 42 | 43 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 44 | 45 | source = source.asUGenInput; 46 | features = features.asUGenInput; 47 | metric = FluidOnsetSlice.prSelectMetric(metric); 48 | if (metric.isNil or: metric.isUGen) { 49 | ("FluidBufOnsetSlice: % is not a recognised metric") 50 | .format(metric).throw; 51 | }; 52 | 53 | source.isNil.if {"FluidBufOnsetFeature: Invalid source buffer".throw}; 54 | features.isNil.if {"FluidBufOnsetFeature: Invalid features buffer".throw}; 55 | 56 | ^this.new( 57 | server, nil, [features] 58 | ).processList( 59 | [source, startFrame, numFrames, startChan, numChans, features, padding, metric, filterSize, frameDelta, windowSize, hopSize, fftSize,maxFFTSize,1],freeWhenDone,action 60 | ); 61 | } 62 | } 63 | FluidBufOnsetFeatureTrigger : FluidProxyUgen {} 64 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufOnsetSlice.sc: -------------------------------------------------------------------------------- 1 | FluidBufOnsetSlice : FluidBufProcessor { 2 | 3 | *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| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | source = source.asUGenInput; 8 | indices = indices.asUGenInput; 9 | metric = FluidOnsetSlice.prSelectMetric(metric) ?? { 10 | ("FluidBufOnsetSlice: % is not a recognised metric") 11 | .format(metric).throw; 12 | }; 13 | 14 | source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw}; 15 | indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw}; 16 | 17 | ^FluidProxyUgen.kr(\FluidBufOnsetSliceTrigger, -1, source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 18 | } 19 | 20 | *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| 21 | 22 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 23 | 24 | source = source.asUGenInput; 25 | indices = indices.asUGenInput; 26 | metric = FluidOnsetSlice.prSelectMetric(metric); 27 | if (metric.isNil or: metric.isUGen) { 28 | ("FluidBufOnsetSlice: % is not a recognised metric") 29 | .format(metric).throw; 30 | }; 31 | 32 | source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw}; 33 | indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw}; 34 | 35 | ^this.new( 36 | server, nil, [indices] 37 | ).processList( 38 | [source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize,maxFFTSize,0],freeWhenDone,action 39 | ); 40 | } 41 | 42 | *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| 43 | 44 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 45 | 46 | source = source.asUGenInput; 47 | indices = indices.asUGenInput; 48 | metric = FluidOnsetSlice.prSelectMetric(metric); 49 | if (metric.isNil or: metric.isUGen) { 50 | ("FluidBufOnsetSlice: % is not a recognised metric") 51 | .format(metric).throw; 52 | }; 53 | 54 | source.isNil.if {"FluidBufOnsetSlice: Invalid source buffer".throw}; 55 | indices.isNil.if {"FluidBufOnsetSlice: Invalid features buffer".throw}; 56 | 57 | ^this.new( 58 | server, nil, [indices] 59 | ).processList( 60 | [source, startFrame, numFrames, startChan, numChans, indices, metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize,maxFFTSize,1],freeWhenDone,action 61 | ); 62 | } 63 | } 64 | FluidBufOnsetSliceTrigger : FluidProxyUgen {} 65 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufPitch.sc: -------------------------------------------------------------------------------- 1 | FluidBufPitch : FluidBufProcessor{ 2 | 3 | const (1< 1) { ("Option '" ++ item ++ "' is repeated").warn}; 16 | }; 17 | bits = a.collect{ |sym| 18 | (featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0}) 19 | }.reduce{|x,y| x | y}; 20 | ^bits 21 | } 22 | 23 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 24 | 25 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 26 | 27 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 28 | 29 | source = source.asUGenInput; 30 | features = features.asUGenInput; 31 | 32 | source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; 33 | features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; 34 | 35 | ^FluidProxyUgen.kr(\FluidBufPitchTrigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 36 | 37 | } 38 | 39 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 40 | 41 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 42 | 43 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 44 | 45 | source = source.asUGenInput; 46 | features = features.asUGenInput; 47 | 48 | source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; 49 | features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; 50 | 51 | ^this.new( 52 | server, nil, [features] 53 | ).processList( 54 | [source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone, action 55 | ); 56 | } 57 | 58 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 59 | 60 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 61 | 62 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 63 | 64 | source = source.asUGenInput; 65 | features = features.asUGenInput; 66 | 67 | source.isNil.if {"FluidBufPitch: Invalid source buffer".throw}; 68 | features.isNil.if {"FluidBufPitch: Invalid features buffer".throw}; 69 | 70 | ^this.new( 71 | server, nil, [features] 72 | ).processList( 73 | [source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone, action 74 | ); 75 | } 76 | } 77 | FluidBufPitchTrigger : FluidProxyUgen {} 78 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufSTFT.sc: -------------------------------------------------------------------------------- 1 | FluidBufSTFT : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0,windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 1| 4 | 5 | source = source ? -1; 6 | magnitude = magnitude ? -1; 7 | phase = phase ? -1; 8 | resynth = resynth ? - 1; 9 | 10 | ^FluidProxyUgen.kr(\FluidBufSTFTTrigger, -1, source, startFrame, numFrames, startChan, magnitude, phase, resynth, inverse, padding, windowSize, hopSize, fftSize, -1, trig, blocking); 11 | } 12 | 13 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 14 | 15 | source = source ? -1; 16 | magnitude = magnitude ? -1; 17 | phase = phase ? -1; 18 | resynth = resynth ? - 1; 19 | 20 | ^this.new( 21 | server, nil, [magnitude,phase,resynth].select{|b| b != -1} 22 | ).processList( 23 | [source, startFrame, numFrames, startChan, magnitude, phase, resynth, inverse, padding, windowSize, hopSize, fftSize, -1, 0], freeWhenDone, action 24 | ); 25 | } 26 | 27 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, magnitude, phase, resynth, inverse = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1,freeWhenDone = true, action| 28 | 29 | source = source ? -1; 30 | magnitude = magnitude ? -1; 31 | phase = phase ? -1; 32 | resynth = resynth ? - 1; 33 | 34 | ^this.new( 35 | server, nil, [magnitude,phase,resynth].select{|b| b != -1} 36 | ).processList( 37 | [source, startFrame, numFrames, startChan, magnitude, phase, resynth, inverse, padding, windowSize, hopSize, fftSize, -1, 1], freeWhenDone, action 38 | ); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufScale.sc: -------------------------------------------------------------------------------- 1 | FluidBufScale : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, inputLow = 0, inputHigh = 1, outputLow = 0, outputHigh = 1, clipping = 0, trig = 1, blocking = 1| 4 | 5 | source = source.asUGenInput; 6 | destination = destination.asUGenInput; 7 | 8 | source.isNil.if {"FluidBufScale: Invalid source buffer".throw}; 9 | destination.isNil.if {"FluidBufScale: Invalid destination buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufScaleTrigger, -1, source, startFrame, numFrames, startChan, numChans, destination, inputLow, inputHigh, outputLow, outputHigh, clipping, trig, blocking); 12 | } 13 | 14 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, inputLow = 0, inputHigh = 1, outputLow = 0, outputHigh = 1, clipping = 0, freeWhenDone = true, action| 15 | 16 | source = source.asUGenInput; 17 | destination = destination.asUGenInput; 18 | 19 | source.isNil.if {"FluidBufScale: Invalid source buffer".throw}; 20 | destination.isNil.if {"FluidBufScale: Invalid destination buffer".throw}; 21 | 22 | ^this.new( 23 | server, nil, [destination] 24 | ).processList( 25 | [source, startFrame, numFrames, startChan, numChans, destination, inputLow, inputHigh, outputLow, outputHigh, clipping, 0], freeWhenDone, action 26 | ); 27 | } 28 | 29 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, inputLow = 0, inputHigh = 1, outputLow = 0, outputHigh = 1, clipping = 0, freeWhenDone = true, action| 30 | 31 | source = source.asUGenInput; 32 | destination = destination.asUGenInput; 33 | 34 | source.isNil.if {"FluidBufScale: Invalid source buffer".throw}; 35 | destination.isNil.if {"FluidBufScale: Invalid destination buffer".throw}; 36 | 37 | ^this.new( 38 | server, nil, [destination] 39 | ).processList( 40 | [source, startFrame, numFrames, startChan, numChans, destination, inputLow, inputHigh, outputLow, outputHigh, clipping, 1], freeWhenDone, action 41 | ); 42 | } 43 | } 44 | FluidBufScaleTrigger : FluidProxyUgen {} 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufSelect.sc: -------------------------------------------------------------------------------- 1 | FluidBufSelect : FluidBufProcessor { 2 | 3 | *kr { |source, destination, indices=#[-1], channels=#[-1], trig = 1, blocking = 1| 4 | 5 | var params; 6 | 7 | source = source.asUGenInput; 8 | destination = destination.asUGenInput; 9 | 10 | indices = indices.asArray; 11 | channels = channels.asArray; 12 | 13 | indices = [indices.size] ++ indices; 14 | channels = [channels.size] ++ channels; 15 | 16 | source.isNil.if {"FluidBufSelect: Invalid source buffer".throw}; 17 | destination.isNil.if {"FluidBufSelect: Invalid destination buffer".throw}; 18 | 19 | params = indices ++ channels ++ [trig, blocking] 20 | 21 | ^FluidProxyUgen.kr(\FluidBufSelectTrigger,-1, source, destination, *params); 22 | } 23 | 24 | 25 | *process { |server, source, destination, indices=#[-1], channels=#[-1], freeWhenDone = true, action| 26 | 27 | source = source.asUGenInput; 28 | destination = destination.asUGenInput; 29 | 30 | source.isNil.if {"FluidBufSelect: Invalid source buffer".throw}; 31 | destination.isNil.if {"FluidBufSelect: Invalid destination buffer".throw}; 32 | 33 | indices = indices.asArray; 34 | channels = channels.asArray; 35 | 36 | indices = [indices.size] ++ indices; 37 | channels = [channels.size] ++ channels; 38 | 39 | ^this.new(server, nil, [destination]).processList([source, destination]++ indices ++ channels ++ [1], freeWhenDone, action);//NB always blocking 40 | } 41 | 42 | *processBlocking { |server, source, destination, indices=#[-1], channels=#[-1], freeWhenDone = true, action| 43 | 44 | source = source.asUGenInput; 45 | destination = destination.asUGenInput; 46 | 47 | source.isNil.if {"FluidBufSelect: Invalid source buffer".throw}; 48 | destination.isNil.if {"FluidBufSelect: Invalid destination buffer".throw}; 49 | 50 | indices = indices.asArray; 51 | channels = channels.asArray; 52 | 53 | indices = [indices.size] ++ indices; 54 | channels = [channels.size] ++ channels; 55 | 56 | 57 | ^this.new( 58 | server, nil, [destination] 59 | ).processList([source, destination]++ indices ++ channels ++ [1], freeWhenDone, action);//NB always blocking 60 | } 61 | } 62 | FluidBufSelectTrigger : FluidProxyUgen {} 63 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufSelectEvery.sc: -------------------------------------------------------------------------------- 1 | FluidBufSelectEvery : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, frameHop = 1, chanHop = 1, trig = 1, blocking = 1| 4 | 5 | source = source.asUGenInput; 6 | destination = destination.asUGenInput; 7 | 8 | source.isNil.if {"FluidBufSelectEvery: Invalid source buffer".throw}; 9 | destination.isNil.if {"FluidBufSelectEvery: Invalid destination buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufSelectEveryTrigger, -1, source, startFrame, numFrames, startChan, numChans, destination, frameHop, chanHop, trig, blocking); 12 | } 13 | 14 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, frameHop = 1, chanHop = 1, freeWhenDone = true, action| 15 | 16 | source = source.asUGenInput; 17 | destination = destination.asUGenInput; 18 | 19 | source.isNil.if {"FluidBufSelectEvery: Invalid source buffer".throw}; 20 | destination.isNil.if {"FluidBufSelectEvery: Invalid destination buffer".throw}; 21 | 22 | ^this.new( 23 | server, nil, [destination] 24 | ).processList( 25 | [source, startFrame, numFrames, startChan, numChans, destination, frameHop, chanHop, 0], freeWhenDone, action 26 | ); 27 | } 28 | 29 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, destination, frameHop = 1, chanHop = 1, freeWhenDone = true, action| 30 | 31 | source = source.asUGenInput; 32 | destination = destination.asUGenInput; 33 | 34 | source.isNil.if {"FluidBufSelectEvery: Invalid source buffer".throw}; 35 | destination.isNil.if {"FluidBufSelectEvery: Invalid destination buffer".throw}; 36 | 37 | ^this.new( 38 | server, nil, [destination] 39 | ).processList( 40 | [source, startFrame, numFrames, startChan, numChans, destination, frameHop, chanHop, 1], freeWhenDone, action 41 | ); 42 | } 43 | } 44 | FluidBufSelectEveryTrigger : FluidProxyUgen {} 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufSineFeature.sc: -------------------------------------------------------------------------------- 1 | FluidBufSineFeature : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, frequency = -1, magnitude = -1, numPeaks = 10, detectionThreshold = -96, order = 0, freqUnit = 0, magUnit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | source = source.asUGenInput; 8 | frequency = frequency !? {frequency.asUGenInput} ?? {-1}; 9 | magnitude = magnitude !? {magnitude.asUGenInput} ?? {-1}; 10 | 11 | source.isNil.if {"FluidBufSineFeature: Invalid source buffer".throw}; 12 | 13 | ^FluidProxyUgen.multiNew(\FluidBufSineFeatureTrigger, -1, source, startFrame, numFrames, startChan, numChans, frequency, magnitude, padding, numPeaks, numPeaks, detectionThreshold, order, freqUnit, magUnit, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 14 | } 15 | 16 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, frequency = -1, magnitude = -1, numPeaks = 10, detectionThreshold = -96, order = 0, freqUnit = 0, magUnit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 17 | 18 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 19 | 20 | source = source.asUGenInput; 21 | frequency = frequency !? {frequency.asUGenInput} ?? {-1}; 22 | magnitude = magnitude !? {magnitude.asUGenInput} ?? {-1}; 23 | 24 | source.isNil.if {"FluidBufSineFeature: Invalid source buffer".throw}; 25 | 26 | ^this.new( 27 | server, nil, [frequency, magnitude].select{|x| x!= -1} 28 | ).processList( 29 | [source, startFrame, numFrames, startChan, numChans, frequency, magnitude, padding, numPeaks, numPeaks, detectionThreshold, order, freqUnit, magUnit, windowSize, hopSize, fftSize,maxFFTSize,0],freeWhenDone,action 30 | ); 31 | } 32 | 33 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, frequency = -1, magnitude = -1, numPeaks = 10, detectionThreshold = -96, order = 0, freqUnit = 0, magUnit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 34 | 35 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 36 | 37 | source = source.asUGenInput; 38 | frequency = frequency !? {frequency.asUGenInput} ?? {-1}; 39 | magnitude = magnitude !? {magnitude.asUGenInput} ?? {-1}; 40 | 41 | source.isNil.if {"FluidBufSineFeature: Invalid source buffer".throw}; 42 | 43 | ^this.new( 44 | server, nil, [frequency, magnitude].select{|x| x!= -1} 45 | ).processList( 46 | [source, startFrame, numFrames, startChan, numChans, frequency, magnitude, padding, numPeaks, numPeaks, detectionThreshold, order, freqUnit, magUnit, windowSize, hopSize, fftSize,maxFFTSize,1],freeWhenDone,action 47 | ); 48 | } 49 | 50 | } 51 | FluidBufSineFeatureTrigger : FluidProxyUgen {} -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufSines.sc: -------------------------------------------------------------------------------- 1 | FluidBufSines : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, detectionThreshold = -96, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 15, trackMethod = 0, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, windowSize = 1024, hopSize = -1, fftSize = -1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | 7 | source = source.asUGenInput; 8 | sines = sines !? {sines.asUGenInput} ?? {-1}; 9 | residual = residual !? {residual.asUGenInput} ?? {-1}; 10 | 11 | source.isNil.if {"FluidBufSines: Invalid source buffer".throw}; 12 | 13 | ^FluidProxyUgen.multiNew(\FluidBufSinesTrigger, -1, source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, detectionThreshold,birthLowThreshold, birthHighThreshold, minTrackLen, trackMethod, trackMagRange, trackFreqRange, trackProb, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 14 | } 15 | 16 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, detectionThreshold = -96, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 15, trackMethod = 0, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 17 | 18 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 19 | 20 | source = source.asUGenInput; 21 | sines = sines !? {sines.asUGenInput} ?? {-1}; 22 | residual = residual !? {residual.asUGenInput} ?? {-1}; 23 | 24 | source.isNil.if {"FluidBufSines: Invalid source buffer".throw}; 25 | 26 | ^this.new( 27 | server, nil, [sines, residual].select{|x| x!= -1} 28 | ).processList( 29 | [source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, detectionThreshold,birthLowThreshold, birthHighThreshold, minTrackLen, trackMethod, trackMagRange, trackFreqRange, trackProb, windowSize, hopSize, fftSize,maxFFTSize,0],freeWhenDone = true,action 30 | ); 31 | } 32 | 33 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, sines = -1, residual = -1, bandwidth = 76, detectionThreshold = -96, birthLowThreshold = -24, birthHighThreshold = -60, minTrackLen = 15, trackMethod = 0, trackMagRange = 15, trackFreqRange = 50, trackProb = 0.5, windowSize = 1024, hopSize = -1, fftSize = -1, freeWhenDone = true, action| 34 | 35 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 36 | 37 | source = source.asUGenInput; 38 | sines = sines !? {sines.asUGenInput} ?? {-1}; 39 | residual = residual !? {residual.asUGenInput} ?? {-1}; 40 | 41 | source.isNil.if {"FluidBufSines: Invalid source buffer".throw}; 42 | 43 | ^this.new( 44 | server, nil, [sines, residual].select{|x| x!= -1} 45 | ).processList( 46 | [source, startFrame, numFrames, startChan, numChans, sines, residual, bandwidth, detectionThreshold,birthLowThreshold, birthHighThreshold, minTrackLen, trackMethod, trackMagRange, trackFreqRange, trackProb, windowSize, hopSize, fftSize,maxFFTSize,1],freeWhenDone,action 47 | ); 48 | } 49 | 50 | } 51 | FluidBufSinesTrigger : FluidProxyUgen {} 52 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufSpectralShape.sc: -------------------------------------------------------------------------------- 1 | FluidBufSpectralShape : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, trig = 1, blocking = 0| 4 | 5 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 6 | var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)}; 7 | 8 | source = source.asUGenInput; 9 | features = features.asUGenInput; 10 | 11 | source.isNil.if {"FluidBufSpectralShape: Invalid source buffer".throw}; 12 | features.isNil.if {"FluidBufSpectralShape: Invalid features buffer".throw}; 13 | 14 | 15 | ^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, trig, blocking); 16 | 17 | } 18 | 19 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 20 | 21 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 22 | var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)}; 23 | 24 | source = source.asUGenInput; 25 | features = features.asUGenInput; 26 | 27 | source.isNil.if {"FluidBufSpectralShape: Invalid source buffer".throw}; 28 | features.isNil.if {"FluidBufSpectralShape: Invalid features buffer".throw}; 29 | 30 | ^this.new( 31 | server, nil, [features] 32 | ).processList( 33 | [source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 0], freeWhenDone, action 34 | ); 35 | } 36 | 37 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, features, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, padding = 1, freeWhenDone = true, action| 38 | 39 | var maxFFTSize = if (fftSize == -1) {windowSize.nextPowerOfTwo} {fftSize}; 40 | var selectbits = select !? {FluidSpectralShape.prProcessSelect(select)} ?? {FluidSpectralShape.prProcessSelect(FluidSpectralShape.features)}; 41 | 42 | source = source.asUGenInput; 43 | features = features.asUGenInput; 44 | 45 | source.isNil.if {"FluidBufSpectralShape: Invalid source buffer".throw}; 46 | features.isNil.if {"FluidBufSpectralShape: Invalid features buffer".throw}; 47 | 48 | ^this.new( 49 | server, nil, [features] 50 | ).processList( 51 | [source, startFrame, numFrames, startChan, numChans, features, padding, selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize, 1], freeWhenDone, action 52 | ); 53 | } 54 | } 55 | FluidBufSpectralShapeTrigger : FluidProxyUgen {} 56 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufStats.sc: -------------------------------------------------------------------------------- 1 | FluidBufStats : FluidBufProcessor { 2 | 3 | const 1) { ("Option '" ++ item ++ "' is repeated").warn}; 12 | }; 13 | bits = a.collect{ |sym| 14 | (statslookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0}) 15 | }.reduce{|x,y| x | y}; 16 | ^bits 17 | } 18 | 19 | *initClass { 20 | statslookup = Dictionary.with(*this.stats.collect{|x,i| x->(1< 1000){ 19 | Error("% Buffer is % frames. This is probably not the buffer you intended.".format(this.class,buffer.numFrames)).throw; 20 | }; 21 | 22 | // out of bounds check 23 | if((destStartFrame + krNumChans) > buffer.numFrames,{ 24 | Error("% (destStartFrame + krNumChans) > buffer.numFrames".format(this.class)).throw; 25 | }); 26 | 27 | }); 28 | 29 | ^(krStartChan..endChan).do{ 30 | arg kr_i, i; 31 | BufWr.kr(krStream[kr_i], buffer, destStartFrame + i); 32 | } 33 | } 34 | } 35 | 36 | FluidBufToKr { 37 | *kr { 38 | arg buffer, startFrame = 0, numFrames = -1; 39 | 40 | if(buffer.isKindOf(Buffer) or: {buffer.isKindOf(LocalBuf)},{ 41 | 42 | // fix default -1 43 | if(numFrames == -1,{numFrames = buffer.numFrames - startFrame}); 44 | 45 | // dummy check 46 | if(numFrames < 1,{Error("% numFrames must be >= 1".format(this.class)).throw}); 47 | 48 | // out of bounds check 49 | if((startFrame+numFrames) > buffer.numFrames,{Error("% (startFrame + numFrames) > buffer.numFrames".format(this.class)).throw;}); 50 | 51 | },{ 52 | // make sure the numFrames give is a positive integer 53 | if((numFrames < 1) || (numFrames.isInteger.not),{ 54 | Error("% if no buffer is specified, numFrames must be a value >= 1.".format(this.class)).throw; 55 | }); 56 | }); 57 | 58 | // oopsie check 59 | if(numFrames > 1000) { 60 | Error("%: numframes is % frames. This is probably not what you intended.".format(this.class, numFrames)).throw; 61 | }; 62 | 63 | if(numFrames > 1,{ 64 | ^numFrames.asInteger.collect{ 65 | arg i; 66 | BufRd.kr(1,buffer,i+startFrame,0,0); 67 | } 68 | },{ 69 | ^BufRd.kr(1,buffer,startFrame,0,0); 70 | }); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufTransientSlice.sc: -------------------------------------------------------------------------------- 1 | FluidBufTransientSlice : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, trig = 1, blocking = 0| 4 | 5 | source = source.asUGenInput; 6 | indices = indices.asUGenInput; 7 | 8 | source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw}; 9 | indices.isNil.if {"%: Invalid features buffer".format(this.class.name).throw}; 10 | 11 | ^FluidProxyUgen.kr(this.objectClassName++\Trigger, -1, source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength, trig, blocking); 12 | } 13 | 14 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, freeWhenDone = true, action| 15 | 16 | source = source.asUGenInput; 17 | indices = indices.asUGenInput; 18 | 19 | source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw}; 20 | indices.isNil.if {"%: Invalid features buffer".format(this.class.name).throw}; 21 | 22 | ^this.new( 23 | server, nil,[indices] 24 | ).processList([source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength,0], freeWhenDone, action 25 | ); 26 | } 27 | 28 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, indices, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, minSliceLength = 1000, freeWhenDone = true, action| 29 | 30 | source = source.asUGenInput; 31 | indices = indices.asUGenInput; 32 | 33 | source.isNil.if {"%: Invalid source buffer".format(this.class.name).throw}; 34 | indices.isNil.if {"%: Invalid features buffer".format(this.class.name).throw}; 35 | 36 | ^this.new( 37 | server, nil,[indices] 38 | ).processList([source, startFrame, numFrames, startChan, numChans, indices, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, minSliceLength,1], freeWhenDone, action 39 | ); 40 | } 41 | } 42 | FluidBufTransientSliceTrigger : FluidProxyUgen {} 43 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidBufTransients.sc: -------------------------------------------------------------------------------- 1 | FluidBufTransients : FluidBufProcessor { 2 | 3 | *kr { |source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, trig = 1, blocking = 0| 4 | 5 | source = source.asUGenInput; 6 | transients = transients ? -1; 7 | residual = residual ? -1; 8 | 9 | source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; 10 | 11 | ^FluidProxyUgen.kr(\FluidBufTransientsTrigger, -1, source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength, trig, blocking); 12 | } 13 | 14 | *process { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, freeWhenDone = true, action| 15 | 16 | source = source.asUGenInput; 17 | transients = transients ? -1; 18 | residual = residual ? -1; 19 | 20 | source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; 21 | 22 | ^this.new( 23 | server, nil,[transients, residual].select{|x| x!= -1} 24 | ).processList( 25 | [source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength,0],freeWhenDone,action 26 | ); 27 | } 28 | 29 | *processBlocking { |server, source, startFrame = 0, numFrames = -1, startChan = 0, numChans = -1, transients = -1, residual = -1, order = 20, blockSize = 256, padSize = 128, skew = 0, threshFwd = 2, threshBack = 1.1, windowSize = 14, clumpLength = 25, freeWhenDone = true, action| 30 | 31 | source = source.asUGenInput; 32 | transients = transients ? -1; 33 | residual = residual ? -1; 34 | 35 | source.isNil.if {"FluidBufTransients: Invalid source buffer".throw}; 36 | 37 | ^this.new( 38 | server, nil,[transients, residual].select{|x| x!= -1} 39 | ).processList( 40 | [source, startFrame, numFrames, startChan, numChans, transients, residual, order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength,1],freeWhenDone = true,action 41 | ); 42 | } 43 | } 44 | FluidBufTransientsTrigger : FluidProxyUgen {} 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidChroma.sc: -------------------------------------------------------------------------------- 1 | FluidChroma : FluidRTMultiOutUGen { 2 | 3 | *kr { arg in = 0, numChroma = 12, ref = 440, normalize = 0, minFreq = 0, maxFreq = -1, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1, maxNumChroma; 4 | 5 | maxNumChroma = maxNumChroma ? numChroma; 6 | 7 | ^this.multiNew('control', in.asAudioRateInput(this), numChroma, maxNumChroma, ref, normalize, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize); 8 | } 9 | 10 | init {arg ...theInputs; 11 | inputs = theInputs; 12 | ^this.initOutputs(inputs.at(2),rate); //this instantiate the number of output from the maxNumCoeffs in the multiNew order 13 | } 14 | 15 | checkInputs { 16 | // the checks of rates here are in the order of the kr method definition 17 | if(inputs.at(2).rate != 'scalar') { 18 | ^(": maxNumChroma cannot be modulated."); 19 | }; 20 | if(inputs.at(10).rate != 'scalar') { 21 | ^(": maxFFTSize cannot be modulated."); 22 | };^this.checkValidInputs; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidDataSetQuery.sc: -------------------------------------------------------------------------------- 1 | FluidDataSetQuery : FluidDataObject { 2 | *new{|server| ^super.new(server) } 3 | 4 | addColumnMsg { |column| 5 | ^this.prMakeMsg(\addColumn,id,column); 6 | } 7 | 8 | addColumn{|column, action| 9 | actions[\addColumn] = [nil,action]; 10 | this.prSendMsg(this.addColumnMsg(column)); 11 | } 12 | 13 | addRangeMsg{|start,count| 14 | ^this.prMakeMsg(\addRange,id,start,count); 15 | } 16 | 17 | addRange{|start, count, action| 18 | actions[\addRange] = [nil, action]; 19 | this.prSendMsg(this.addRangeMsg(start, count)); 20 | } 21 | 22 | filterMsg{|column, condition, value, action| 23 | ^this.prMakeMsg(\filter,id,column,condition.asSymbol,value); 24 | } 25 | 26 | filter{|column, condition, value, action| 27 | actions[\filter] = [nil, action]; 28 | this.prSendMsg(this.filterMsg(column, condition, value)); 29 | } 30 | 31 | andMsg{ |column, condition, value| 32 | ^this.prMakeMsg(\and,id,column, condition.asSymbol, value); 33 | } 34 | 35 | and{|column, condition, value, action| 36 | actions[\and] = [nil, action]; 37 | this.prSendMsg(this.andMsg(column,condition,value)); 38 | } 39 | 40 | orMsg{|column, condition, value| 41 | ^this.prMakeMsg(\or,id,column, condition.asSymbol, value) 42 | } 43 | 44 | or{|column, condition, value, action| 45 | actions[\or] = [nil,action]; 46 | this.prSendMsg(this.orMsg(column, condition, value)); 47 | } 48 | 49 | clearMsg{ 50 | ^this.prMakeMsg(\clear,id); 51 | } 52 | 53 | clear{|action| 54 | actions[\clear] = [nil, action]; 55 | this.prSendMsg(this.clearMsg); 56 | } 57 | 58 | limitMsg{|points| 59 | ^this.prMakeMsg(\limit,id,points); 60 | } 61 | 62 | limit{|points, action| 63 | actions[\limit] = [nil,action]; 64 | this.prSendMsg(this.limitMsg(points)); 65 | } 66 | 67 | transformMsg{|sourceDataSet, destDataSet| 68 | ^this.prMakeMsg(\transform,id,sourceDataSet.id,destDataSet.id); 69 | } 70 | 71 | transform{|sourceDataSet, destDataSet, action| 72 | actions[\transform] = [nil,action]; 73 | this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); 74 | } 75 | 76 | transformJoinMsg{|source1DataSet, source2DataSet, destDataSet| 77 | ^this.prMakeMsg(\transformJoin,id,source1DataSet.id, source2DataSet.id, destDataSet.id); 78 | } 79 | 80 | transformJoin{|source1DataSet, source2DataSet, destDataSet, action| 81 | actions[\transformJoin] = [nil,action]; 82 | this.prSendMsg(this.transformJoinMsg(source1DataSet, source2DataSet, destDataSet)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidDataSetWr.sc: -------------------------------------------------------------------------------- 1 | FluidDataSetWr : FluidBufProcessor { 2 | *kr { |dataset,idPrefix = "", idNumber = 0,buf, trig=1, blocking = 1| 3 | var args; 4 | buf ?? {(this.class.name ++ ": No input buffer provided").error}; 5 | 6 | idNumber = idNumber !? {[2,1,idNumber.asInteger.asUGenInput]} ?? {[2,0,0]}; 7 | idPrefix = idPrefix !? {[idPrefix.asString.size] ++ idPrefix.asString.ascii} ?? {0}; 8 | 9 | args = [-1] ++ dataset.asUGenInput ++idPrefix ++ idNumber ++ buf.asUGenInput ++ trig ++ blocking; 10 | 11 | ^FluidProxyUgen.kr(\FluidDataSetWrTrigger,*args); 12 | } 13 | } 14 | 15 | FluidDataSetWrTrigger : FluidProxyUgen {} 16 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidFilesPath.sc: -------------------------------------------------------------------------------- 1 | FluidFilesPath { 2 | *new { 3 | arg fileName; 4 | fileName = fileName ? ""; 5 | ^("%/../Resources/AudioFiles/".format(File.realpath(FluidDataSet.class.filenameSymbol).dirname) +/+ fileName); 6 | } 7 | } -------------------------------------------------------------------------------- /release-packaging/Classes/FluidGain.sc: -------------------------------------------------------------------------------- 1 | FluidGain : UGen { 2 | *ar { arg in = 0, gain=1.0; 3 | ^this.multiNew('audio', in.asAudioRateInput(this), gain) 4 | } 5 | } 6 | 7 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidGrid.sc: -------------------------------------------------------------------------------- 1 | FluidGrid : FluidModelObject { 2 | var <>oversample, <>extent, <>axis; 3 | *new {|server, oversample = 1, extent = 0, axis = 0| 4 | ^super.new(server,[oversample, extent, axis]) 5 | .oversample_(oversample).extent_(extent).axis_(axis); 6 | } 7 | 8 | prGetParams{ 9 | ^[this.oversample, this.extent, this.axis]; 10 | } 11 | 12 | fitTransformMsg{|sourceDataSet, destDataSet| 13 | ^this.prMakeMsg(\fitTransform,id, sourceDataSet.id, destDataSet.id); 14 | } 15 | 16 | fitTransform{|sourceDataSet, destDataSet, action| 17 | actions[\fitTransform] = [nil,action]; 18 | this.fitTransformMsg(sourceDataSet,destDataSet); 19 | this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidHPSS.sc: -------------------------------------------------------------------------------- 1 | FluidHPSS : FluidRTMultiOutUGen { 2 | *ar { arg in = 0, harmFilterSize=17, percFilterSize = 31, maskingMode=0, harmThreshFreq1 = 0.1, harmThreshAmp1 = 0, harmThreshFreq2 = 0.5, harmThreshAmp2 = 0, percThreshFreq1 = 0.1, percThreshAmp1 = 0, percThreshFreq2 = 0.5, percThreshAmp2 = 0, windowSize= 1024, hopSize= -1, fftSize= -1, maxFFTSize = -1, maxHarmFilterSize, maxPercFilterSize; 3 | 4 | maxHarmFilterSize = maxHarmFilterSize ? harmFilterSize; 5 | maxPercFilterSize = maxPercFilterSize ? percFilterSize; 6 | 7 | ^this.multiNew('audio', in.asAudioRateInput(this), harmFilterSize, maxHarmFilterSize, percFilterSize, maxPercFilterSize, maskingMode, harmThreshFreq1, harmThreshAmp1, harmThreshFreq2, harmThreshAmp2, percThreshFreq1, percThreshAmp1, percThreshFreq2, percThreshAmp2, windowSize, hopSize, fftSize, maxFFTSize) 8 | } 9 | init { arg ... theInputs; 10 | inputs = theInputs; 11 | channels = [ 12 | OutputProxy(rate, this, 0), 13 | OutputProxy(rate, this, 1), 14 | OutputProxy(rate, this, 2) 15 | ]; 16 | ^channels 17 | } 18 | checkInputs { 19 | if(inputs.at(17).rate != 'scalar') { 20 | ^(": maxFFTSize cannot be modulated."); 21 | }; 22 | if(inputs.at(2).rate != 'scalar') { 23 | ^(": maxHarmFilterSize cannot be modulated."); 24 | }; 25 | if(inputs.at(4).rate != 'scalar') { 26 | ^(": maxPercFilterSize cannot be modulated."); 27 | }; 28 | ^this.checkValidInputs; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidKDTree.sc: -------------------------------------------------------------------------------- 1 | FluidKDTree : FluidModelObject 2 | { 3 | 4 | var neighbours,radius; 5 | 6 | *new{ |server, numNeighbours = 1, radius = 0| 7 | ^super.new(server,[numNeighbours,radius ? -1]) 8 | .numNeighbours_(numNeighbours) 9 | .radius_(radius); 10 | } 11 | 12 | numNeighbours_{|k|neighbours = k.asInteger; } 13 | numNeighbours{ ^neighbours; } 14 | 15 | radius_{|r| radius = r.asUGenInput;} 16 | radius{ ^radius; } 17 | 18 | prGetParams{^[this.id, this.numNeighbours,this.radius];} 19 | 20 | fitMsg{ |dataSet| ^this.prMakeMsg(\fit,this.id,dataSet.id);} 21 | 22 | fit{|dataSet,action| 23 | actions[\fit] = [nil,action]; 24 | this.prSendMsg(this.fitMsg(dataSet)); 25 | } 26 | 27 | kNearestMsg{|buffer,k| 28 | k !? 29 | {^this.prMakeMsg(\kNearest,id,this.prEncodeBuffer(buffer),k);} 30 | ?? 31 | {^this.prMakeMsg(\kNearest,id,this.prEncodeBuffer(buffer));} 32 | } 33 | 34 | kNearest{ |buffer, k, action| 35 | actions[\kNearest] = [strings(FluidMessageResponse,_,_),action]; 36 | this.prSendMsg(this.kNearestMsg(buffer,k)); 37 | } 38 | 39 | kNearestDistMsg {|buffer, k| 40 | k !? 41 | {^this.prMakeMsg(\kNearestDist,id,this.prEncodeBuffer(buffer),k);} 42 | ?? 43 | {^this.prMakeMsg(\kNearestDist,id,this.prEncodeBuffer(buffer));} 44 | } 45 | 46 | kNearestDist { |buffer, k, action| 47 | actions[\kNearestDist] = [numbers(FluidMessageResponse,_,nil,_),action]; 48 | this.prSendMsg(this.kNearestDistMsg(buffer,k)); 49 | } 50 | 51 | kr{|trig, inputBuffer, outputBuffer, numNeighbours, radius, lookupDataSet| 52 | ^FluidKDTreeQuery.kr(trig, 53 | this, numNeighbours??{this.numNeighbours}, radius??{this.radius}, lookupDataSet.asUGenInput, 54 | inputBuffer,outputBuffer); 55 | } 56 | 57 | } 58 | 59 | FluidKDTreeQuery : FluidRTMultiOutUGen 60 | { 61 | *kr{ |trig, tree, numNeighbours, radius, lookupDataSet, inputBuffer, outputBuffer | 62 | ^this.multiNew('control', trig, tree.asUGenInput, numNeighbours, radius, lookupDataSet!?(_.asUGenInput)??{-1}, inputBuffer.asUGenInput, outputBuffer.asUGenInput) 63 | } 64 | 65 | init { arg ... theInputs; 66 | inputs = theInputs; 67 | ^this.initOutputs(1, rate); 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidKNNClassifier.sc: -------------------------------------------------------------------------------- 1 | FluidKNNClassifier : FluidModelObject { 2 | 3 | var <>numNeighbours, <>weight; 4 | 5 | *new {|server, numNeighbours = 3, weight = 1| 6 | ^super.new(server,[numNeighbours,weight]) 7 | .numNeighbours_(numNeighbours) 8 | .weight_(weight); 9 | } 10 | 11 | prGetParams{^[this.id,this.numNeighbours,this.weight];} 12 | 13 | fitMsg{|dataSet, labelSet| 14 | ^this.prMakeMsg(\fit, id, dataSet.id, labelSet.id) 15 | } 16 | 17 | fit{|dataSet, labelSet, action| 18 | actions[\fit] = [nil,action]; 19 | this.prSendMsg(this.fitMsg(dataSet, labelSet)); 20 | } 21 | 22 | predictMsg{|dataSet, labelSet| 23 | ^this.prMakeMsg(\predict, id, dataSet.id, labelSet.id) 24 | } 25 | 26 | predict{|dataSet, labelSet, action| 27 | actions[\predict] = [nil, action]; 28 | this.prSendMsg(this.predictMsg(dataSet, labelSet)); 29 | } 30 | 31 | predictPointMsg{|buffer| 32 | ^this.prMakeMsg(\predictPoint, id, this.prEncodeBuffer(buffer)) 33 | } 34 | 35 | predictPoint {|buffer, action| 36 | actions[\predictPoint] = [string(FluidMessageResponse,_,_),action]; 37 | this.prSendMsg(this.predictPointMsg(buffer)); 38 | } 39 | 40 | kr{|trig, inputBuffer,outputBuffer| 41 | ^FluidKNNClassifierQuery.kr(trig, 42 | this, this.numNeighbours, this.weight, 43 | this.prEncodeBuffer(inputBuffer), 44 | this.prEncodeBuffer(outputBuffer)); 45 | } 46 | 47 | } 48 | 49 | FluidKNNClassifierQuery : FluidRTMultiOutUGen { 50 | 51 | *kr{ |trig, model,numNeighbours = 3, weight = 1,inputBuffer, outputBuffer | 52 | ^this.multiNew('control',trig, model.asUGenInput, 53 | numNeighbours,weight, 54 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 55 | } 56 | 57 | init { arg ... theInputs; 58 | inputs = theInputs; 59 | ^this.initOutputs(1, rate); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidKNNRegressor.sc: -------------------------------------------------------------------------------- 1 | FluidKNNRegressor : FluidModelObject { 2 | 3 | var <>numNeighbours, <>weight; 4 | 5 | *new {|server, numNeighbours = 3, weight = 1| 6 | ^super.new(server,[numNeighbours,weight]) 7 | .numNeighbours_(numNeighbours) 8 | .weight_(weight); 9 | } 10 | 11 | prGetParams{^[this.id,this.numNeighbours,this.weight,-1,-1];} 12 | 13 | fitMsg{|sourceDataSet, targetDataSet| 14 | ^this.prMakeMsg(\fit,this.id,sourceDataSet.id,targetDataSet.id) 15 | } 16 | 17 | fit{|sourceDataSet, targetDataSet, action| 18 | actions[\fit] = [nil,action]; 19 | this.prSendMsg(this.fitMsg(sourceDataSet, targetDataSet)); 20 | } 21 | 22 | predictMsg{ |sourceDataSet, targetDataSet| 23 | ^this.prMakeMsg(\predict,this.id,sourceDataSet.id,targetDataSet.id) 24 | } 25 | 26 | predict{ |sourceDataSet, targetDataSet, action| 27 | actions[\predict] = [nil, action]; 28 | this.prSendMsg(this.predictMsg(sourceDataSet, targetDataSet)); 29 | } 30 | 31 | predictPointMsg { |sourceBuffer, targetBuffer| 32 | ^this.prMakeMsg(\predictPoint,id, 33 | this.prEncodeBuffer(sourceBuffer), 34 | this.prEncodeBuffer(targetBuffer), 35 | ["/b_query", targetBuffer.asUGenInput]); 36 | } 37 | 38 | predictPoint { |sourceBuffer, targetBuffer, action| 39 | actions[\predictPoint] = [nil,{action.value(targetBuffer)}]; 40 | this.predictPointMsg(sourceBuffer, targetBuffer); 41 | this.prSendMsg(this.predictPointMsg(sourceBuffer, targetBuffer)); 42 | } 43 | 44 | kr{|trig, inputBuffer, outputBuffer, numNeighbours, weight| 45 | ^FluidKNNRegressorQuery.kr(K2A.ar(trig), 46 | this, numNeighbours??{this.numNeighbours}, weight??{this.weight}, 47 | this.prEncodeBuffer(inputBuffer), 48 | this.prEncodeBuffer(outputBuffer)); 49 | } 50 | } 51 | 52 | FluidKNNRegressorQuery : FluidRTMultiOutUGen { 53 | 54 | *kr{ |trig, model,numNeighbours = 3, weight = 1,inputBuffer, outputBuffer | 55 | ^this.multiNew('control',trig, model.asUGenInput, 56 | numNeighbours,weight, 57 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 58 | } 59 | 60 | init { arg ... theInputs; 61 | inputs = theInputs; 62 | ^this.initOutputs(1, rate); 63 | } 64 | } -------------------------------------------------------------------------------- /release-packaging/Classes/FluidLabelSet.sc: -------------------------------------------------------------------------------- 1 | FluidLabelSet : FluidDataObject { 2 | 3 | *new{|server| ^super.new(server) } 4 | 5 | addLabelMsg{|identifier,label| 6 | ^this.prMakeMsg(\addLabel,id,identifier.asSymbol,label.asSymbol); 7 | } 8 | 9 | addLabel{|identifier, label, action| 10 | actions[\addLabel] = [nil, action]; 11 | this.prSendMsg(this.addLabelMsg(identifier,label)); 12 | } 13 | 14 | updateLabelMsg{|identifier, label| 15 | ^this.prMakeMsg(\updateLabel, id, identifier.asSymbol, label.asSymbol); 16 | } 17 | 18 | setLabelMsg{|identifier,label| 19 | ^this.prMakeMsg(\setLabel,id,identifier.asSymbol,label.asSymbol); 20 | } 21 | 22 | setLabel{|identifier, label, action| 23 | actions[\setLabel] = [nil, action]; 24 | this.prSendMsg(this.setLabelMsg(identifier,label)); 25 | } 26 | 27 | updateLabel{|identifier, label, action| 28 | actions[\updateLabel] = [nil,action]; 29 | this.prSendMsg(this.updateLabelMsg(identifier,label)); 30 | } 31 | 32 | getLabelMsg{|identifier| 33 | ^this.prMakeMsg(\getLabel, id, identifier.asSymbol); 34 | } 35 | 36 | getLabel{|identifier, action| 37 | actions[\getLabel] = [string(FluidMessageResponse,_,_),action]; 38 | this.prSendMsg(this.getLabelMsg(identifier)); 39 | } 40 | 41 | deleteLabelMsg{|identifier, action| 42 | ^this.prMakeMsg(\deleteLabel, id, identifier.asSymbol); 43 | } 44 | 45 | deleteLabel{|identifier, action| 46 | actions[\deleteLabel] = [nil, action]; 47 | this.prSendMsg(this.deleteLabelMsg(identifier)); 48 | } 49 | 50 | clearMsg { ^this.prMakeMsg(\clear,id); } 51 | 52 | clear { |action| 53 | actions[\clear] = [nil,action]; 54 | this.prSendMsg(this.clearMsg); 55 | } 56 | 57 | mergeMsg{|sourceLabelSet, overwrite = 0| 58 | ^this.prMakeMsg(\merge,id,sourceLabelSet.asUGenInput,overwrite); 59 | } 60 | 61 | merge{|sourceLabelSet, overwrite = 0, action| 62 | actions[\merge] = [nil,action]; 63 | this.prSendMsg(this.mergeMsg(sourceLabelSet,overwrite)); 64 | } 65 | 66 | printMsg { ^this.prMakeMsg(\print,id); } 67 | 68 | print { |action=(postResponse)| 69 | actions[\print] = [string(FluidMessageResponse,_,_),action]; 70 | this.prSendMsg(this.printMsg); 71 | } 72 | 73 | getIdsMsg{|labelSet| 74 | ^this.prMakeMsg(\getIds, id, labelSet.asUGenInput); 75 | } 76 | 77 | getIds{|labelSet, action| 78 | actions[\getIds] = [nil,action]; 79 | this.prSendMsg(this.getIdsMsg(labelSet)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidLoudness.sc: -------------------------------------------------------------------------------- 1 | FluidLoudness : FluidRTMultiOutUGen { 2 | 3 | const (1< 1) { ("Option '" ++ item ++ "' is repeated").warn}; 16 | }; 17 | bits = a.collect{ |sym| 18 | (featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0}) 19 | }.reduce{|x,y| x | y}; 20 | ^bits 21 | } 22 | 23 | *kr { arg in = 0, select, kWeighting = 1, truePeak = 1, windowSize = 1024, hopSize = 512, maxWindowSize = 16384; 24 | 25 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 26 | 27 | ^this.multiNew('control', in.asAudioRateInput(this), selectbits, kWeighting, truePeak, windowSize, hopSize, maxWindowSize); 28 | } 29 | 30 | init {arg ...theInputs; 31 | var numChannels; 32 | inputs = theInputs; 33 | numChannels = inputs.at(1).asBinaryDigits.sum; 34 | ^this.initOutputs(numChannels,rate); 35 | } 36 | 37 | checkInputs { 38 | if(inputs.at(6).rate != 'scalar') { 39 | ^(": maxwindowSize cannot be modulated."); 40 | }; 41 | ^this.checkValidInputs; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidMDS.sc: -------------------------------------------------------------------------------- 1 | FluidMDS : FluidModelObject { 2 | classvar < manhattan = 0; 3 | classvar < euclidean = 1; 4 | classvar < sqeuclidean = 2; 5 | classvar < max = 3; 6 | classvar < min = 4; 7 | classvar < kl = 5; 8 | classvar < cosine = 5; 9 | 10 | var <>numDimensions, <>distanceMetric; 11 | 12 | *new {|server,numDimensions = 2, distanceMetric = 1| 13 | ^super.new(server,[numDimensions, distanceMetric]) 14 | .numDimensions_(numDimensions) 15 | .distanceMetric_(distanceMetric); 16 | } 17 | 18 | prGetParams{ 19 | ^[this.numDimensions, this.distanceMetric]; 20 | } 21 | 22 | fitTransformMsg{|sourceDataSet, destDataSet| 23 | ^this.prMakeMsg(\fitTransform,id, sourceDataSet.id, destDataSet.id); 24 | } 25 | 26 | fitTransform{|sourceDataSet, destDataSet, action| 27 | actions[\fitTransform] = [nil,action]; 28 | this.fitTransformMsg(sourceDataSet,destDataSet); 29 | 30 | this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); 31 | } 32 | 33 | // not implemented 34 | cols {|action|} 35 | read{|filename,action|} 36 | write{|filename,action|} 37 | size { |action|} 38 | 39 | } 40 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidMFCC.sc: -------------------------------------------------------------------------------- 1 | FluidMFCC : FluidRTMultiOutUGen { 2 | 3 | *kr { arg in = 0, numCoeffs = 13, numBands = 40, startCoeff = 0, minFreq = 20, maxFreq = 20000, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1, maxNumCoeffs = nil, maxNumBands = nil; 4 | 5 | maxNumCoeffs = maxNumCoeffs ? numCoeffs; 6 | maxNumBands = maxNumBands ? numBands; 7 | 8 | ^this.multiNew('control', in.asAudioRateInput(this), numCoeffs, maxNumCoeffs, numBands, maxNumBands, startCoeff, minFreq, maxFreq, windowSize, hopSize, fftSize, maxFFTSize); 9 | } 10 | 11 | 12 | init {arg ...theInputs; 13 | inputs = theInputs; 14 | ^this.initOutputs(inputs.at(2),rate);//this instantiate the number of output from the maxNumCoeffs in the multiNew order 15 | } 16 | 17 | checkInputs { 18 | // the checks of rates here are in the order of the kr method definition 19 | if(inputs.at(2).rate != 'scalar') { 20 | ^(": maxNumCoeffs cannot be modulated."); 21 | }; 22 | if(inputs.at(4).rate != 'scalar') { 23 | ^(": maxNumBands cannot be modulated."); 24 | }; 25 | if(inputs.at(10).rate != 'scalar') { 26 | ^(": maxFFTSize cannot be modulated."); 27 | }; 28 | ^this.checkValidInputs; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidManipulationJSON.sc: -------------------------------------------------------------------------------- 1 | + FluidDataObject { 2 | tmpJSONFilename{ 3 | ^Platform.defaultTempDir++"tmp_fluid_data_"++ 4 | Date.localtime.stamp++"_"++UniqueID.next++".json"; 5 | } 6 | 7 | dump {|action| 8 | var filename = this.tmpJSONFilename; 9 | action ?? {action = postResponse}; 10 | this.write(filename, { 11 | action.value(this.parseJSON(File.readAllString(filename))); 12 | File.delete(filename); 13 | }); 14 | } 15 | 16 | load{|dict, action| 17 | var filename = this.tmpJSONFilename; 18 | File.use(filename, "wt", { |f| f.write(this.asJSON(dict));}); 19 | this.read(filename, { 20 | action.notNil.if{ action.value; }; 21 | File.delete(filename); 22 | }); 23 | } 24 | 25 | toDict{|obj| 26 | var converted; 27 | if(obj.class === Event){ 28 | converted = obj.as(Dictionary); 29 | converted.keysValuesChange{|k,v|this.toDict(v)} 30 | ^converted; 31 | }; 32 | if(obj.class === Array){ 33 | converted = obj.collect{|v| this.toDict(v)}; 34 | ^converted; 35 | }; 36 | ^obj; 37 | } 38 | 39 | parseJSON{|jsonStr| 40 | var parsed = jsonStr; 41 | jsonStr.do({|char,pos| 42 | var inString = false; 43 | char.switch( 44 | $",{(jsonStr[pos-1]==$\ && inString).not.if({inString = inString.not})}, 45 | ${,{ if(inString.not){parsed[pos] = $(} }, 46 | $},{ if(inString.not){parsed[pos] = $)} } 47 | ) 48 | }); 49 | ^this.toDict(parsed.interpret); 50 | } 51 | 52 | asJSON{|d| 53 | if(d.isNumber){^d}; 54 | if(d.isString){^d.asString.asCompileString}; 55 | if(d.isKindOf(Symbol)){^this.asJSON(d.asString)}; 56 | if(d.isKindOf(Dictionary)) 57 | { 58 | ^"{" ++ ( 59 | d.keys.asList.collect{|k| 60 | k.asString.asCompileString ++ ":" + this.asJSON(d[k]) 61 | }).join(", ") ++ "}" 62 | }; 63 | if(d.isKindOf(SequenceableCollection)) 64 | { 65 | ^"[" ++ d.collect({|x|this.asJSON(x)}).join(", ")++ "]"; 66 | }; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidMelBands.sc: -------------------------------------------------------------------------------- 1 | FluidMelBands : FluidRTMultiOutUGen { 2 | 3 | *kr { arg in = 0, numBands = 40, minFreq = 20, maxFreq = 20000, normalize = 1, scale = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1, maxNumBands; 4 | 5 | maxNumBands = maxNumBands ? numBands; 6 | 7 | ^this.multiNew('control', in.asAudioRateInput(this), numBands, maxNumBands, minFreq, maxFreq, normalize, scale, windowSize, hopSize, fftSize, maxFFTSize); 8 | } 9 | 10 | init {arg ...theInputs; 11 | inputs = theInputs; 12 | ^this.initOutputs(inputs.at(2),rate); //this instantiate the number of output from the maxNumCoeffs in the multiNew order 13 | } 14 | 15 | checkInputs { 16 | // the checks of rates here are in the order of the kr method definition 17 | if(inputs.at(2).rate != 'scalar') { 18 | ^(": maxNumBands cannot be modulated."); 19 | }; 20 | if(inputs.at(10).rate != 'scalar') { 21 | ^(": maxFFTSize cannot be modulated."); 22 | };^this.checkValidInputs; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidMessageResponse.sc: -------------------------------------------------------------------------------- 1 | FluidMessageResponse : Object 2 | { 3 | //selectors is an array of functions 4 | //my cunning thought is that those that need extra data (e..g numbers()) can 5 | //use partial applicaiton 6 | *collectArgs{ |selectors,a| 7 | var response = []; 8 | var idx = 0; 9 | selectors.do{ |selector| 10 | var newThings; 11 | # newThings,idx = selector.value(a, idx); 12 | response = response ++ newThings; 13 | }; 14 | 15 | if(response.size == 1, 16 | {^response[0]},{^response}) 17 | } 18 | 19 | *string{ |a, offset| 20 | ^[a] 21 | } 22 | 23 | *strings {|a,offset| 24 | //TODO add an n argument as with numbers() to make this less omnivorous 25 | ^[a.drop(offset)]; 26 | } 27 | 28 | *numbers{ |a, n, offset| 29 | n = n ? a.size - offset; //send n = nil to consume everything 30 | ^[a.copyRange(offset, offset + n),offset + n] 31 | } 32 | 33 | *number{ |a,offset| 34 | ^[a[offset]]; 35 | } 36 | 37 | *buffer{ |a,server,offset| 38 | server = server ? Server.default ; 39 | ^[Buffer.cachedBufferAt(server, a[offset]), offset + 1] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidNMFFilter.sc: -------------------------------------------------------------------------------- 1 | FluidNMFFilter : FluidRTMultiOutUGen { 2 | 3 | *ar { arg in = 0, bases, maxComponents = 1, iterations = 10, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 4 | ^this.multiNew('audio', in.asAudioRateInput(this), bases, maxComponents, maxComponents, iterations, windowSize, hopSize, fftSize, maxFFTSize); 5 | } 6 | 7 | init {arg ...theInputs; 8 | inputs = theInputs; 9 | ^this.initOutputs(inputs[2],rate); 10 | } 11 | 12 | checkInputs { 13 | if(inputs.at(3).rate != 'scalar') { 14 | ^(": maxComponents cannot be modulated."); 15 | }; 16 | if(inputs.at(8).rate != 'scalar') { 17 | ^(": maxFFTSize cannot be modulated."); 18 | }; 19 | ^this.checkValidInputs; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidNMFMatch.sc: -------------------------------------------------------------------------------- 1 | FluidNMFMatch : FluidRTMultiOutUGen { 2 | 3 | *kr { arg in = 0, bases, maxComponents = 1, iterations = 10, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 4 | ^this.multiNew('control', in.asAudioRateInput(this), bases, maxComponents, maxComponents, iterations, windowSize, hopSize, fftSize, maxFFTSize); 5 | } 6 | 7 | init {arg ...theInputs; 8 | inputs = theInputs; 9 | ^this.initOutputs(inputs[2],rate); 10 | } 11 | 12 | checkInputs { 13 | if(inputs.at(3).rate != 'scalar') { 14 | ^(": maxComponents cannot be modulated."); 15 | }; 16 | if(inputs.at(8).rate != 'scalar') { 17 | ^(": maxFFTSize cannot be modulated."); 18 | }; 19 | ^this.checkValidInputs; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidNMFMorph.sc: -------------------------------------------------------------------------------- 1 | FluidNMFMorph : FluidRTUGen { 2 | 3 | *ar { arg source = -1, target = -1, activations = -1, autoassign = 1, interpolation = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 4 | 5 | source = source ?? {-1}; 6 | target = target ?? {-1}; 7 | activations = activations ?? {-1}; 8 | 9 | ^this.new1('audio', source, target, activations, autoassign, interpolation, windowSize, hopSize, fftSize, maxFFTSize); 10 | } 11 | 12 | init {arg ...theInputs; 13 | inputs = theInputs; 14 | specialIndex = -1; 15 | } 16 | 17 | checkInputs { 18 | if(inputs.last.rate != 'scalar') { 19 | ^(": maxFFTSize cannot be modulated."); 20 | }; 21 | ^this.checkValidInputs; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidNRTProcess.sc: -------------------------------------------------------------------------------- 1 | FluidNRTProcess : Object{ 2 | var min, <>max; 4 | 5 | *new {|server, min = 0, max = 1| 6 | ^super.new(server,[min,max]) 7 | .min_(min).max_(max); 8 | } 9 | 10 | prGetParams{ 11 | ^[this.id, this.min,this.max,-1,-1]; 12 | } 13 | 14 | 15 | fitMsg{|dataSet| 16 | ^this.prMakeMsg(\fit,id,dataSet.id) 17 | } 18 | 19 | fit{|dataSet, action| 20 | actions[\fit] = [nil,action]; 21 | this.prSendMsg(this.fitMsg(dataSet)); 22 | } 23 | 24 | transformMsg{|sourceDataSet, destDataSet| 25 | ^this.prMakeMsg(\transform,id,sourceDataSet.id,destDataSet.id); 26 | } 27 | 28 | transform{|sourceDataSet, destDataSet, action| 29 | actions[\transform] = [nil,action]; 30 | this.prSendMsg(this.transformMsg(sourceDataSet, destDataSet)); 31 | } 32 | 33 | fitTransformMsg{|sourceDataSet, destDataSet| 34 | ^this.prMakeMsg(\fitTransform,id,sourceDataSet.id,destDataSet.id) 35 | } 36 | 37 | fitTransform{|sourceDataSet, destDataSet, action| 38 | actions[\fitTransform] = [nil,action]; 39 | this.prSendMsg(this.fitTransformMsg(sourceDataSet, destDataSet)); 40 | } 41 | 42 | transformPointMsg{|sourceBuffer, destBuffer| 43 | ^this.prMakeMsg(\transformPoint,id, 44 | this.prEncodeBuffer(sourceBuffer), 45 | this.prEncodeBuffer(destBuffer), 46 | ["/b_query",destBuffer.asUGenInput] 47 | ); 48 | } 49 | 50 | transformPoint{|sourceBuffer, destBuffer, action| 51 | actions[\transformPoint] = [nil,{action.value(destBuffer)}]; 52 | this.prSendMsg(this.transformPointMsg(sourceBuffer, destBuffer)); 53 | } 54 | 55 | inverseTransformMsg{|sourceDataSet, destDataSet| 56 | ^this.prMakeMsg(\inverseTransform,id,sourceDataSet.id,destDataSet.id); 57 | } 58 | 59 | inverseTransform{|sourceDataSet, destDataSet, action| 60 | actions[\inverseTransform] = [nil,action]; 61 | this.prSendMsg(this.inverseTransformMsg(sourceDataSet, destDataSet)); 62 | } 63 | 64 | inverseTransformPointMsg{|sourceBuffer, destBuffer| 65 | ^this.prMakeMsg(\inverseTransformPoint,id, 66 | this.prEncodeBuffer(sourceBuffer), 67 | this.prEncodeBuffer(destBuffer), 68 | ["/b_query",destBuffer.asUGenInput] 69 | ); 70 | } 71 | 72 | inverseTransformPoint{|sourceBuffer, destBuffer, action| 73 | actions[\inverseTransformPoint] = [nil,{action.value(destBuffer)}]; 74 | this.prSendMsg(this.inverseTransformPointMsg(sourceBuffer, destBuffer)); 75 | } 76 | 77 | kr{|trig, inputBuffer,outputBuffer,min = 0 ,max = 1,invert = 0| 78 | 79 | min = min ? this.min; 80 | max = max ? this.max; 81 | 82 | this.min_(min).max_(max); 83 | 84 | ^FluidNormalizeQuery.kr(trig, 85 | this, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer), this.min, this.max, invert); 86 | } 87 | 88 | 89 | } 90 | 91 | FluidNormalizeQuery : FluidRTMultiOutUGen { 92 | 93 | *kr{ |trig, model,inputBuffer,outputBuffer,min = 0 ,max = 1,invert = 0| 94 | // inputBuffer.asUGenInput.postln; 95 | ^this.multiNew('control',trig, model.asUGenInput, 96 | min,max,invert, 97 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 98 | } 99 | 100 | init { arg ... theInputs; 101 | inputs = theInputs; 102 | ^this.initOutputs(1, rate); 103 | } 104 | } -------------------------------------------------------------------------------- /release-packaging/Classes/FluidNoveltyFeature.sc: -------------------------------------------------------------------------------- 1 | FluidNoveltyFeature : FluidRTUGen { 2 | *kr { arg in = 0, algorithm = 0, kernelSize = 3, filterSize = 1, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1, maxKernelSize, maxFilterSize; 3 | 4 | maxKernelSize = maxKernelSize ? kernelSize; 5 | maxFilterSize = maxFilterSize ? filterSize; 6 | algorithm = FluidNoveltySlice.prSelectAlgorithm(algorithm) ?? { 7 | ("FluidNoveltySlice: % is not a recognised algorithm").format(algorithm); 8 | }; 9 | 10 | ^this.multiNew('control', in.asAudioRateInput(this), algorithm, kernelSize, maxKernelSize, filterSize, maxFilterSize, windowSize, hopSize, fftSize, maxFFTSize) 11 | } 12 | 13 | checkInputs { 14 | if([\scalar, \control].includes(inputs.at(1).rate).not) { 15 | ^(": invalid algorithm"); 16 | }; 17 | if(inputs.at(9).rate != 'scalar') { 18 | ^(": maxFFTSize cannot be modulated."); 19 | }; 20 | if(inputs.at(3).rate != 'scalar') { 21 | ^(": maxKernelSize cannot be modulated."); 22 | }; 23 | if(inputs.at(5).rate != 'scalar') { 24 | ^(": maxFilterSize cannot be modulated."); 25 | }; 26 | ^this.checkValidInputs; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidNoveltySlice.sc: -------------------------------------------------------------------------------- 1 | FluidNoveltySlice : FluidRTUGen { 2 | 3 | const = 0 && (sym < algorithms.size)) { 9 | ^sym 10 | } { 11 | ^nil 12 | } 13 | }; 14 | ^algorithms.indexOf(sym.asSymbol) 15 | } 16 | 17 | *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; 18 | 19 | maxKernelSize = maxKernelSize ? kernelSize; 20 | maxFilterSize = maxFilterSize ? filterSize; 21 | 22 | algorithm = this.prSelectAlgorithm(algorithm) ?? { 23 | ("FluidNoveltySlice: % is not a recognised algorithm").format(algorithm); 24 | }; 25 | 26 | ^this.multiNew('audio', in.asAudioRateInput(this), algorithm, kernelSize, maxKernelSize, threshold, filterSize, maxFilterSize, minSliceLength, windowSize, hopSize, fftSize, maxFFTSize) 27 | } 28 | 29 | checkInputs { 30 | if([\scalar, \control].includes(inputs.at(1).rate).not) { 31 | ^(": invalid algorithm"); 32 | }; 33 | if(inputs.at(11).rate != 'scalar') { 34 | ^(": maxFFTSize cannot be modulated."); 35 | }; 36 | if(inputs.at(3).rate != 'scalar') { 37 | ^(": maxKernelSize cannot be modulated."); 38 | }; 39 | if(inputs.at(6).rate != 'scalar') { 40 | ^(": maxFilterSize cannot be modulated."); 41 | }; 42 | ^this.checkValidInputs; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidOnsetFeature.sc: -------------------------------------------------------------------------------- 1 | FluidOnsetFeature : FluidRTUGen { 2 | *kr { arg in = 0, metric = 0, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 3 | 4 | metric = FluidOnsetSlice.prSelectMetric(metric) ?? { 5 | ("% is not a recognised metric").format(metric); 6 | }; 7 | 8 | ^this.multiNew('control', in.asAudioRateInput(this), metric, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize) 9 | } 10 | checkInputs { 11 | if([\scalar, \control].includes(inputs.at(1).rate).not) { 12 | ^(": invalid metric"); 13 | }; 14 | if(inputs.at(7).rate != 'scalar') { 15 | ^(": maxFFTSize cannot be modulated."); 16 | }; 17 | ^this.checkValidInputs; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidOnsetSlice.sc: -------------------------------------------------------------------------------- 1 | FluidOnsetSlice : FluidRTUGen { 2 | 3 | const = 0 && (sym < metrics.size)) { 20 | ^sym 21 | } { 22 | ^nil 23 | } 24 | }; 25 | ^metrics.indexOf(sym.asSymbol) 26 | } 27 | 28 | *ar { arg in = 0, metric = 0, threshold = 0.5, minSliceLength = 2, filterSize = 5, frameDelta = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 29 | 30 | metric = this.prSelectMetric(metric) ?? { 31 | ("% is not a recognised metric").format(metric); 32 | }; 33 | 34 | ^this.multiNew('audio', in.asAudioRateInput(this), metric, threshold, minSliceLength, filterSize, frameDelta, windowSize, hopSize, fftSize, maxFFTSize) 35 | } 36 | checkInputs { 37 | if([\scalar, \control].includes(inputs.at(1).rate).not) { 38 | ^(": invalid metric"); 39 | }; 40 | if(inputs.at(9).rate != 'scalar') { 41 | ^(": maxFFTSize cannot be modulated."); 42 | }; 43 | ^this.checkValidInputs; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidPCA.sc: -------------------------------------------------------------------------------- 1 | FluidPCA : FluidModelObject{ 2 | 3 | var <>numDimensions, <>whiten; 4 | 5 | *new {|server, numDimensions = 2, whiten = 0| 6 | ^super.new(server,[numDimensions, whiten]).numDimensions_(numDimensions).whiten_(whiten); 7 | } 8 | 9 | prGetParams{ 10 | ^[this.id, numDimensions, whiten]; 11 | } 12 | 13 | fitMsg{|dataSet| 14 | ^this.prMakeMsg(\fit,id, dataSet.id); 15 | } 16 | 17 | fit{|dataSet, action| 18 | actions[\fit] = [nil, action]; 19 | this.prSendMsg(this.fitMsg(dataSet)); 20 | } 21 | 22 | transformMsg{|sourceDataSet, destDataSet| 23 | ^this.prMakeMsg(\transform, id, sourceDataSet.id, destDataSet.id); 24 | } 25 | 26 | transform{|sourceDataSet, destDataSet, action| 27 | actions[\transform] = [numbers(FluidMessageResponse,_,1,_),action]; 28 | this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); 29 | } 30 | 31 | fitTransformMsg{|sourceDataSet, destDataSet| 32 | ^this.prMakeMsg(\fitTransform,id, sourceDataSet.id, destDataSet.id); 33 | } 34 | 35 | fitTransform{|sourceDataSet, destDataSet, action| 36 | actions[\fitTransform] = [numbers(FluidMessageResponse,_,1,_),action]; 37 | this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); 38 | } 39 | 40 | transformPointMsg{|sourceBuffer, destBuffer| 41 | ^this.prMakeMsg(\transformPoint,id, 42 | this.prEncodeBuffer(sourceBuffer), 43 | this.prEncodeBuffer(destBuffer), 44 | ["/b_query",destBuffer.asUGenInput] 45 | ); 46 | } 47 | 48 | transformPoint{|sourceBuffer, destBuffer, action| 49 | actions[\transformPoint] = [nil,{action.value(destBuffer)}]; 50 | this.prSendMsg(this.transformPointMsg(sourceBuffer,destBuffer)); 51 | } 52 | 53 | kr{|trig, inputBuffer,outputBuffer,numDimensions| 54 | 55 | numDimensions = numDimensions ? this.numDimensions; 56 | this.numDimensions_(numDimensions); 57 | 58 | ^FluidPCAQuery.kr(trig ,this, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer), this.numDimensions, this.whiten); 59 | } 60 | 61 | inverseTransformPointMsg{|sourceBuffer, destBuffer| 62 | ^this.prMakeMsg(\inverseTransformPoint,id, 63 | this.prEncodeBuffer(sourceBuffer), 64 | this.prEncodeBuffer(destBuffer), 65 | ["/b_query",destBuffer.asUGenInput] 66 | ); 67 | } 68 | 69 | inverseTransformPoint{|sourceBuffer, destBuffer, action| 70 | actions[\inverseTransformPoint] = [nil,{action.value(destBuffer)}]; 71 | this.prSendMsg(this.inverseTransformPointMsg(sourceBuffer,destBuffer)); 72 | } 73 | 74 | inverseTransformMsg{|sourceDataSet, destDataSet| 75 | ^this.prMakeMsg(\inverseTransform,id,sourceDataSet.id, destDataSet.id); 76 | } 77 | 78 | inverseTransform{|sourceDataSet, destDataSet,action| 79 | actions[\inverseTransform] = [nil,action]; 80 | this.prSendMsg(this.inverseTransformMsg(sourceDataSet, destDataSet)); 81 | } 82 | 83 | 84 | } 85 | 86 | FluidPCAQuery : FluidRTMultiOutUGen { 87 | *kr{ |trig, model, inputBuffer,outputBuffer,numDimensions, whiten| 88 | ^this.multiNew('control',trig, model.asUGenInput, 89 | numDimensions, whiten, 90 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 91 | } 92 | 93 | init { arg ... theInputs; 94 | inputs = theInputs; 95 | ^this.initOutputs(1, rate); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidPitch.sc: -------------------------------------------------------------------------------- 1 | FluidPitch : FluidRTMultiOutUGen { 2 | 3 | const (1< 1) { ("Option '" ++ item ++ "' is repeated").warn}; 16 | }; 17 | bits = a.collect{ |sym| 18 | (featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0}) 19 | }.reduce{|x,y| x | y}; 20 | ^bits 21 | } 22 | 23 | 24 | *kr { arg in = 0, select, algorithm = 2, minFreq = 20, maxFreq = 10000, unit = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 25 | 26 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 27 | 28 | ^this.multiNew('control', in.asAudioRateInput(this), selectbits, algorithm, minFreq, maxFreq, unit, windowSize, hopSize, fftSize, maxFFTSize); 29 | } 30 | 31 | init {arg ...theInputs; 32 | var numChannels; 33 | inputs = theInputs; 34 | numChannels = inputs.at(1).asBinaryDigits.sum; 35 | ^this.initOutputs(numChannels,rate); 36 | } 37 | 38 | checkInputs { 39 | if(inputs.at(9).rate != 'scalar') { 40 | ^(": maxFFTSize cannot be modulated."); 41 | }; 42 | ^this.checkValidInputs; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidRobustScale.sc: -------------------------------------------------------------------------------- 1 | FluidRobustScale : FluidModelObject { 2 | 3 | var <>low, <>high; 4 | 5 | *new {|server, low = 25, high = 75| 6 | ^super.new(server,[low,high]) 7 | .low_(low).high_(high); 8 | } 9 | 10 | prGetParams{ 11 | ^[this.id,this.low,this.high]; 12 | } 13 | 14 | 15 | fitMsg{|dataSet| 16 | ^this.prMakeMsg(\fit,id,dataSet.id) 17 | } 18 | 19 | fit{|dataSet, action| 20 | actions[\fit] = [nil,action]; 21 | this.prSendMsg(this.fitMsg(dataSet)); 22 | } 23 | 24 | transformMsg{|sourceDataSet, destDataSet| 25 | ^this.prMakeMsg(\transform,id,sourceDataSet.id,destDataSet.id); 26 | } 27 | 28 | transform{|sourceDataSet, destDataSet, action| 29 | actions[\transform] = [nil,action]; 30 | this.prSendMsg(this.transformMsg(sourceDataSet, destDataSet)); 31 | } 32 | 33 | fitTransformMsg{|sourceDataSet, destDataSet| 34 | ^this.prMakeMsg(\fitTransform,id,sourceDataSet.id,destDataSet.id) 35 | } 36 | 37 | fitTransform{|sourceDataSet, destDataSet, action| 38 | actions[\fitTransform] = [nil,action]; 39 | this.prSendMsg(this.fitTransformMsg(sourceDataSet, destDataSet)); 40 | } 41 | 42 | transformPointMsg{|sourceBuffer, destBuffer| 43 | ^this.prMakeMsg(\transformPoint,id, 44 | this.prEncodeBuffer(sourceBuffer), 45 | this.prEncodeBuffer(destBuffer), 46 | ["/b_query",destBuffer.asUGenInput] 47 | ); 48 | } 49 | 50 | transformPoint{|sourceBuffer, destBuffer, action| 51 | actions[\transformPoint] = [nil,{action.value(destBuffer)}]; 52 | this.prSendMsg(this.transformPointMsg(sourceBuffer, destBuffer)); 53 | } 54 | 55 | inverseTransformMsg{|sourceDataSet, destDataSet| 56 | ^this.prMakeMsg(\inverseTransform,id,sourceDataSet.id,destDataSet.id); 57 | } 58 | 59 | inverseTransform{|sourceDataSet, destDataSet, action| 60 | actions[\inverseTransform] = [nil,action]; 61 | this.prSendMsg(this.inverseTransformMsg(sourceDataSet, destDataSet)); 62 | } 63 | 64 | inverseTransformPointMsg{|sourceBuffer, destBuffer| 65 | ^this.prMakeMsg(\inverseTransformPoint,id, 66 | this.prEncodeBuffer(sourceBuffer), 67 | this.prEncodeBuffer(destBuffer), 68 | ["/b_query",destBuffer.asUGenInput] 69 | ); 70 | } 71 | 72 | inverseTransformPoint{|sourceBuffer, destBuffer, action| 73 | actions[\inverseRransformPoint] = [nil,{action.value(destBuffer)}]; 74 | this.prSendMsg(this.inverseTransformPointMsg(sourceBuffer, destBuffer)); 75 | } 76 | 77 | kr{|trig, inputBuffer,outputBuffer,invert = 0| 78 | 79 | ^FluidRobustScaleQuery.kr(trig,this, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer), invert); 80 | } 81 | 82 | 83 | } 84 | 85 | FluidRobustScaleQuery : FluidRTMultiOutUGen { 86 | *kr{ |trig, model, inputBuffer,outputBuffer,invert| 87 | ^this.multiNew('control',trig, model.asUGenInput, 88 | invert, 89 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 90 | } 91 | 92 | init { arg ... theInputs; 93 | inputs = theInputs; 94 | ^this.initOutputs(1, rate); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidSTFTPass.sc: -------------------------------------------------------------------------------- 1 | FluidSTFTPass : FluidRTUGen { 2 | *ar { arg in = 0, windowSize= 1024, hopSize= -1, fftSize= -1, maxFFTSize; 3 | ^this.multiNew('audio', in.asAudioRateInput(this), windowSize, hopSize = -1, fftSize = -1, maxFFTSize = -1) 4 | } 5 | checkInputs { 6 | if(inputs.at(4).rate != 'scalar') { 7 | ^": maxFFTSize cannot be modulated."; 8 | }; 9 | ^this.checkValidInputs 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidServerCache.sc: -------------------------------------------------------------------------------- 1 | FluidProxyUgen : UGen { 2 | 3 | var <>pluginname; 4 | 5 | *kr { |pluginname...args| 6 | args = args.collect{|x| x.asUGenInput} 7 | ^this.new1('control', pluginname,*args) 8 | } 9 | 10 | init { |pluginname...args| 11 | this.pluginname = pluginname; 12 | inputs = args; 13 | rate = 'control'; 14 | } 15 | 16 | name{ 17 | ^pluginname.asString; 18 | } 19 | 20 | poll{ |trig = 10, label, trigid = -1| 21 | ^super.poll(trig, label ? this.name, trigid) 22 | } 23 | } 24 | 25 | FluidServerCache { 26 | 27 | var (1< 1) { ("Option '" ++ item ++ "' is repeated").warn}; 16 | }; 17 | bits = a.collect{ |sym| 18 | (featuresLookup[sym.asSymbol] !? {|x| x} ?? {this.prWarnUnrecognised(sym); 0}) 19 | }.reduce{|x,y| x | y}; 20 | ^bits 21 | } 22 | 23 | 24 | *kr { arg in = 0, select, minFreq = 0, maxFreq = -1, rolloffPercent = 95, unit = 0, power = 0, windowSize = 1024, hopSize = -1, fftSize = -1, maxFFTSize = -1; 25 | 26 | var selectbits = select !? {this.prProcessSelect(select)} ?? {this.prProcessSelect(this.features)}; 27 | 28 | ^this.multiNew('control', in.asAudioRateInput(this), selectbits, minFreq, maxFreq, rolloffPercent, unit, power, windowSize, hopSize, fftSize, maxFFTSize); 29 | } 30 | 31 | init {arg ...theInputs; 32 | var numChannels; 33 | inputs = theInputs; 34 | numChannels = inputs.at(1).asBinaryDigits.sum; 35 | ^this.initOutputs(numChannels,rate); 36 | } 37 | 38 | checkInputs { 39 | if(inputs.at(10).rate != 'scalar') { 40 | ^(": maxFFTSize cannot be modulated."); 41 | }; 42 | ^this.checkValidInputs; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidStandardize.sc: -------------------------------------------------------------------------------- 1 | FluidStandardize : FluidModelObject { 2 | 3 | *new {|server| 4 | ^super.new(server,[]); 5 | } 6 | 7 | prGetParams{ 8 | ^[this.id]; 9 | } 10 | 11 | fitMsg{|dataSet| 12 | ^this.prMakeMsg(\fit,id,dataSet.id); 13 | } 14 | 15 | fit{|dataSet, action| 16 | actions[\fit] = [nil, action]; 17 | this.prSendMsg(this.fitMsg(dataSet)); 18 | } 19 | 20 | transformMsg{|sourceDataSet, destDataSet| 21 | ^this.prMakeMsg(\transform,id,sourceDataSet.id,destDataSet.id); 22 | } 23 | 24 | transform{|sourceDataSet, destDataSet, action| 25 | actions[\transform] = [nil,action]; 26 | this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); 27 | } 28 | 29 | fitTransformMsg{|sourceDataSet, destDataSet| 30 | ^this.prMakeMsg(\fitTransform,id,sourceDataSet.id,destDataSet.id) 31 | } 32 | 33 | fitTransform{|sourceDataSet, destDataSet, action| 34 | actions[\fitTransform] = [nil,action]; 35 | this.prSendMsg(this.fitTransformMsg(sourceDataSet, destDataSet)); 36 | } 37 | 38 | 39 | transformPointMsg{|sourceBuffer, destBuffer| 40 | ^this.prMakeMsg(\transformPoint, id, this.prEncodeBuffer(sourceBuffer), this.prEncodeBuffer(destBuffer),["/b_query",destBuffer.asUGenInput]); 41 | } 42 | 43 | transformPoint{|sourceBuffer, destBuffer, action| 44 | actions[\transformPoint] = [nil, {action.value(destBuffer)}]; 45 | this.prSendMsg(this.transformPointMsg(sourceBuffer,destBuffer)); 46 | } 47 | 48 | inverseTransformMsg{|sourceDataSet, destDataSet| 49 | ^this.prMakeMsg(\inverseTransform,id,sourceDataSet.id,destDataSet.id); 50 | } 51 | 52 | inverseTransform{|sourceDataSet, destDataSet, action| 53 | actions[\inverseTransform] = [nil,action]; 54 | this.prSendMsg(this.inverseTransformMsg(sourceDataSet, destDataSet)); 55 | } 56 | 57 | inverseTransformPointMsg{|sourceBuffer, destBuffer| 58 | ^this.prMakeMsg(\inverseTransformPoint,id, 59 | this.prEncodeBuffer(sourceBuffer), 60 | this.prEncodeBuffer(destBuffer), 61 | ["/b_query",destBuffer.asUGenInput] 62 | ); 63 | } 64 | 65 | inverseTransformPoint{|sourceBuffer, destBuffer, action| 66 | actions[\inverseRransformPoint] = [nil,{action.value(destBuffer)}]; 67 | this.prSendMsg(this.inverseTransformPointMsg(sourceBuffer, destBuffer)); 68 | } 69 | 70 | kr{|trig, inputBuffer,outputBuffer,invert = 0| 71 | 72 | ^FluidStandardizeQuery.kr(trig,this, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer), invert); 73 | } 74 | } 75 | 76 | FluidStandardizeQuery : FluidRTMultiOutUGen { 77 | *kr{ |trig, model,inputBuffer,outputBuffer,invert = 0| 78 | ^this.multiNew('control',trig, model.asUGenInput, 79 | invert, 80 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 81 | } 82 | 83 | init { arg ... theInputs; 84 | inputs = theInputs; 85 | ^this.initOutputs(1, rate); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidStats.sc: -------------------------------------------------------------------------------- 1 | FluidStats : MultiOutUGen { 2 | 3 | *kr { arg in, history; 4 | ^this.multiNew('control',*(in.asArray++history)).reshape(2,in.asArray.size); 5 | } 6 | 7 | init {arg ...theInputs; 8 | inputs = theInputs; 9 | this.specialIndex = (inputs.size - 2).max(0); 10 | ^this.initOutputs(inputs.size - 1,rate) 11 | } 12 | 13 | checkInputs { 14 | ^this.checkValidInputs; 15 | } 16 | 17 | initOutputs{|numChans,rate| 18 | if(numChans.isNil or: {numChans < 1}) 19 | { 20 | Error("No input channels").throw 21 | }; 22 | 23 | channels = Array.fill(numChans * 2, { |i| 24 | OutputProxy('control',this,i); 25 | }); 26 | ^channels 27 | } 28 | 29 | numOutputs { ^(channels.size); } 30 | } 31 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidTransientSlice.sc: -------------------------------------------------------------------------------- 1 | FluidTransientSlice : FluidRTUGen { 2 | *ar { arg in = 0, order = 20, blockSize = 256, padSize = 128, skew = 0.0, threshFwd = 2.0, threshBack = 1.1, windowSize=14, clumpLength=25, minSliceLength = 1000; 3 | ^this.multiNew('audio', in.asAudioRateInput(this), order, blockSize, padSize, skew, threshFwd ,threshBack, windowSize, clumpLength, minSliceLength) 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidTransients.sc: -------------------------------------------------------------------------------- 1 | FluidTransients : FluidRTMultiOutUGen { 2 | *ar { arg in = 0, order = 20, blockSize = 256, padSize = 128, skew = 0.0, threshFwd = 2.0, threshBack = 1.1, windowSize=14, clumpLength=25; 3 | ^this.multiNew('audio', in.asAudioRateInput(this), order, blockSize, padSize, skew, threshFwd, threshBack, windowSize, clumpLength) 4 | } 5 | init { arg ... theInputs; 6 | inputs = theInputs; 7 | channels = [ 8 | OutputProxy(rate, this, 0), 9 | OutputProxy(rate, this, 1) 10 | ]; 11 | ^channels 12 | } 13 | checkInputs { ^this.checkNInputs(1) } 14 | } 15 | -------------------------------------------------------------------------------- /release-packaging/Classes/FluidUMAP.sc: -------------------------------------------------------------------------------- 1 | FluidUMAP : FluidModelObject { 2 | 3 | var <>numDimensions, <>numNeighbours, <>minDist, <>iterations, <>learnRate; 4 | 5 | *new {|server,numDimensions = 2, numNeighbours = 15, minDist = 0.1, iterations = 200, learnRate = 0.1| 6 | ^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate]) 7 | .numDimensions_(numDimensions) 8 | .numNeighbours_(numNeighbours) 9 | .minDist_(minDist) 10 | .iterations_(iterations) 11 | .learnRate_(learnRate); 12 | } 13 | 14 | prGetParams{ 15 | ^[ 16 | this.id, 17 | this.numDimensions, 18 | this.numNeighbours, 19 | this.minDist, 20 | this.iterations, 21 | this.learnRate, 22 | ] 23 | } 24 | 25 | fitTransformMsg{|sourceDataSet, destDataSet| 26 | ^this.prMakeMsg(\fitTransform, id, sourceDataSet.id, destDataSet.id) 27 | } 28 | 29 | fitTransform{|sourceDataSet, destDataSet, action| 30 | actions[\fitTransform] = [nil, action]; 31 | this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); 32 | } 33 | 34 | fitMsg{|dataSet| 35 | ^this.prMakeMsg(\fit,id, dataSet.id); 36 | } 37 | 38 | fit{|dataSet, action| 39 | actions[\fit] = [nil, action]; 40 | this.prSendMsg(this.fitMsg(dataSet)); 41 | } 42 | 43 | transformMsg{|sourceDataSet, destDataSet| 44 | ^this.prMakeMsg(\transform, id, sourceDataSet.id, destDataSet.id); 45 | } 46 | 47 | transform{|sourceDataSet, destDataSet, action| 48 | actions[\transform] = [nil, action]; 49 | this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); 50 | } 51 | 52 | 53 | transformPointMsg{|sourceBuffer, destBuffer| 54 | ^this.prMakeMsg(\transformPoint,id, 55 | this.prEncodeBuffer(sourceBuffer), 56 | this.prEncodeBuffer(destBuffer), 57 | ["/b_query",destBuffer.asUGenInput] 58 | ); 59 | } 60 | 61 | transformPoint{|sourceBuffer, destBuffer, action| 62 | actions[\transformPoint] = [nil,{action.value(destBuffer)}]; 63 | this.prSendMsg(this.transformPointMsg(sourceBuffer,destBuffer)); 64 | } 65 | 66 | kr{|trig, inputBuffer,outputBuffer| 67 | 68 | ^FluidUMAPQuery.kr(trig, 69 | this, 70 | this.prEncodeBuffer(inputBuffer), 71 | this.prEncodeBuffer(outputBuffer)); 72 | } 73 | 74 | // not implemented 75 | cols {|action|} 76 | size { |action|} 77 | } 78 | 79 | FluidUMAPQuery : FluidRTMultiOutUGen { 80 | *kr{ |trig, model, inputBuffer,outputBuffer| 81 | ^this.multiNew('control',trig, model.asUGenInput, 82 | inputBuffer.asUGenInput, outputBuffer.asUGenInput) 83 | } 84 | 85 | init { arg ... theInputs; 86 | inputs = theInputs; 87 | ^this.initOutputs(1, rate); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /release-packaging/Examples/Guides/DataSetQuery to Filter Out some Data Points.scd: -------------------------------------------------------------------------------- 1 | ( 2 | // run the analysis 3 | Routine{ 4 | var time = Main.elapsedTime; 5 | var ds = FluidDataSet(s); 6 | var labels = FluidLabelSet(s); 7 | var scaler = FluidStandardize(s); 8 | var buf1 = Buffer.alloc(s,1); 9 | var dsq = FluidDataSetQuery(s); 10 | 11 | ~pitch_features_buf = Buffer.new(s); 12 | // specify some params for the analysis (these are the defaults, but we'll specify them here so we can use them later) 13 | ~windowSize = 4096; 14 | ~hopSize = 512; 15 | 16 | ~buf = Buffer.read(s,FluidFilesPath("Tremblay-FMTriDist-M.wav")); 17 | 18 | s.sync; 19 | 20 | FluidBufPitch.process(s,~buf,features:~pitch_features_buf,windowSize:~windowSize,hopSize:~hopSize).wait; 21 | // {~pitch_features_buf.plot(separately:true)}.defer; 22 | 23 | ds.fromBuffer(~pitch_features_buf,action:{ 24 | ds.print; 25 | /*dsq.addRange(0,2,{ 26 | dsq.filter(1,">",0.7,{ 27 | dsq.transform(ds,ds,{ 28 | ds.print;*/ 29 | ds.dump({ 30 | arg dict; 31 | ~pitch_features_array = Array.newClear(dict.at("data").size); 32 | dict.at("data").keysValuesDo({ 33 | arg id, pt, i; 34 | ~pitch_features_array[i] = [id,pt]; 35 | }); 36 | 37 | ~pitch_features_sorted = ~pitch_features_array.sort({ 38 | arg a, b; 39 | a[1][0] < b[1][0]; 40 | }); 41 | 42 | ~center_pos = ~pitch_features_sorted.collect({arg arr; (arr[0].asInteger * ~hopSize) / ~buf.sampleRate}); 43 | 44 | ~center_pos_buf = Buffer.loadCollection(s,~center_pos); 45 | }); 46 | /*}); 47 | }); 48 | });*/ 49 | }); 50 | }.play 51 | ) 52 | 53 | ( 54 | OSCdef(\fluidbufpitch_help,{ 55 | arg msg; 56 | msg[3].midiname.postln; 57 | },"/fluidbufpitch_help"); 58 | 59 | { 60 | var trig = Impulse.kr(s.sampleRate / ~hopSize); 61 | var index = (PulseCount.kr(trig) - 1) % BufFrames.ir(~center_pos_buf); 62 | var centerPos = Index.kr(~center_pos_buf,index); 63 | var pan = TRand.kr(-1.0,1.0,trig); 64 | var sig; 65 | var pitch, conf; 66 | sig = TGrains.ar(2,trig,~buf,BufRateScale.ir(~buf),centerPos,~windowSize / BufSampleRate.ir(~buf),pan,0.5); 67 | # pitch, conf = FluidPitch.kr(sig,unit:1,windowSize:4096); 68 | pitch = FluidStats.kr(pitch,25)[0]; 69 | SendReply.kr(Impulse.kr(30) * (conf > 0.6),"/fluidbufpitch_help",pitch); 70 | sig; 71 | }.play; 72 | ) -------------------------------------------------------------------------------- /release-packaging/Examples/buffer_compositing/bufcompose-MS-FIR.scd: -------------------------------------------------------------------------------- 1 | // A complex example of using composition as an Mid-Side FIR filtering process 2 | 3 | // load a stereo buffer and initialise the many destinations 4 | ( 5 | b = Buffer.read(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav")); 6 | c = Buffer.new(s); 7 | d = Buffer.new(s); 8 | e = Buffer.new(s); 9 | f = Buffer.new(s); 10 | ) 11 | 12 | // encode the mid (in c) and the side (in d) 13 | ( 14 | FluidBufCompose.process(s,b, numChans: 1, gain: -3.0.dbamp, destination: c); 15 | FluidBufCompose.process(s,b, numChans: 1, gain: -3.0.dbamp, destination: d); 16 | FluidBufCompose.process(s,b, numChans: 1, gain: -3.0.dbamp, startChan: 1, destination: c, destGain: 1.0); 17 | FluidBufCompose.process(s,b, numChans: 1, gain: -3.0.dbamp * -1.0, startChan: 1, destination: d, destGain: 1.0); 18 | ) 19 | 20 | // (optional) compare auraly the stereo with the MS 21 | b.play; 22 | {PlayBuf.ar(1, [c,d])}.play; 23 | 24 | //check nullsum with real-time versions 25 | {PlayBuf.ar(1, c) - PlayBuf.ar(2, b).madd(-3.0.dbamp).sum}.play; 26 | {PlayBuf.ar(1, d) - PlayBuf.ar(2, b).madd(-3.0.dbamp * [1,-1]).sum}.play; 27 | 28 | // The geeky bit: copy the side (buffer d) on itself with specific amplitudes and delays, in effect applying a FIR filter through expensive convolution 29 | 30 | // Important: do either of the 3 options below 31 | 32 | // option 1: apply a high pass on the side, with a cutoff of nyquist / 4 33 | e.free; e = Buffer.new(s); 34 | ( 35 | [1.0, -1.0].do({ arg x,y; 36 | FluidBufCompose.process(s, d, gain: x, destStartFrame: y, destination: e, destGain: 1.0); 37 | }); 38 | ) 39 | 40 | // option 2: apply a high pass on the side, with a cutoff of nyquist / 10 41 | e.free; e = Buffer.new(s); 42 | ( 43 | [0.8, -0.32, -0.24, -0.16, -0.08].do({ arg x,y; 44 | FluidBufCompose.process(s, d, gain: x, destStartFrame: y, destination: e, destGain: 1.0); 45 | }); 46 | ) 47 | 48 | // option 3: apply a high pass on the side, with a cutoff of nyquist / 100 49 | e.free; e = Buffer.new(s); 50 | ( 51 | [0.982494, -0.066859, -0.064358, -0.061897, -0.059477, -0.057098, -0.054761, -0.052466, -0.050215, -0.048007, -0.045843, -0.043724, -0.041649, -0.03962, -0.037636, -0.035697, -0.033805, -0.031959, -0.030159, -0.028406, -0.026699, -0.025038, -0.023425, -0.021857, -0.020337].do({ arg x,y; 52 | FluidBufCompose.process(s, d, gain: x, destStartFrame: y, destination: e, destGain: 1.0); 53 | }); 54 | ) 55 | 56 | // play the high-passed side buffer 57 | e.play; 58 | // if you want to try the other filters, do not forget to clear the destination buffer since it will add programmatically onto itself and would not create the expected frequency response 59 | 60 | // decode the MS back to stereo 61 | ( 62 | FluidBufCompose.process(s,c, numChans: 2, gain: -3.0.dbamp, destination: f); 63 | FluidBufCompose.process(s,e, gain: -3.0.dbamp, destination: f, destGain: 1.0); 64 | FluidBufCompose.process(s,e, gain: -3.0.dbamp * -1.0, destination: f, destStartChan: 1, destGain: 1.0); 65 | ) 66 | 67 | // play the MS processed version 68 | f.play; 69 | 70 | // compare with the original 71 | b.play; 72 | -------------------------------------------------------------------------------- /release-packaging/Examples/buffer_compositing/bufcomposemacros.scd: -------------------------------------------------------------------------------- 1 | // (re)set the source buffers 2 | ( 3 | ~low = Buffer.sendCollection(s, (Signal.sineFill(4410, Array.fill(3,0) ++ 1))); 4 | ~mid = Buffer.sendCollection(s, (Signal.sineFill(4410, Array.fill(12,0) ++ 1))); 5 | ~high = Buffer.sendCollection(s, (Signal.sineFill(4410, Array.fill(48,0) ++ 1))); 6 | ~piano = Buffer.read(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav"),0,8820); 7 | ) 8 | 9 | // draw the buffers to see what happened 10 | ( 11 | ~low.plot; 12 | ~mid.plot; 13 | ~high.plot; 14 | ~piano.plot; 15 | ) 16 | 17 | // define the concatenation macro 18 | ( 19 | ~concat = { 20 | arg x; 21 | if(x.class != Array, 22 | { 23 | "Error - Needs an array as argument".postln; 24 | }, { 25 | Routine{ 26 | for (1,x.size - 1, { 27 | arg i; 28 | FluidBufCompose.process(s,x[i],destination:x[0], destStartFrame:x[0].numFrames).wait; 29 | }); 30 | "Done!".postln; 31 | }.play; 32 | } 33 | ); 34 | } 35 | ) 36 | // test various combinations of concatenation 37 | ~concat.value([~low,~mid]) 38 | ~concat.value([~mid,~low,~high]) 39 | ~concat.value([~mid,~piano,~low]) 40 | ~concat.value([~mid,~piano]) 41 | 42 | // check the buffers for the results 43 | 44 | //////////////////////////////// 45 | 46 | // define the merging macro 47 | ( 48 | ~merge = { 49 | arg x; 50 | if(x.class != Array, 51 | { 52 | "Error - Needs an array as argument".postln; 53 | }, { 54 | Routine{ 55 | for (1,x.size - 1, { 56 | arg i; 57 | FluidBufCompose.process(s,x[i],destination:x[0],destGain:1); 58 | }); 59 | "Done!".postln; 60 | }.play; 61 | } 62 | ); 63 | } 64 | ) 65 | // test various combinations of merging 66 | ~merge.value([~low,~mid]) 67 | ~merge.value([~mid,~low,~high]) 68 | ~merge.value([~mid,~piano,~low]) 69 | ~merge.value([~mid,~piano]) 70 | 71 | // check the buffers for the results 72 | 73 | //////////////////////////////// 74 | 75 | // define the stacking macro 76 | ( 77 | ~stack = { 78 | arg x; 79 | if(x.class != Array, 80 | { 81 | "Error - Needs an array as argument".postln; 82 | }, { 83 | Routine{ 84 | for (1,x.size - 1, { 85 | arg i; 86 | FluidBufCompose.process(s,x[i],destination:x[0], destStartChan:x[0].numChannels).wait; 87 | }); 88 | "Done!".postln; 89 | }.play; 90 | } 91 | ); 92 | } 93 | ) 94 | // test various combinations of stacking 95 | ~stack.value([~low,~mid]) 96 | ~stack.value([~mid,~low,~high]) 97 | ~stack.value([~mid,~piano,~low]) 98 | ~stack.value([~mid,~piano]) 99 | 100 | // check the buffers for the results 101 | -------------------------------------------------------------------------------- /release-packaging/Examples/dataset/1-learning examples/10b-weighted-pitch-comparison.scd: -------------------------------------------------------------------------------- 1 | //load a part of a sound that has 3 clear components: a clear pitch component to start, a noisy pitchless ending and DC offset silence on both ends 2 | ( 3 | b = Buffer.read(s,FluidFilesPath("Tremblay-ASWINE-ScratchySynth-M.wav"),42250,44100); 4 | ~pitches = Buffer(s); 5 | ~stats = Buffer(s); 6 | ~loud = Buffer(s); 7 | ~scaled = Buffer(s); 8 | ~brutePitchStats = Array; 9 | ~loudnessWeighedPitchStats = Array; 10 | ~confidenceWeighedPitchStats = Array; 11 | ~condidenceWeightedPitchIQRStats = Array; 12 | ~pitchIQRStats = Array; 13 | ) 14 | 15 | b.play 16 | b.plot 17 | 18 | FluidBufPitch.process(s,b,features: ~pitches) 19 | FluidBufStats.process(s,~pitches,stats:~stats) 20 | ~stats.getn(0,14,{|x|~brutePitchStats = x; x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 21 | 22 | //observe the data - there are something clearly "wrong" in there - mostly, should we consider the stats on pitch when the confidence is low? 23 | ~pitches.plot(separately: true) 24 | 25 | //let's check the loudness 26 | FluidBufLoudness.process(s,b,features: ~loud) 27 | FluidBufStats.process(s,~loud,stats:~stats) 28 | ~stats.getn(0,14,{|x|x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 29 | 30 | ~loud.plot(separately: true) 31 | 32 | //it seems the loudness of the noisy section will not help us reject the silence. But let's try 33 | FluidBufScale.process(s,~loud,numChans: 1,destination: ~scaled,inputLow: -60,inputHigh: -20) 34 | FluidBufStats.process(s,~pitches, stats:~stats,weights: ~scaled) 35 | ~stats.getn(0,14,{|x|~loudnessWeighedPitchStats = x; x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 36 | //not much difference but let's listen 37 | 38 | //average pitch 39 | c = {SinOsc.ar(~brutePitchStats[0],mul: 0.05)}.play 40 | //compare with the source 41 | b.play 42 | c.free 43 | //loudness-weighted average 44 | c = {SinOsc.ar(~loudnessWeighedPitchStats[0],mul: 0.05)}.play 45 | //compare with the source 46 | b.play 47 | c.free 48 | //hmmm, worse! That is because we did remove the low amplitude skewing to wards the default value (high) which was balancing our noisy peak with low pitch and low pitch confidence... 49 | 50 | //let's instead weight against the pitch confidence, first applying a threshold to so we pull down any middle value we want to ignore 51 | FluidBufThresh.process(s, ~pitches, startChan: 1, numChans: 1, destination: ~scaled, threshold: 0.8) 52 | FluidBufStats.process(s,~pitches, stats:~stats,weights: ~scaled) 53 | ~stats.getn(0,14,{|x|~confidenceWeighedPitchStats = x;x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 54 | 55 | //let's listen 56 | c = {SinOsc.ar(~confidenceWeighedPitchStats[0],mul: 0.05)}.play 57 | //compare with the source 58 | b.play 59 | c.free 60 | // much better! it is even better when we move the threshold above but 0.8 confidence is quite high... If we look at our stats we see that there are still minima in the low hundreds, and maxima in the very top...These must be statistically far enough and few enough just to mess a bit our stats, so let's use the inter-quantile range to first remove them then compute the stats. 61 | FluidBufStats.process(s,~pitches, stats:~stats,weights: ~scaled,outliersCutoff: 1.5) 62 | ~stats.getn(0,14,{|x|~confidenceWeightedPitchIQRStats = x;x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 63 | //now that is impressive! 64 | c = {SinOsc.ar(~confidenceWeightedPitchIQRStats[0],mul: 0.05)}.play 65 | b.play 66 | c.free 67 | 68 | //for completion, here is just with rejection of outliers - not as good, but a decent second best! 69 | FluidBufStats.process(s,~pitches, stats:~stats,outliersCutoff: 1.5) 70 | ~stats.getn(0,14,{|x|~pitchIQRStats = x;x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 71 | c = {SinOsc.ar(~pitchIQRStats[0],mul: 0.05)}.play 72 | b.play 73 | c.free 74 | -------------------------------------------------------------------------------- /release-packaging/Examples/dataset/1-learning examples/7a-making-datasets-with-json.scd: -------------------------------------------------------------------------------- 1 | // create the data dictionary 2 | ~data = Dictionary.new 3 | 7.do{|i| ~data.add(("entry-"++i).asSymbol -> 10.collect{|j|j/10 + i})} 4 | 5 | // nest that dictionary in the dataset format, adding the number of columns 6 | ~dict = Dictionary.new 7 | ~dict.add(\data -> ~data) 8 | ~dict.add(\cols -> 10) 9 | 10 | //create a dataset, then loading the dictionary 11 | ~ds = FluidDataSet(s); 12 | ~ds.load(~dict) 13 | ~ds.print 14 | 15 | //fun with kdtree to see it actually works 16 | ~kdtree = FluidKDTree.new(s,numNeighbours:5) 17 | ~kdtree.fit(~ds,{\done.postln;}) 18 | ~target = Buffer.loadCollection(s,(4).dup(10)); 19 | ~kdtree.kNearest(~target, {|a|a.postln;}) 20 | ~kdtree.kNearestDist(~target, {|a|a.postln;}) 21 | 22 | 23 | ///////////////////////////////////////////// 24 | // creating a labelset the same way 25 | 26 | // creating the data dictionary 27 | ~data2 = Dictionary.new 28 | 7.do{|i| ~data2.add(("entry-"++i).asSymbol -> (if( i.odd, {["odd"]},{["even"]})))} 29 | 30 | // nesting again 31 | ~dict2 = Dictionary.new 32 | ~dict2.add(\data -> ~data2) 33 | ~dict2.add(\cols -> 1) 34 | 35 | // creating a labelset and loading the dictionary 36 | ~ls = FluidLabelSet(s); 37 | ~ls.load(~dict2) 38 | ~ls.print 39 | 40 | // testin with a classifier toy example 41 | ~classifier = FluidKNNClassifier.new(s, numNeighbours:2); 42 | ~classifier.fit(~ds,~ls, {\done.postln;}) 43 | 44 | // run many times for random pleasure 45 | ( 46 | fork{ 47 | var value = 7.rand; 48 | ~ds.getPoint(("entry-"++value).asSymbol,~target); 49 | s.sync; 50 | ~classifier.predictPoint(~target, action: {|x|"entry % is an % entry.\n".postf(value,x);}) 51 | } 52 | ) -------------------------------------------------------------------------------- /release-packaging/Examples/dataset/1-learning examples/8a-mlp-didactic.scd: -------------------------------------------------------------------------------- 1 | // basic xor to show non-linearity guestimating of MLP 2 | // see https://medium.com/@jayeshbahire/the-xor-problem-in-neural-networks-50006411840b 3 | // and https://youtu.be/188B6k_F9jU 4 | 5 | // make 2 datasets as our truth 6 | ( 7 | Routine{ 8 | d = Dictionary.new; 9 | d.add(\cols -> 2); 10 | d.add(\data -> Dictionary.newFrom(["f-f", [0,0], "f-t", [0,1], "t-f", [1,0], "t-t", [1,1]])); 11 | ~mlpHelpSource = FluidDataSet.new(s); 12 | s.sync; 13 | ~mlpHelpSource.load(d); 14 | s.sync; 15 | d.add(\cols -> 1); 16 | d.add(\data -> Dictionary.newFrom(["f-f", [0], "f-t", [1], "t-f", [1], "t-t", [0]])); 17 | ~mlpHelpTarget = FluidDataSet.new(s); 18 | s.sync; 19 | ~mlpHelpTarget.load(d); 20 | s.sync; 21 | }.play; 22 | ) 23 | 24 | //check our thruth tables 25 | ~mlpHelpSource.print 26 | ~mlpHelpTarget.print 27 | 28 | // make an MLPregressor 29 | ~mlp = FluidMLPRegressor(s, [3], FluidMLPRegressor.sigmoid, FluidMLPRegressor.sigmoid,maxIter:1000,learnRate: 0.1,momentum: 0.1,batchSize: 1,validation: 0);//1000 epoch at a time 30 | //train it by executing the following line multiple time, and observe the error 31 | ~mlp.fit(~mlpHelpSource,~mlpHelpTarget,{|x|x.postln;}); 32 | 33 | //to make a plot of the error let's do a classic 'shades of truth' (a grid of 11 x 11 with each values of truth between 0 and 1 34 | ( 35 | Routine{ 36 | d = Dictionary.new; 37 | 38 | d.add(\cols -> 2); 39 | d.add(\data -> Dictionary.newFrom(121.collect{|x|[x.asString, [x.div(10)/10,x.mod(10)/10]]}.flatten)); 40 | ~mlpHelpShades = FluidDataSet.new(s); 41 | s.sync; 42 | ~mlpHelpShades.load(d); 43 | s.sync; 44 | }.play; 45 | ) 46 | 47 | // check it 48 | ~mlpHelpShades.print 49 | 50 | // let's make a destination for our regressions 51 | ~mlpHelpRegressed = FluidDataSet.new(s); 52 | 53 | // then predict the full DataSet in our trained network 54 | ~mlp.predict(~mlpHelpShades,~mlpHelpRegressed); 55 | 56 | // estimated values 57 | ~mlpHelpRegressed.print; 58 | 59 | // lets extract them as an array 60 | ~assignments = Array.new(121); ~mlpHelpRegressed.dump{|x|~assignments = x.at("data").atAll(x.at("data").keys.asArray.sort{|a,b|a.asInteger < b.asInteger}).flatten.postln;}; 61 | 62 | //and draw them 63 | ( 64 | w = Window("scatter", Rect(128, 64, 200, 200)); 65 | w.drawFunc = { 66 | Pen.use { 67 | ~assignments.do{|val,ind| 68 | var x = (ind.div(10)*20); 69 | var y = (ind.mod(10)*20); 70 | var r = Rect(x,y,20,20); 71 | Pen.fillColor = Color.grey(val); 72 | Pen.fillRect(r); 73 | } 74 | } 75 | }; 76 | w.refresh; 77 | w.front; 78 | ) 79 | 80 | ~mlp.free 81 | ~mlpHelpShades.free 82 | ~mlpHelpSource.free 83 | ~mlpHelpTarget.free -------------------------------------------------------------------------------- /release-packaging/Examples/nmf/JiT-NMF.scd: -------------------------------------------------------------------------------- 1 | s.reboot 2 | 3 | //this patch does just-in-time nmf processes on buffer, faking a slightly delayed real-time version of it 4 | //what is happening: 5 | //a circular buffer is doing a fake real time - every half second, it sends a frame to be proceesed by NMF~, requesting 3 ranks. Because this latter process is randomly seeded and not sorted, the 3 ranks are not getting similar results each time, hence the random pan 6 | 7 | ( 8 | b = Buffer.alloc(s,s.sampleRate * 2); 9 | c = Buffer.new(s,0,3); 10 | d = Buffer.new(s,0,3); 11 | e = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); 12 | g = Bus.audio(s,1); 13 | h = Buffer.loadCollection(s, Signal.rectWindow(22491).fade(0,440).fade(22049,22489,1,0).put(22490,0)); 14 | 15 | SynthDef(\becauseIcan,{arg bufnum = 0, nmfa = 0, nmfb = 0, input = 0, env = 0; 16 | var head, head2, duration, audioin, halfdur; 17 | duration = BufFrames.kr(bufnum) / 2; 18 | halfdur = duration / 2; 19 | head = Phasor.ar(0,1,0,duration); 20 | head2 = (head + halfdur) % duration; 21 | 22 | // circular buffer writer 23 | audioin = In.ar(input,1); 24 | BufWr.ar(audioin,bufnum,head,0); 25 | BufWr.ar(audioin,bufnum,head+duration,0); 26 | 27 | // cue the calculations via the language 28 | SendReply.ar(head > 500, '/processplease',2); 29 | SendReply.ar(head > (halfdur + 500), '/processplease',1); 30 | 31 | // read the 2 buffers with an envelop 32 | Out.ar(0, Splay.ar(BufRd.ar(3,nmfa,head,0,1) * BufRd.ar(1,env,head,0,1)) + Splay.ar(BufRd.ar(3,nmfb,head2,0,1) * BufRd.ar(1,env,head2,0,1))); 33 | }).add; 34 | 35 | SynthDef(\playa, { arg output = 0, bufnum = 0; 36 | Out.ar(output,PlayBuf.ar(1,bufnum,loop:1)); 37 | }).add; 38 | ) 39 | 40 | // instantiate the player 41 | x = Synth(\playa,[\output, g.index, \bufnum, e.bufnum]); 42 | 43 | // instantiate the processor, please ignore the Buffer UGen warnings 44 | y = Synth(\becauseIcan,[\bufnum, b.bufnum, \nmfa, c.bufnum, \nmfb, d.bufnum, \input, g.index, \env, h.bufnum], x, 'addAfter'); 45 | 46 | // instantiate the listener to cue the processing from the language side 47 | ( 48 | w = OSCFunc({ arg msg; 49 | if(msg[3]== 1, { 50 | FluidBufNMF.process(s, b, numFrames: 22500, resynth: c.bufnum, resynthMode: 1, components: 3, fftSize: 1024, windowSize: 512, hopSize: 256); 51 | }, { 52 | FluidBufNMF.process(s, b, 22050, 22500, resynth: d.bufnum, resynthMode: 1, components: 3, fftSize: 1024, windowSize: 512, hopSize: 256); 53 | });}, '/processplease', s.addr); 54 | ) 55 | 56 | // stop it all 57 | b.free;c.free;d.free;e.free;f.free;g.free;w.clear;x.free; y.free; 58 | -------------------------------------------------------------------------------- /release-packaging/Examples/nmf/nmfmatch-object-finding.scd: -------------------------------------------------------------------------------- 1 | // using NMF, splitting a small portion, then associating components to targets, then thresholding on these target's activations to find objects. 2 | 3 | //set some buffers 4 | ( 5 | b = Buffer.read(s,FluidFilesPath("Tremblay-BaB-SoundscapeGolcarWithDog.wav")); 6 | c = Buffer.new(s); 7 | x = Buffer.new(s); 8 | e = Buffer.new(s); 9 | ) 10 | 11 | // train where all objects are present 12 | ( 13 | Routine { 14 | FluidBufNMF.process(s, b, startFrame: 130000, numFrames: 150000, numChans: 1, resynth: c, resynthMode: 1, bases: x, components:10).wait; 15 | c.query; 16 | }.play; 17 | ) 18 | 19 | // wait for the query to print 20 | // then find a component for each item you want to find. You could also sum them. Try to find a component with a good object-to-rest ratio 21 | ( 22 | ~dog =0; 23 | {PlayBuf.ar(10,c)[~dog]}.play 24 | ) 25 | 26 | ( 27 | ~bird = 1; 28 | {PlayBuf.ar(10,c)[~bird]}.play 29 | ) 30 | 31 | 32 | // copy at least one other component to a third filter, a sort of left-over channel 33 | ( 34 | Routine{ 35 | FluidBufCompose.process(s, x, startChan:~dog, numChans: 1, destination: e).wait; 36 | FluidBufCompose.process(s, x, startChan:~bird, numChans: 1, destStartChan: 1, destination: e, destGain:1).wait; 37 | (0..9).removeAll([~dog,~bird]).do({|chan|FluidBufCompose.process(s,x, startChan:chan, numChans: 1, destStartChan: 2, destination: e, destGain:1)}); 38 | e.query; 39 | }.play; 40 | ) 41 | e.plot; 42 | 43 | //using this trained basis we can then see the activation... (wait for 5 seconds before it prints!) 44 | ( 45 | { 46 | var source, blips; 47 | //read the source 48 | source = PlayBuf.ar(2, b); 49 | blips = FluidNMFMatch.kr(source.sum,e,3); 50 | }.plot(5); 51 | ) 52 | 53 | // ...and use some threshold to 'find' objects... 54 | ( 55 | { 56 | var source, blips; 57 | //read the source 58 | source = PlayBuf.ar(2, b); 59 | blips = Schmidt.kr(FluidNMFMatch.kr(source.sum,e,3),0.5,[10,1,1000]); 60 | }.plot(5); 61 | ) 62 | 63 | // ...and use these to sonify them 64 | ( 65 | { 66 | var source, blips, dogs, birds; 67 | //read the source 68 | source = PlayBuf.ar(2, b); 69 | blips = Schmidt.kr(FluidNMFMatch.kr(source.sum,e,3),0.5,[10,1,1000]); 70 | dogs = SinOsc.ar(100,0,Lag.kr(blips[0],0.05,0.15)); 71 | birds = SinOsc.ar(1000,0,Lag.kr(blips[1],0.05,0.05)); 72 | [dogs, birds] + source; 73 | }.play; 74 | ) 75 | -------------------------------------------------------------------------------- /release-packaging/Examples/nmf/nmfmatch-pretrained-piano.scd: -------------------------------------------------------------------------------- 1 | // Using an 88-components piano base to do polyphonic pitch tracking 2 | 3 | //load in the sound in and a pretrained basis 4 | ( 5 | b = Buffer.read(s,FluidFilesPath("Tremblay-SA-UprightPianoPedalWide.wav")); 6 | c = Buffer.read(s,FluidFilesPath("filters/piano-dicts.wav")); 7 | ) 8 | b.play 9 | c.query 10 | 11 | //use the pretrained bases to compute activations of each notes to drive the amplitude of a resynth 12 | ( 13 | { 14 | var source, resynth; 15 | source = PlayBuf.ar(2, b,loop:1).sum; 16 | resynth = SinOsc.ar((21..108).midicps, 0, FluidNMFMatch.kr(source,c,88,10,4096).madd(0.002)).sum; 17 | [source, resynth] 18 | }.play 19 | ) 20 | 21 | 22 | //now sample and hold the same stream to get notes identified, played and sent back via osc 23 | ( 24 | { 25 | var source, resynth, chain, trig, acts; 26 | source = PlayBuf.ar(2,b,loop:1).sum; 27 | 28 | // built in attack detection, delayed until the stable part of the sound 29 | chain = FFT(LocalBuf(256), source); 30 | trig = TDelay.kr(Onsets.kr(chain, 0.5),0.1); 31 | 32 | // samples and holds activation values that are scaled and capped, in effect thresholding them 33 | acts = Latch.kr(FluidNMFMatch.kr(source,c,88,10,4096).linlin(15,20,0,0.1),trig); 34 | 35 | // resynths as in the previous example, with the values sent back to the language 36 | resynth = SinOsc.ar((21..108).midicps, 0, acts).sum; 37 | SendReply.kr(trig, '/activations', acts); 38 | [source, resynth] 39 | // [source, T2A.ar(trig)] 40 | // resynth 41 | }.play 42 | ) 43 | 44 | // define a receiver for the activations 45 | ( 46 | OSCdef(\listener, {|msg| 47 | var data = msg[3..]; 48 | // removes the silent and spits out the indicies as midinote number 49 | data.collect({arg item, i; if (item > 0.01, {i + 21})}).reject({arg item; item.isNil}).postln; 50 | }, '/activations'); 51 | ) 52 | -------------------------------------------------------------------------------- /release-packaging/Examples/segmenting/nb_of_slices.scd: -------------------------------------------------------------------------------- 1 | ( 2 | b = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); 3 | c = Buffer.new(s); 4 | ) 5 | 6 | ( 7 | // with basic params 8 | Routine{ 9 | var startTime, target, tolerance, startThresh, prevThresh, curThresh, curVal, prevVal, iters, maxIters, dVal, dThresh; 10 | 11 | startTime = Main.elapsedTime; 12 | prevThresh = 0.1; //initial threshold (between 0.00001 and 0.99999 13 | target = 10; //number of slices desired 14 | tolerance = 0; // the acceptable error in the number of slices yield 15 | maxIters = 100; //max number of iterations acceptable 16 | 17 | //makes a first iteration 18 | FluidBufNoveltySlice.process(s,b, indices: c, threshold:prevThresh).wait; 19 | prevVal = c.numFrames; 20 | 21 | //makes a second iteration 22 | if ( (prevVal < target), { 23 | curThresh = (prevThresh * 0.5).max(0.000001); 24 | }, { 25 | curThresh = (prevThresh * 2).min(0.999999); 26 | }); 27 | FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh).wait; 28 | curVal = c.numFrames; 29 | 30 | //makes further iterations until the result is achieved, or the maximum of acceptable iterations is reached 31 | iters = 2; 32 | while ( { 33 | (iters < maxIters) && ((curVal - target).abs > tolerance) 34 | }, { 35 | iters = iters + 1; 36 | dVal = curVal - prevVal; 37 | dThresh = curThresh - prevThresh; 38 | 39 | prevThresh = curThresh; 40 | prevVal = curVal; 41 | 42 | if ( (dVal == 0), { 43 | //if we have not change results between the last 2 passes, make the variation of threshold bigger 44 | curThresh = (dThresh + curThresh).min(0.999999).max(0.000001); 45 | },{ 46 | //if we have 47 | curThresh = (((dThresh / dVal) * (target - curVal)) + curThresh).min(0.999999).max(0.000001); 48 | }); 49 | FluidBufNoveltySlice.process(s,b, indices: c, threshold:curThresh).wait; 50 | curVal = c.numFrames; 51 | } 52 | ); 53 | //depending on the outcome, gives the right info back 54 | 55 | if ( iters >= maxIters, { 56 | // failed 57 | "Failed to find a suitable threshold in % seconds.\n".postf((Main.elapsedTime - startTime).round(0.01)); 58 | }, { 59 | // succeeded 60 | "Found % as a suitable threshold for % slices in % seconds and % iterations.\n".postf(curThresh, curVal, (Main.elapsedTime - startTime).round(0.01), iters); 61 | } 62 | ); 63 | }.play 64 | ) 65 | -------------------------------------------------------------------------------- /release-packaging/HelpSource/Classes/FluidBufToKr.schelp: -------------------------------------------------------------------------------- 1 | TITLE:: FluidBufToKr 2 | summary:: Helper pseudo UGen for reading data out of a buffer to a Kr stream 3 | categories:: Libraries>FluidCorpusManipulation 4 | related:: Classes/FluidKrToBuf 5 | 6 | DESCRIPTION:: 7 | Helper pseudo UGen for reading data out of a buffer to a Kr stream. It only reads one-channel buffers, converting them to a Kr stream. 8 | 9 | CLASSMETHODS:: 10 | 11 | METHOD:: kr 12 | Initialize an instance of this pseudo UGen 13 | 14 | ARGUMENT:: buffer 15 | Either a link::Classes/Buffer:: object or an index opointing to a buffer that this pseudo UGen will read out of. Must be a one-channel buffer. 16 | 17 | ARGUMENT:: startFrame 18 | Offset of reading position in the buffer. The default is 0. 19 | 20 | ARGUMENT:: numFrames 21 | Number of frames to read from the buffer. Needs to be set, if buffer is not a code::Buffer:: object but a buffer index. If code::-1::, read whole buffer starting at code::startFrame::. The default is -1. 22 | 23 | returns:: a Kr stream that has the same number of channels as frames in the link::Classes/Buffer::. 24 | 25 | INSTANCEMETHODS:: 26 | 27 | EXAMPLES:: 28 | 29 | code:: 30 | 31 | // fill a 1-channel buffer with 7 numbers 32 | ~buf = Buffer.loadCollection(s,{exprand(100,4000)} ! 7); 33 | 34 | // in a synth, read those numbers out of the buffer and get them as a control stream 35 | ( 36 | ~synth = { 37 | arg buf; 38 | var freqs = FluidBufToKr.kr(buf,numFrames:7); 39 | var sig = SinOsc.ar(freqs.lag(0.03)) * 0.1; 40 | sig.poll; 41 | Splay.ar(sig); 42 | }.play(args:[\buf,~buf]); 43 | ) 44 | 45 | // then you can change what's in the buffer and it will get read out by the synth 46 | ~buf.setn(0,{exprand(100,4000)} ! 7); 47 | 48 | :: 49 | Use with other FluCoMa objects: 50 | code:: 51 | 52 | // create an neural network for classification 53 | ~mlp = FluidMLPClassifier(s); 54 | 55 | // load a model that has been pre-trained to classify between a tone and noise, simple, i know, but... 56 | ~mlp.read(FluidFilesPath("../../Resources/bufToKrExample.json")); 57 | 58 | // can be used to demonstrate that... 59 | ( 60 | { 61 | var input_buf = LocalBuf(7); 62 | var out_buf = LocalBuf(1); 63 | var sig = Select.ar(ToggleFF.kr(Dust.kr(1)),[SinOsc.ar(440),PinkNoise.ar]); 64 | var analysis = FluidSpectralShape.kr(sig); 65 | FluidKrToBuf.kr(analysis,input_buf); 66 | 67 | // the output prediction is written into a buffer 68 | ~mlp.kr(Impulse.kr(30),input_buf,out_buf); 69 | 70 | // and FluidBufToKr can be used to read the prediction out into a control rate stream 71 | FluidBufToKr.kr(out_buf).poll; 72 | 73 | sig.dup * -30.dbamp 74 | }.play; 75 | ) 76 | 77 | :: -------------------------------------------------------------------------------- /release-packaging/HelpSource/Classes/FluidFilesPath.schelp: -------------------------------------------------------------------------------- 1 | TITLE:: FluidFilesPath 2 | summary:: A convenience class for accessing the audio files provided with the FluCoMa Extension 3 | categories:: Libraries>FluidCorpusManipulation 4 | related:: Classes/FluidLoadFolder 5 | 6 | DESCRIPTION:: 7 | 8 | 9 | CLASSMETHODS:: 10 | 11 | METHOD:: new 12 | Get the path to the "AudioFiles" folder inside the FluCoMa extensions folder. Following this with a ++ "name_Of_The_File-You-Want.wav" will create the path to file you want. 13 | 14 | ARGUMENT:: fileName 15 | Optionally, you may pass in the name of the file you want to use and the *new class method will return the path to that file. 16 | 17 | returns:: The path to the "AudioFiles" folder inside the FluCoMa extensions folder (optionally with provided file name). 18 | 19 | EXAMPLES:: 20 | 21 | code:: 22 | ( 23 | // these will return the same path 24 | (FluidFilesPath()++"Nicol-LoopE-M.wav").postln; 25 | FluidFilesPath("Nicol-LoopE-M.wav").postln; 26 | ) 27 | 28 | ( 29 | // test it one way 30 | s.waitForBoot{ 31 | Routine{ 32 | var path = FluidFilesPath()++"Nicol-LoopE-M.wav"; 33 | var buf = Buffer.read(s,path); 34 | 35 | s.sync; 36 | 37 | buf.play; 38 | }.play; 39 | } 40 | ) 41 | 42 | ( 43 | // test it another way 44 | s.waitForBoot{ 45 | Routine{ 46 | var path = FluidFilesPath("Nicol-LoopE-M.wav"); 47 | var buf = Buffer.read(s,path); 48 | 49 | s.sync; 50 | 51 | buf.play; 52 | }.play; 53 | } 54 | ) 55 | :: 56 | -------------------------------------------------------------------------------- /release-packaging/HelpSource/Classes/FluidKrToBuf.schelp: -------------------------------------------------------------------------------- 1 | TITLE:: FluidKrToBuf 2 | summary:: Helper pseudo UGen for writing data into a buffer from a Kr stream 3 | categories:: Libraries>FluidCorpusManipulation 4 | related:: Classes/FluidBufToKr 5 | 6 | DESCRIPTION:: 7 | Helper pseudo UGen for writing data into a buffer from a Kr stream. It only works with one-channel buffers. 8 | 9 | CLASSMETHODS:: 10 | 11 | METHOD:: kr 12 | Create a new instance of this pseudo UGen. 13 | 14 | ARGUMENT:: krStream 15 | The Kr stream to write into the buffer. 16 | 17 | ARGUMENT:: buffer 18 | The buffer to write the Kr stream into. Can be either a link::Classes/Buffer:: object, or an index poiting to a buffer. 19 | 20 | ARGUMENT:: krStartChan 21 | The channel in the code::krStream:: to begin the reading from. The default is 0. 22 | 23 | ARGUMENT:: krNumChans 24 | The number of channels in the code::krStream:: to read from starting at code::krStartChan:: The default of -1 will read from code::krStartChan:: to the max number of channels in the code::krStream::. 25 | 26 | ARGUMENT:: destStartFrame 27 | The frame in the code::buffer:: to begin writing into. The default is 0. 28 | 29 | returns:: This class. 30 | 31 | INSTANCEMETHODS:: 32 | 33 | 34 | EXAMPLES:: 35 | code:: 36 | 37 | ( 38 | ~synth = { 39 | var buf = LocalBuf(512).clear; 40 | var sig = SinOsc.ar([440,441]); 41 | var lfos = Array.fill(512,{arg i; SinOsc.ar(i.linlin(0,511,0.01,0.2))}); 42 | FluidKrToBuf.kr(lfos,buf); 43 | sig = Shaper.ar(buf,sig); 44 | sig.dup * -40.dbamp; 45 | }.scope; 46 | ) 47 | 48 | :: 49 | Use with other FluCoMa objects: 50 | code:: 51 | 52 | // make a new dataset 53 | ~ds = FluidDataSet(s); 54 | 55 | // run a synth with varying sounds and an mfcc analysis 56 | ( 57 | ~synth = { 58 | arg t_trig; 59 | var buf = LocalBuf(13); 60 | var n = 7; 61 | var sig = BPF.ar(PinkNoise.ar.dup(n),LFDNoise1.kr(2.dup(n)).exprange(100,4000)).sum * -20.dbamp; 62 | var mfccs = FluidMFCC.kr(sig,buf.numFrames,startCoeff:1,maxNumCoeffs:buf.numFrames); 63 | 64 | // write the real-time mfcc analysis into this buffer so that... 65 | FluidKrToBuf.kr(mfccs,buf); 66 | 67 | // it can be added to the dataset from that buffer by sending a trig to the synth 68 | FluidDataSetWr.kr(~ds,"point-",PulseCount.kr(t_trig),buf:buf,trig:t_trig); 69 | sig.dup; 70 | }.play; 71 | ) 72 | 73 | // send a bunch of triggers and... 74 | ~synth.set(\t_trig,1); 75 | 76 | // see how your dataset grows 77 | ~ds.print; 78 | 79 | :: 80 | -------------------------------------------------------------------------------- /release-packaging/HelpSource/Classes/FluidLoadFolder.schelp: -------------------------------------------------------------------------------- 1 | TITLE:: FluidLoadFolder 2 | summary:: Load a folder of audio into a single buffer 3 | categories:: Libraries>FluidCorpusManipulation 4 | related:: Classes/FluidSliceCorpus, Classes/FluidProcessSlices 5 | 6 | DESCRIPTION:: 7 | Given a path name, load every audio file in the path (using link::Classes/SoundFile#*collect::), allocate a link::Classes/Buffer::, and load the files top to tail into the buffer. Information about start stop points, channel counts and sample rates is then stored in link::Classes/FluidLoadFolder#index:: as a link::Classes/IdentityDictionary::. 8 | 9 | 10 | CLASSMETHODS:: 11 | 12 | METHOD:: new 13 | Construct a new instance 14 | 15 | ARGUMENT:: path 16 | A string pointing to a folder on disk 17 | 18 | ARGUMENT:: idFunc 19 | A function that determines how the identifiers for the chunks are created; default is file name without path. 20 | 21 | ARGUMENT:: channelFunc 22 | A funciton that controls what to do with differently wide files. Default behaviour is for loaded buffer to have as many channels as the widest file in the path, and for narrower files to repeat their channels across this buffer. The funciton is passed the channels for the current file, the maximum channel count, and the current index. 23 | 24 | INSTANCEMETHODS:: 25 | 26 | METHOD:: index 27 | A link::Classes/IdentityDictionary:: containing the metadata on the loaded files 28 | 29 | The keys of this dictionary are the identifiers produced by the code::idFunc:: passed to link::Classes/FluidLoadFolder#*new:: (or the default of the filename if nil). The value for each key is a further dictionary consisting of: 30 | 31 | definitionlist:: 32 | ## bounds 33 | || A two element array giving the start and end point of this files eventual position in the overall buffer (in samples). 34 | ## sr 35 | || The sampling rate of the original file 36 | ## numchans 37 | || Number of channels in the original file 38 | :: 39 | 40 | METHOD:: files 41 | The list of files loaded 42 | 43 | METHOD:: buffer 44 | The buffer in which the files are placed, end to end. 45 | 46 | METHOD:: play 47 | Load the files. 48 | 49 | ARGUMENT:: server 50 | The server on which to run 51 | 52 | ARGUMENT:: action 53 | Function to execute on completion 54 | 55 | 56 | EXAMPLES:: 57 | 58 | code:: 59 | s.reboot; 60 | 61 | ( 62 | // We'll load all the Fluid Corpus Manipulation audio example files 63 | ~path = FluidFilesPath(); 64 | 65 | ~loader = FluidLoadFolder(~path); 66 | 67 | ~loader.play(s,action:{ |dataDictionary| 68 | ("Done loading into" + ~loader.buffer).postln; 69 | //we get passed an IdentityDictionary of slice data, let's look at it 70 | dataDictionary.pairsDo{|identifier,data| 71 | //data is also a dictionary 72 | (identifier ++ '(').post; 73 | data.pairsDo{|k,v| (k ++ ':' + v + ' ').post }; 74 | ')'.postln; 75 | } 76 | }); 77 | ) 78 | :: 79 | -------------------------------------------------------------------------------- /release-packaging/HelpSource/Classes/FluidManipulationClient.schelp: -------------------------------------------------------------------------------- 1 | TITLE:: FluidManipulationClient 2 | summary:: A base case for Libraries>FluidCorpusManipulation classes 3 | categories:: Libraries>FluidCorpusManipulation 4 | 5 | DESCRIPTION:: 6 | A utility base class for Libraries>FluidCorpusManipulation classes, that deals with common functionality (wrapping a link::Classes/Synth:: in the instance, etc.) 7 | 8 | Not intended to be used directly. 9 | 10 | CLASSMETHODS:: 11 | 12 | PRIVATE:: nonBlocking 13 | 14 | METHOD:: new 15 | Language-side constructor. Internally, this creates a new synth around an instance of the sub-class being constructed, and maintains a variable pointing to the synth, so that it can be communicated with. 16 | 17 | ARGUMENT:: server 18 | The link::Classes/Server:: this instance is running on 19 | 20 | ARGUMENT:: ... args 21 | Arguments specific to the sub-class at hand 22 | 23 | returns:: A new instance 24 | 25 | INSTANCEMETHODS:: 26 | 27 | private:: pr_sendMsg 28 | 29 | METHOD:: synth 30 | Fluid Manipulation client objects are server-side entities, wrapped in a Node to manage communication between language and object. For this, a link::Classes/Synth:: is needed, as the representation of a server node. 31 | 32 | returns:: the instance's link::Classes/Synth:: 33 | 34 | METHOD:: server 35 | The link::Classes/Server:: that our instance's object is running on 36 | 37 | returns:: a link::Classes/Server:: 38 | 39 | METHOD:: read 40 | Read the object's data from a JSON file on disk, replacing the current contents. 41 | ​ 42 | METHOD:: write 43 | Write the object's data to disk as a JSON file. 44 | 45 | METHOD:: size 46 | Report the number of items currently in the object's data. 47 | 48 | METHOD:: cols 49 | Report the dimensionality of the object's data. If action is nil, will default to posting result. 50 | 51 | METHOD:: dump 52 | Get the contents of the object's data as a Dictionary (note: uses a temporary file under the hood); 53 | 54 | METHOD:: load 55 | Fill the object with the contents of a dictionary, replacing its current contents (note: uses a temporary file under the hood). 56 | -------------------------------------------------------------------------------- /sc-resources/bufToKrExample.json: -------------------------------------------------------------------------------- 1 | { 2 | "labels": { 3 | "labels": [ 4 | "tone", 5 | "noise" 6 | ], 7 | "rows": 2 8 | }, 9 | "mlp": { 10 | "layers": [ 11 | { 12 | "activation": 1, 13 | "biases": [ 14 | 9.475189836135217e-245, 15 | -7.312978302687739e-296, 16 | 0.0, 17 | 0.0, 18 | 0.0 19 | ], 20 | "cols": 5, 21 | "rows": 7, 22 | "weights": [ 23 | [ 24 | -0.7070957130289968, 25 | 0.2529529084252004, 26 | -0.6315006118399392, 27 | 0.2641365029014226, 28 | -0.11879484878940468 29 | ], 30 | [ 31 | -0.5210842572299229, 32 | 0.25356340881888756, 33 | 0.04200241621968997, 34 | 0.12583197506255497, 35 | 0.2845264672854667 36 | ], 37 | [ 38 | 0.36148051326296066, 39 | 0.614748588906755, 40 | 0.24204178015383798, 41 | 0.6087291285844215, 42 | 0.5802812834026664 43 | ], 44 | [ 45 | -0.05847754423619632, 46 | -0.16475294200213061, 47 | -0.6962199018410693, 48 | 0.48955391140174614, 49 | 0.3708040237508281 50 | ], 51 | [ 52 | 0.04633987154978883, 53 | 0.02745889671058346, 54 | -0.16487516786286913, 55 | 0.03808304248049002, 56 | -0.33594219806125813 57 | ], 58 | [ 59 | -0.3974517302751846, 60 | 0.4680556811476128, 61 | -0.6125775823484346, 62 | -0.5770487854150471, 63 | -0.6399818221697359 64 | ], 65 | [ 66 | -0.6405756468993841, 67 | -0.65821443359875, 68 | -0.1166924540077695, 69 | 0.21767428398943345, 70 | 0.3338702030112145 71 | ] 72 | ] 73 | }, 74 | { 75 | "activation": 1, 76 | "biases": [ 77 | -0.3628999139757816, 78 | -0.42250374321781475 79 | ], 80 | "cols": 2, 81 | "rows": 5, 82 | "weights": [ 83 | [ 84 | -0.31804841180355814, 85 | -0.46839296834399485 86 | ], 87 | [ 88 | -4.2805091183479895, 89 | 4.474227050298208 90 | ], 91 | [ 92 | 0.4747799633725462, 93 | 0.4122869489228666 94 | ], 95 | [ 96 | 0.5463246485585964, 97 | 0.04662010562772569 98 | ], 99 | [ 100 | 3.913863778074305, 101 | -3.7226634012685995 102 | ] 103 | ] 104 | } 105 | ] 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /sc-resources/color-schemes/-credits.txt: -------------------------------------------------------------------------------- 1 | https://colorcet.com/ 2 | 3 | Kovesi, Peter. "Good colour maps: How to design them." arXiv preprint arXiv:1509.03700 (2015). 4 | https://arxiv.org/abs/1509.03700 5 | -------------------------------------------------------------------------------- /scripts/MakeDevTree.cmake: -------------------------------------------------------------------------------- 1 | # Part of the Fluid Corpus Manipulation Project (http://www.flucoma.org/) 2 | # Copyright University of Huddersfield. 3 | # Licensed under the BSD-3 License. 4 | # See license.md file in the project root for full license information. 5 | # This project has received funding from the European Research Council (ERC) 6 | # under the European Union’s Horizon 2020 research and innovation programme 7 | # (grant agreement No 725899). 8 | 9 | cmake_minimum_required(VERSION 3.18) 10 | 11 | file(GLOB helpfiles "${ROOT}/help/*") 12 | file(GLOB abstractions "${ROOT}/abstractions/*") 13 | file(GLOB externals "${ROOT}/pd_objects/*") 14 | 15 | set(devfolder "${ROOT}/dev") 16 | file(REMOVE_RECURSE ${devfolder}) 17 | file(MAKE_DIRECTORY ${devfolder}) 18 | 19 | foreach(item IN LISTS helpfiles abstractions externals) 20 | get_filename_component(item_name "${item}" NAME) 21 | file(CREATE_LINK "${item}" "${devfolder}/${item_name}" SYMBOLIC) 22 | endforeach() 23 | 24 | file(CREATE_LINK "${CORE_SRC}/Resources/" "${devfolder}/Resources" SYMBOLIC) 25 | file(CREATE_LINK "${BINARIES}/Resources/" "${devfolder}/Resources" SYMBOLIC) 26 | file(CREATE_LINK "${CORE_SRC}/Resources/" "${devfolder}/Resources" SYMBOLIC) 27 | file(CREATE_LINK "${CORE_SRC}/Resources/" "${devfolder}/Resources" SYMBOLIC) 28 | file(CREATE_LINK "${CORE_SRC}/Resources/" "${devfolder}/Resources" SYMBOLIC) 29 | -------------------------------------------------------------------------------- /scripts/settings/FluidManipulation.cpp.in: -------------------------------------------------------------------------------- 1 | makeSCWrapper("FluidDataSetRead",inTable); 2 | makeSCWrapper("FluidKDTreeQuery",inTable); 3 | makeSCWrapper("FluidKMeansQuery",inTable); 4 | makeSCWrapper("FluidSKMeansQuery",inTable); 5 | makeSCWrapper("FluidKNNClassifierQuery",inTable); 6 | makeSCWrapper("FluidKNNRegressorQuery",inTable); 7 | makeSCWrapper("FluidNormalizeQuery",inTable); 8 | makeSCWrapper("FluidRobustScaleQuery",inTable); 9 | makeSCWrapper("FluidStandardizeQuery",inTable); 10 | makeSCWrapper("FluidPCAQuery",inTable); 11 | makeSCWrapper("FluidUMAPQuery",inTable); 12 | makeSCWrapper("FluidMLPRegressorQuery",inTable); 13 | makeSCWrapper("FluidMLPClassifierQuery",inTable); 14 | -------------------------------------------------------------------------------- /test/10b-weighted-pitch-comparison.scd: -------------------------------------------------------------------------------- 1 | //load a part of a sound that has 3 clear components: a clear pitch component to start, a noisy pitchless ending and DC offset silence on both ends 2 | ( 3 | b = Buffer.read(s,FluidFilesPath("Tremblay-ASWINE-ScratchySynth-M.wav"),42250,44100); 4 | ~pitches = Buffer(s); 5 | ~stats = Buffer(s); 6 | ~loud = Buffer(s); 7 | ~scaled = Buffer(s); 8 | ~brutePitchStats = Array; 9 | ~loudnessWeighedPitchStats = Array; 10 | ~confidenceWeighedPitchStats = Array; 11 | ~condidenceWeightedPitchIQRStats = Array; 12 | ~pitchIQRStats = Array; 13 | ) 14 | 15 | b.play 16 | b.plot 17 | 18 | FluidBufPitch.process(s,b,features: ~pitches) 19 | FluidBufStats.process(s,~pitches,stats:~stats) 20 | ~stats.getn(0,14,{|x|~brutePitchStats = x; x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 21 | 22 | //observe the data - there are something clearly "wrong" in there - mostly, should we consider the stats on pitch when the confidence is low? 23 | ~pitches.plot(separately: true) 24 | 25 | //let's check the loudness 26 | FluidBufLoudness.process(s,b,features: ~loud) 27 | FluidBufStats.process(s,~loud,stats:~stats) 28 | ~stats.getn(0,14,{|x|x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 29 | 30 | ~loud.plot(separately: true) 31 | 32 | //it seems the loudness of the noisy section will not help us reject the silence. But let's try 33 | FluidBufScale.process(s,~loud,numChans: 1,destination: ~scaled,inputLow: -60,inputHigh: -20) 34 | FluidBufStats.process(s,~pitches, stats:~stats,weights: ~scaled) 35 | ~stats.getn(0,14,{|x|~loudnessWeighedPitchStats = x; x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 36 | //not much difference but let's listen 37 | 38 | //average pitch 39 | c = {SinOsc.ar(~brutePitchStats[0],mul: 0.05)}.play 40 | //compare with the source 41 | b.play 42 | c.free 43 | //loudness-weighted average 44 | c = {SinOsc.ar(~loudnessWeighedPitchStats[0],mul: 0.05)}.play 45 | //compare with the source 46 | b.play 47 | c.free 48 | //hmmm, worse! That is because we did remove the low amplitude skewing to wards the default value (high) which was balancing our noisy peak with low pitch and low pitch confidence... 49 | 50 | //let's instead weight against the pitch confidence, first applying a threshold to so we pull down any middle value we want to ignore 51 | FluidBufThresh.process(s, ~pitches, startChan: 1, numChans: 1, destination: ~scaled, threshold: 0.8) 52 | FluidBufStats.process(s,~pitches, stats:~stats,weights: ~scaled) 53 | ~stats.getn(0,14,{|x|~confidenceWeighedPitchStats = x;x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 54 | 55 | //let's listen 56 | c = {SinOsc.ar(~confidenceWeighedPitchStats[0],mul: 0.05)}.play 57 | //compare with the source 58 | b.play 59 | c.free 60 | // much better! it is even better when we move the threshold above but 0.8 confidence is quite high... If we look at our stats we see that there are still minima in the low hundreds, and maxima in the very top...These must be statistically far enough and few enough just to mess a bit our stats, so let's use the inter-quantile range to first remove them then compute the stats. 61 | FluidBufStats.process(s,~pitches, stats:~stats,weights: ~scaled,outliersCutoff: 1.5) 62 | ~stats.getn(0,14,{|x|~confidenceWeightedPitchIQRStats = x;x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 63 | //now that is impressive! 64 | c = {SinOsc.ar(~confidenceWeightedPitchIQRStats[0],mul: 0.05)}.play 65 | b.play 66 | c.free 67 | 68 | //for completion, here is just with rejection of outliers - not as good, but a decent second best! 69 | FluidBufStats.process(s,~pitches, stats:~stats,outliersCutoff: 1.5) 70 | ~stats.getn(0,14,{|x|~pitchIQRStats = x;x.reshape(7,2).do{|y| "%\t\t\t%\n".postf(y[0].round(0.1),y[1].round(0.01))}}) 71 | c = {SinOsc.ar(~pitchIQRStats[0],mul: 0.05)}.play 72 | b.play 73 | c.free 74 | -------------------------------------------------------------------------------- /test/FluidFilesPath_test.scd: -------------------------------------------------------------------------------- 1 | ( 2 | // these will return the same path 3 | (FluidFilesPath()++"Nicol-LoopE-M.wav").postln; 4 | FluidFilesPath("Nicol-LoopE-M.wav").postln; 5 | ) 6 | 7 | ( 8 | // test it one way 9 | s.waitForBoot{ 10 | Routine{ 11 | var path = FluidFilesPath()++"Nicol-LoopE-M.wav"; 12 | var buf = Buffer.read(s,path); 13 | 14 | s.sync; 15 | 16 | buf.play; 17 | }.play; 18 | } 19 | ) 20 | 21 | ( 22 | // test it another way 23 | s.waitForBoot{ 24 | Routine{ 25 | var path = FluidFilesPath("Nicol-LoopE-M.wav"); 26 | var buf = Buffer.read(s,path); 27 | 28 | s.sync; 29 | 30 | buf.play; 31 | }.play; 32 | } 33 | ) -------------------------------------------------------------------------------- /test/FluidWaveform raster scratch paper.scd: -------------------------------------------------------------------------------- 1 | ( 2 | ~normalize = { 3 | arg vals; 4 | var min = vals.minItem; 5 | var max = vals.maxItem; 6 | var range = max - min; 7 | 8 | "min: %".format(min).postln; 9 | "max: %".format(max).postln; 10 | "range: %".format(range).postln; 11 | 12 | vals = (vals - min) / range; 13 | vals = (vals * 255).asInteger; 14 | vals; 15 | }; 16 | 17 | ~dbs_range = { 18 | arg vals; 19 | vals.postln; 20 | vals = vals / vals.maxItem; 21 | vals.postln; 22 | vals = vals.ampdb; 23 | vals.postln; 24 | vals = vals.linlin(-120.0,0.0,0.0,255.0).asInteger; 25 | vals.postln; 26 | vals; 27 | }; 28 | 29 | ~raster = { 30 | arg rasterBuffer; 31 | var colors; 32 | 33 | colors = CSVFileReader.readInterpret(FluidFilesPath("../color-schemes/%.csv".format("CET-L16"))).collect{ 34 | arg row; 35 | Color.fromArray(row); 36 | }; 37 | 38 | rasterBuffer.loadToFloatArray(action:{ 39 | arg vals; 40 | "n vals in raster buffer: %".format(vals.size).postln; 41 | fork({ 42 | var img = Image(rasterBuffer.numFrames,rasterBuffer.numChannels); 43 | // vals = ~normalize.(vals); 44 | vals = ~dbs_range.(vals); 45 | 46 | vals.do{ 47 | arg val, index; 48 | img.setColor(colors[val], index.div(rasterBuffer.numChannels), rasterBuffer.numChannels - 1 - index.mod(rasterBuffer.numChannels)); 49 | }; 50 | 51 | img.plot; 52 | },AppClock); 53 | }); 54 | }; 55 | ) 56 | 57 | // show mels 58 | ~drums = Buffer.read(s,FluidFilesPath("Nicol-LoopE-M.wav")); 59 | ~rasterBuffer = Buffer(s); 60 | ( 61 | fork({ 62 | Window.closeAll; 63 | FluidBufMelBands.processBlocking(s,~drums,features:~rasterBuffer,windowSize:4096,hopSize:256,numBands:480,action:{"done".postln}); 64 | // FluidBufSTFT.processBlocking(s,~drums,magnitude:~rasterBuffer,windowSize:1024,action:{"done".postln}); 65 | // FluidBufMFCC.processBlocking(s,~drums,features:~rasterBuffer,windowSize:1024,action:{"done".postln}); 66 | // FluidBufChroma.processBlocking(s,~drums,features:~rasterBuffer,action:{"done".postln}); 67 | 68 | s.sync; 69 | ~rasterBuffer.postln; 70 | 71 | ~raster.(~rasterBuffer); 72 | },AppClock); 73 | ) 74 | -------------------------------------------------------------------------------- /test/PCA_inverse_test.scd: -------------------------------------------------------------------------------- 1 | ( 2 | fork{ 3 | ~dict = Dictionary.newFrom([ 4 | "cols",5, 5 | "data",Dictionary.newFrom(Array.fill(20,{ 6 | arg i; 7 | [(i/2).asInteger,Array.fill(5,{rrand(-1.0,1.0)})] 8 | }).flatten) 9 | ]); 10 | ~ds = FluidDataSet(s).load(~dict); 11 | ~pca = FluidPCA(s,5); 12 | ~pca.fit(~ds); 13 | b = Buffer.alloc(s,5); 14 | e = 5.collect{rrand(-1.0,1.0)}.postln; 15 | s.sync; 16 | b.setn(0,e); 17 | c = Buffer.alloc(s,5); 18 | d = Buffer(); 19 | } 20 | ) 21 | 22 | b.plot 23 | 24 | ~pca.transformPoint(b,c); 25 | 26 | ( 27 | c.loadToFloatArray(action:{ 28 | arg fa; 29 | fa.postln; 30 | }); 31 | ) 32 | 33 | ~pca.inverseTransformPoint(c,d); 34 | 35 | ( 36 | d.loadToFloatArray(action:{ 37 | arg fa; 38 | fa.postln; 39 | (fa - e).postln; 40 | }); 41 | ) --------------------------------------------------------------------------------