diff --git a/.travis.yml b/.travis.yml index 266b8a8..716ed91 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,7 +17,7 @@ matrix: script: - mkdir build && cd build - cmake .. -GXcode -DUSE_LLVM_CONFIG=off -DLLVM_DIR=./llvm/lib/cmake/llvm - - cmake --build . --config Release --target faust_tilde_project + - cmake --build . --config Release --target faustgen_tilde_project - os: linux compiler: gcc env: release_arch=Linux-amd64-32 @@ -29,16 +29,16 @@ matrix: script: - mkdir build && cd build - cmake .. -DCMAKE_C_FLAGS=-m64 -DUSE_LLVM_CONFIG=off -DLLVM_DIR=./llvm/lib/cmake/llvm -DCMAKE_BUILD_TYPE=Release - - cmake --build . --config Release --target faust_tilde_project + - cmake --build . --config Release --target faustgen_tilde_project before_deploy: - cd $TRAVIS_BUILD_DIR - cp -r faust/libraries external/libs - - cp src/faust_tilde.c external/faust_tilde.c + - cp src/faustgen_tilde.c external/faustgen_tilde.c - cp README.md external/README.txt - cp LICENSE external/LICENSE.txt - curl -o ./external/faust-quick-reference.pdf http://faust.grame.fr/images/faust-quick-reference.pdf - - mv external faust~ - - zip -r "faust_tilde-$release_arch-sources.zip" faust~ + - mv external faustgen~ + - zip -r "faustgen_tilde-$release_arch-sources.zip" faustgen~ deploy: provider: releases diff --git a/CMakeLists.txt b/CMakeLists.txt index 96368a7..590c866 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) include(pd.build/pd.cmake) -project(faust~ C) +project(faustgen~ C) ## On Linux "force" the link with stdc++ if(UNIX AND NOT APPLE) @@ -29,17 +29,25 @@ endif() include(FaustLib.cmake) ## Create Faust~ -message(STATUS "Faust External") +message(STATUS "faustgen~ external") ## Create the Pure Data external set_pd_sources(${PROJECT_SOURCE_DIR}/pure-data/src/) set_pd_external_path("${PROJECT_SOURCE_DIR}/external/") -add_pd_external(faust_tilde_project faust~ ${PROJECT_SOURCE_DIR}/src/faust_tilde.c) +file(GLOB faustgen_tilde_sources +${PROJECT_SOURCE_DIR}/src/faustgen_tilde.c +${PROJECT_SOURCE_DIR}/src/faust_tilde_ui.h +${PROJECT_SOURCE_DIR}/src/faust_tilde_ui.c +${PROJECT_SOURCE_DIR}/src/faust_tilde_io.h +${PROJECT_SOURCE_DIR}/src/faust_tilde_io.c +${PROJECT_SOURCE_DIR}/src/faust_tilde_options.h +${PROJECT_SOURCE_DIR}/src/faust_tilde_options.c) +add_pd_external(faustgen_tilde_project faustgen~ "${faustgen_tilde_sources}") ## Link the Pure Data external with faustlib include_directories(${PROJECT_SOURCE_DIR}/faust/architecture) -add_dependencies(faust_tilde_project staticlib) -target_link_libraries(faust_tilde_project staticlib) +add_dependencies(faustgen_tilde_project staticlib) +target_link_libraries(faustgen_tilde_project staticlib) ## Link the Pure Data external with llvm find_package(LLVM REQUIRED CONFIG) @@ -50,11 +58,11 @@ add_definitions(${LLVM_DEFINITIONS}) include_directories(${LLVM_INCLUDE_DIRS}) llvm_map_components_to_libnames(llvm_libs all) list(REMOVE_ITEM llvm_libs LTO) -target_link_libraries(faust_tilde_project ${llvm_libs}) +target_link_libraries(faustgen_tilde_project ${llvm_libs}) if(WIN32) - target_link_libraries(faust_tilde_project ws2_32) + target_link_libraries(faustgen_tilde_project ws2_32) endif() if(MSVC) - set_property(TARGET faust_tilde_project APPEND_STRING PROPERTY LINK_FLAGS " /ignore:4099 ") + set_property(TARGET faustgen_tilde_project APPEND_STRING PROPERTY LINK_FLAGS " /ignore:4099 ") endif() diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100644 index 0000000..f52204a --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,16 @@ +v0.0.3 +- Change name from faust~ to faustgen~ +- Remove abstraction faust.watcher +- Add support for autocompile method +- Add support for passive parameter +- Add support for list of active parameters +- Add support for ui glue long names +- Add support for dynamic compile options +- Improve print method + +v0.0.2 +- Fix Linux dependencies +- Add abstraction faust.watcher + +v0.0.1 +- Integration of FAUST lib inside the faust~ external (Linux/MacOS/Windows) diff --git a/FaustDeken.bat b/FaustDeken.bat index 496c085..0792a8c 100644 --- a/FaustDeken.bat +++ b/FaustDeken.bat @@ -1,40 +1,40 @@ @echo off -title Deken manager for Faust~ for Pure Data +title Deken manager for faustgen~ for Pure Data set release_version=%1 -rmdir /S /Q faust~ +rmdir /S /Q faustgen~ del /F /S /Q /A *.dek del /F /S /Q /A *.dek.sha256 del /F /S /Q /A *.dek.txt -del /F /Q faust_tilde_darwin.zip -curl -L https://github.com/pierreguillot/faust-pd/releases/download/v%release_version%/faust_tilde-Darwin-amd64-32-sources.zip -o faust_tilde_darwin.zip -7z x faust_tilde_darwin.zip -deken package -v%release_version% faust~ -rmdir /S /Q faust~ -del /F /Q faust_tilde_darwin.zip +del /F /Q faustgen_tilde_darwin.zip +curl -L https://github.com/pierreguillot/faust-pd/releases/download/v%release_version%/faustgen_tilde-Darwin-amd64-32-sources.zip -o faustgen_tilde_darwin.zip +7z x faustgen_tilde_darwin.zip +deken package -v%release_version% faustgen~ +rmdir /S /Q faustgen~ +del /F /Q faustgen_tilde_darwin.zip -del /F /Q faust_tilde_linux.zip -curl -L https://github.com/pierreguillot/faust-pd/releases/download/v%release_version%/faust_tilde-Linux-amd64-32-sources.zip -o faust_tilde_linux.zip -7z x faust_tilde_linux.zip -deken package -v%release_version% faust~ -rmdir /S /Q faust~ -del /F /Q faust_tilde_linux.zip +del /F /Q faustgen_tilde_linux.zip +curl -L https://github.com/pierreguillot/faust-pd/releases/download/v%release_version%/faustgen_tilde-Linux-amd64-32-sources.zip -o faustgen_tilde_linux.zip +7z x faustgen_tilde_linux.zip +deken package -v%release_version% faustgen~ +rmdir /S /Q faustgen~ +del /F /Q faustgen_tilde_linux.zip -del /F /Q faust_tilde_windows.zip -curl -L https://github.com/pierreguillot/faust-pd/releases/download/v%release_version%/faust_tilde-Windows-amd64-32-sources.zip -o faust_tilde_windows.zip -7z x faust_tilde_windows.zip -deken package -v%release_version% faust~ -rmdir /S /Q faust~ -del /F /Q faust_tilde_windows.zip +del /F /Q faustgen_tilde_windows.zip +curl -L https://github.com/pierreguillot/faust-pd/releases/download/v%release_version%/faustgen_tilde-Windows-amd64-32-sources.zip -o faustgen_tilde_windows.zip +7z x faustgen_tilde_windows.zip +deken package -v%release_version% faustgen~ +rmdir /S /Q faustgen~ +del /F /Q faustgen_tilde_windows.zip -del /F /Q faust_tilde_archive.zip -curl -L https://github.com/pierreguillot/faust-pd/archive/v%release_version%.zip -o faust_tilde_archive.zip -7z x faust_tilde_archive.zip -rename faust-pd-%release_version% faust~ -deken package -v%release_version% faust~ -rmdir /S /Q faust~ -del /F /Q faust_tilde_archive.zip +del /F /Q faustgen_tilde_archive.zip +curl -L https://github.com/pierreguillot/faust-pd/archive/v%release_version%.zip -o faustgen_tilde_archive.zip +7z x faustgen_tilde_archive.zip +rename faust-pd-%release_version% faustgen~ +deken package -v%release_version% faustgen~ +rmdir /S /Q faustgen~ +del /F /Q faustgen_tilde_archive.zip -rem deken upload faust~[v%release_version%](Darwin-amd64-32)(Sources).dek faust~[v%release_version%](Linux-amd64-32)(Sources).dek faust~[v%release_version%](Windows-amd64-32)(Sources).dek faust~[v%release_version%](Sources).dek +rem deken upload faustgen~[v%release_version%](Darwin-amd64-32)(Sources).dek faustgen~[v%release_version%](Linux-amd64-32)(Sources).dek faustgen~[v%release_version%](Windows-amd64-32)(Sources).dek faustgen~[v%release_version%](Sources).dek pause diff --git a/FaustDeken.sh b/FaustDeken.sh index c09697a..1d1d7ce 100755 --- a/FaustDeken.sh +++ b/FaustDeken.sh @@ -1,39 +1,39 @@ #!/bin/bash -echo -e "title Deken manager for Faust~ for Pure Data" +echo -e "title Deken manager for faustgen~ for Pure Data" -rm -rf faust~ +rm -rf faustgen~ rm -f *.dek rm -f *.dek.sha256 rm -f *.dek.txt -rm -f faust_tilde_darwin.zip -curl -L "https://github.com/pierreguillot/faust-pd/releases/download/v$1/faust_tilde-Darwin-amd64-32-sources.zip" -o faust_tilde_darwin.zip -tar zxvf faust_tilde_darwin.zip -deken package -v$1 faust~ -rm -rf faust~ -rm -f faust_tilde_darwin.zip +rm -f faustgen_tilde_darwin.zip +curl -L "https://github.com/pierreguillot/faust-pd/releases/download/v$1/faustgen_tilde-Darwin-amd64-32-sources.zip" -o faustgen_tilde_darwin.zip +tar zxvf faustgen_tilde_darwin.zip +deken package -v$1 faustgen~ +rm -rf faustgen~ +rm -f faustgen_tilde_darwin.zip -rm -f faust_tilde_linux.zip -curl -L "https://github.com/pierreguillot/faust-pd/releases/download/v$1/faust_tilde-Linux-amd64-32-sources.zip" -o faust_tilde_linux.zip -tar zxvf faust_tilde_linux.zip -deken package -v$1 faust~ -rm -rf faust~ -rm -f faust_tilde_linux.zip +rm -f faustgen_tilde_linux.zip +curl -L "https://github.com/pierreguillot/faust-pd/releases/download/v$1/faustgen_tilde-Linux-amd64-32-sources.zip" -o faustgen_tilde_linux.zip +tar zxvf faustgen_tilde_linux.zip +deken package -v$1 faustgen~ +rm -rf faustgen~ +rm -f faustgen_tilde_linux.zip -rm -f faust_tilde_windows.zip -curl -L "https://github.com/pierreguillot/faust-pd/releases/download/v$1/faust_tilde-Windows-amd64-32-sources.zip" -o faust_tilde_windows.zip -tar zxvf faust_tilde_windows.zip -deken package -v$1 faust~ -rm -rf faust~ -rm -f faust_tilde_windows.zip +rm -f faustgen_tilde_windows.zip +curl -L "https://github.com/pierreguillot/faust-pd/releases/download/v$1/faustgen_tilde-Windows-amd64-32-sources.zip" -o faustgen_tilde_windows.zip +tar zxvf faustgen_tilde_windows.zip +deken package -v$1 faustgen~ +rm -rf faustgen~ +rm -f faustgen_tilde_windows.zip -rm -f faust_tilde_archive.zip -curl -L "https://github.com/pierreguillot/faust-pd/archive/v$1.zip" -o faust_tilde_archive.zip -tar zxvf faust_tilde_archive.zip -mv faust-pd-$1 faust~ -deken package -v$1 faust~ -rm -rf faust~ -rm -f faust_tilde_archive.zip +rm -f faustgen_tilde_archive.zip +curl -L "https://github.com/pierreguillot/faust-pd/archive/v$1.zip" -o faustgen_tilde_archive.zip +tar zxvf faustgen_tilde_archive.zip +mv faust-pd-$1 faustgen~ +deken package -v$1 faustgen~ +rm -rf faustgen~ +rm -f faustgen_tilde_archive.zip -# deken upload faust~[v%release_version%](Darwin-amd64-32)(Sources).dek faust~[v%release_version%](Linux-amd64-32)(Sources).dek faust~[v%release_version%](Windows-amd64-32)(Sources).dek faust~[v%release_version%](Sources).dek +# deken upload faustgen~[v%release_version%](Darwin-amd64-32)(Sources).dek faustgen~[v%release_version%](Linux-amd64-32)(Sources).dek faustgen~[v%release_version%](Windows-amd64-32)(Sources).dek faustgen~[v%release_version%](Sources).dek diff --git a/FaustLib.cmake b/FaustLib.cmake index 1927961..b59f20e 100644 --- a/FaustLib.cmake +++ b/FaustLib.cmake @@ -41,7 +41,7 @@ set(WASM_BACKEND OFF CACHE STRING "Include WASM ba add_subdirectory(./faust/build EXCLUDE_FROM_ALL) if(MSVC) - set_property(TARGET staticlib APPEND_STRING PROPERTY COMPILE_FLAGS " /EHsc /D WIN32 -D_SCL_SECURE_NO_WARNINGS ") + set_property(TARGET staticlib APPEND_STRING PROPERTY COMPILE_FLAGS " /EHsc /D WIN32 -D_SCL_SECURE_NO_WARNINGS") set_property(TARGET staticlib APPEND_STRING PROPERTY LINK_FLAGS " /ignore:4099 ") endif() diff --git a/README.md b/README.md index 2bfb0b3..e2147c6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- faust~ + faustgen~

The FAUST compiler embedded in a Pd external @@ -15,7 +15,7 @@ ## Presentation -The **faust~** object is an external with the [FAUST](http://faust.grame.fr/about/) just-in-time (JIT) compiler embedded that allows to load, compile and play FAUST files within the audio programming environment [Pure Data](http://msp.ucsd.edu/software.html). FAUST (Functional Audio Stream) is a functional programming language specifically designed for real-time signal processing and synthesis developed by the [GRAME](http://www.grame.fr/). The FAUST JIT compiler - built with [LLVM](https://llvm.org/) - brings together the convenience of a standalone interpreted language with the efficiency of a compiled language. The **faust~** object is a very first version with elementary features, any help and any contribution are welcome. +The **faustgen~** object is an external with the [FAUST](http://faust.grame.fr/about/) just-in-time (JIT) compiler embedded that allows to load, compile and play FAUST files within the audio programming environment [Pure Data](http://msp.ucsd.edu/software.html). FAUST (Functional Audio Stream) is a functional programming language specifically designed for real-time signal processing and synthesis developed by the [GRAME](http://www.grame.fr/). The FAUST JIT compiler - built with [LLVM](https://llvm.org/) - brings together the convenience of a standalone interpreted language with the efficiency of a compiled language. The **faustgen~** object is a very first version with elementary features, any help and any contribution are welcome. **Dependencies:** @@ -77,12 +77,12 @@ Once the binaries are compiled or uploaded with Travis and Appveyor to the relea **FAUST website**: faust.grame.fr **FAUST developers**: Yann Orlarey, Stéphane Letz, Dominique Fober and others -**faust~ institutions**: CICM - ANR MUSICOLL -**fauts~ website**: github.com/grame-cncm/faust-pd -**faust~ developer**: Pierre Guillot +**faustgen~ institutions**: CICM - ANR MUSICOLL +**faustgen~ website**: github.com/grame-cncm/faust-pd +**faustgen~ developer**: Pierre Guillot ## Legacy -This **faust~** object for Pd is inspired by the **faustgen~** object for Max developed by Martin Di Rollo and Stéphane Letz. +This **faustgen~** object for Pd is inspired by the **faustgen~** object for Max developed by Martin Di Rollo and Stéphane Letz. Another **faust~** object has been developed by Albert Graef using the programming language [Pure](https://github.com/agraef/pure-lang). diff --git a/ToDoList.md b/ToDoList.md new file mode 100644 index 0000000..f3ccf75 --- /dev/null +++ b/ToDoList.md @@ -0,0 +1,4 @@ +- Mesure DSP time of the code +- Use automatic optimizations with compile options +- Check if the DSP process is in-place +- Check why -double option crashes diff --git a/appveyor.yml b/appveyor.yml index 6dc8df2..73e3c02 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,7 +23,7 @@ install: build_script: - mkdir build%llvmplateform% && cd build%llvmplateform% - cmake .. -G "%compiler%" -DUSE_LLVM_CONFIG=off -DLLVM_DIR=./llvm-windows-%llvmplateform%-%llvmpconfig%/lib/cmake/llvm - - msbuild faust~.sln /nologo /p:config=%configuration% /p:plateform=%platform% + - msbuild faustgen~.sln /nologo /p:config=%configuration% /p:plateform=%platform% after_build: - cd %APPVEYOR_BUILD_FOLDER% - del /F /Q llvm.zip @@ -31,12 +31,12 @@ after_build: - del /F /S /Q /A external\*.ilk - del /F /S /Q /A external\*.lib - del /F /S /Q /A external\*.exp - - copy src\faust_tilde.c external\faust_tilde.c + - copy src\faustgen_tilde.c external\faustgen_tilde.c - copy README.md external\README.md - copy LICENSE external\LICENSE.txt - xcopy /S /E /Y /I .\faust\libraries .\external\libs - - rename external faust~ - - 7z a "faust_tilde-%release_arch%-sources.zip" faust~ + - rename external faustgen~ + - 7z a "faustgen_tilde-%release_arch%-sources.zip" faustgen~ artifacts: - path: '*.zip' diff --git a/external/examples/dummy.dsp b/external/examples/dummy.dsp new file mode 100644 index 0000000..d5fed73 --- /dev/null +++ b/external/examples/dummy.dsp @@ -0,0 +1,6 @@ +declare name "Dummy"; +declare version "1.0"; +declare author "Heu... me..."; + + +process = _, _, _, _ :> _, _; diff --git a/external/examples/gain.dsp b/external/examples/gain.dsp new file mode 100644 index 0000000..90fb692 --- /dev/null +++ b/external/examples/gain.dsp @@ -0,0 +1,7 @@ +import("stdfaust.lib"); + +process = _ * (gain) +with +{ + gain = vslider("gain [unit:linear]", 0,0,1,0.001); +}; diff --git a/external/examples/mixer.dsp b/external/examples/mixer.dsp new file mode 100644 index 0000000..e0b8854 --- /dev/null +++ b/external/examples/mixer.dsp @@ -0,0 +1,7 @@ +declare name "mixer"; +declare version "1.0"; +declare author "Grame"; +declare license "BSD"; +declare copyright "(c)GRAME 2006"; + +process = _; diff --git a/external/examples/resonator.dsp b/external/examples/resonator.dsp new file mode 100644 index 0000000..5ec6e8e --- /dev/null +++ b/external/examples/resonator.dsp @@ -0,0 +1,11 @@ +import("stdfaust.lib"); + +// Example programmed by Christophe Lebreton - GRAME + +f(i) = hslider("freq%3i", 160.,-0.,20000.,0.001); +r(i) = hslider("decay%3i", 0.,0.,1.,0.001):((pow(4.78)*6)+0.0001):ba.tau2pole; +g(i) = hslider("gain%3i", 0.,0.,1.,0.0001); + +resonator(n) = _<:par(i,n,*(g(i)):fi.nlf2(f(i),r(i)):_,!:*(ba.db2linear((100*(log(1/r(i))))))):>*(0.003162); + +process = resonator(20) ; diff --git a/external/faust.watcher-help.pd b/external/faust.watcher-help.pd deleted file mode 100644 index 0def173..0000000 --- a/external/faust.watcher-help.pd +++ /dev/null @@ -1,43 +0,0 @@ -#N canvas 436 64 481 520 10; -#X obj 12 15 cnv 15 360 17 empty empty faust.watcher 2 9 0 14 -233017 --66577 0; -#X obj 180 122 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 -1; -#X obj 45 80 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 -; -#X msg 45 172 reload; -#X text 67 79 Start/Stop watching; -#X text 198 122 Errors; -#X obj 46 225 dac~; -#X obj 45 204 faust~ noise; -#X obj 45 101 faust.watcher noise 100; -#X text 51 130 Bang when file has changed, f 17; -#X text 94 169 Recompile the code when the file changed, f 22; -#X text 9 36 The first argument is the name of the FAUST DSP file to -watch. The second optional argument is the time in ms between each -file check.; -#X text 16 252 The abstraction sends a notification each time the FAUST -DSP file is saved (modified). Activates the watching when coding your -FAUST code in your favorite text editor to recompile automatically -the code.; -#X text 17 410 The abstraction uses the ggee library developed by Guenter -Geiger. If you don't have the ggee library installed \, use Deken to -download it.; -#X text 17 460 This notification system has been inspired by the approach -offered by the FAUST implementation for Pure Data developed by Albert -Graef : https://github.com/agraef/pure-lang., f 69; -#X text 168 16 a notifier of FAUST file changes; -#X text 16 311 FAUST institution: GRAME; -#X text 16 325 FAUST website: faust.grame.fr; -#X text 122 340 Yann Orlarey \, Stéphane Letz \, Dominique Fober \, -...; -#X text 16 339 FAUST developers:; -#X text 16 387 faust~ developer: Pierre Guillot; -#X text 16 359 faust~ institutions: CICM - ANR MUSICOLL; -#X text 16 373 fauts~ website: github.com/grame-cncm/faust-pd; -#X connect 2 0 8 0; -#X connect 3 0 7 0; -#X connect 7 0 6 0; -#X connect 7 0 6 1; -#X connect 8 0 3 0; -#X connect 8 1 1 0; diff --git a/external/faust.watcher.pd b/external/faust.watcher.pd deleted file mode 100644 index a4628f1..0000000 --- a/external/faust.watcher.pd +++ /dev/null @@ -1,47 +0,0 @@ -#N canvas 223 281 425 443 10; -#X obj 147 16 loadbang; -#X obj 174 128 makefilename %s/%%s.dsp; -#X msg 174 149 set \$1; -#X obj 174 170 makefilename; -#X obj 243 255 outlet; -#X obj 147 57 t b b; -#X obj 147 83 symbol \$1; -#X obj 21 8 inlet; -#X obj 147 36 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 --1; -#X msg 174 213 date -r \$1 +s%Y.%S.%m.%d.%H.%M.%S; -#X obj 174 276 t s s; -#X obj 174 255 symbol; -#X obj 174 191 symbol; -#X obj 201 350 outlet; -#X obj 201 328 bang; -#X obj 174 306 sel s; -#X obj 174 107 ggee/getdir 1; -#X obj 174 234 ggee/shell, f 12; -#X obj 45 28 loadbang; -#X obj 45 49 f \$2; -#X obj 45 70 sel 0; -#X obj 21 93 metro 100; -#X connect 0 0 8 0; -#X connect 1 0 2 0; -#X connect 2 0 3 0; -#X connect 3 0 12 0; -#X connect 5 0 6 0; -#X connect 5 1 16 0; -#X connect 6 0 3 0; -#X connect 7 0 21 0; -#X connect 8 0 5 0; -#X connect 9 0 17 0; -#X connect 10 0 15 1; -#X connect 10 1 15 0; -#X connect 11 0 10 0; -#X connect 12 0 9 0; -#X connect 14 0 13 0; -#X connect 15 1 14 0; -#X connect 16 0 1 0; -#X connect 17 0 11 0; -#X connect 17 1 4 0; -#X connect 18 0 19 0; -#X connect 19 0 20 0; -#X connect 20 1 21 1; -#X connect 21 0 12 0; diff --git a/external/faustgen~-help.pd b/external/faustgen~-help.pd new file mode 100644 index 0000000..b9b35a2 --- /dev/null +++ b/external/faustgen~-help.pd @@ -0,0 +1,182 @@ +#N canvas 428 137 481 548 10; +#X obj 12 15 cnv 15 360 17 empty empty faustgen~ 2 9 0 14 -233017 -66577 +0; +#X obj 286 115 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X msg 286 135 \; pd dsp \$1; +#X obj 32 308 dac~ 1 2; +#X obj 62 192 nbx 5 14 0 1 0 0 empty empty empty 0 -8 0 10 -262144 +-1 -1 0 256; +#X obj 62 149 loadbang; +#X msg 62 171 0; +#X text 10 36 The first argument is the name of the file FAUST DSP +file to read. The path is relative to the patch. Extra arguments can +be used to define compilation options \, see the FAUST documentation +for further information. Use the debug level 3 to displays information +about the code in the Pd console.; +#X text 26 351 FAUST institution: GRAME; +#X text 26 365 FAUST website: faust.grame.fr; +#X text 132 380 Yann Orlarey \, Stéphane Letz \, Dominique Fober \, +...; +#X text 26 379 FAUST developers:; +#X text 26 449 This object is inspired by faustgen~ for Max developed +by Martin Di Rollo and Stéphane Letz., f 50; +#X text 95 16 the FAUST compiler embedded in a Pd external; +#X text 26 479 Another faust~ object has been developed by Albert Graef +using the programming language "Pure" : https://github.com/agraef/pure-lang. +, f 67; +#X text 125 189 Control the parameters with their names, f 15; +#X text 26 399 faustgen~ institutions: CICM - ANR MUSICOLL; +#X text 26 427 faustgen~ developer: Pierre Guillot; +#X msg 62 211 gain \$1; +#X obj 32 118 osc~ 220; +#N canvas 766 136 471 246 options 0; +#X text 16 70 Change the compile options and recompile; +#X msg 17 91 compileoptions -vec -vs 64; +#X text 56 141 Use the compile options as default arguments; +#X text 19 196 All the compile options are listed page 54 and page +55 of the PDF file faust-quick-reference, f 46; +#X text 21 27 Use the compile options to optimize the CPU or improve +the redering, f 55; +#X msg 41 115 print; +#X text 84 116 Print faustgen~ informations; +#X obj 405 65 switch~; +#X obj 405 43 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 17 165 faustgen~ examples/gain -vec -lv 1; +#X connect 1 0 9 0; +#X connect 5 0 9 0; +#X connect 8 0 7 0; +#X restore 287 185 pd options; +#N canvas 287 129 524 202 recompilation 0; +#X obj 17 75 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1 +; +#X msg 17 134 autocompile \$1 100; +#X obj 17 166 faustgen~ examples/dummy; +#X text 14 11 The automatic compilation can be used during the Faust +code edition to recompile the code each time the file has been modified. +; +#X text 50 62 Active/deactivate the autocompilation when the dsp file +changed., f 37; +#X text 50 92 The second argument is the time between each check., +f 37; +#X msg 155 134 compile; +#X text 214 128 Reload and recompile the FAUST file manually, f 23 +; +#X obj 339 90 switch~; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 6 0 2 0; +#X restore 287 214 pd recompilation; +#N canvas 575 109 646 630 control 0; +#X obj 30 598 dac~ 1 2; +#X msg 45 195 print; +#N canvas 0 22 450 278 (subpatch) 0; +#X array \$0-gains 20 float 3; +#A 0 0.706521 0.597826 0.521739 0.521739 0.521739 0.378572 0.442858 +0.528573 0.621431 0.685717 0.792861 0.921433 0.950004 0.950004 0.950004 +0.871432 0.792861 0.607145 0.578574 0.3; +#X coords 0 1 20 0 199 92 1 0 0; +#X restore 397 74 graph; +#N canvas 0 22 450 278 (subpatch) 0; +#X array \$0-decays 20 float 3; +#A 0 0.0652173 0.0978258 0.119565 0.152173 0.206521 0.260868 0.326085 +0.402172 0.456519 0.521736 0.65217 0.706518 0.771735 0.804344 0.804344 +0.804344 0.771735 0.749996 0.66304 0.608692; +#X coords 0 1 20 0 199 92 1 0 0; +#X restore 397 198 graph; +#N canvas 0 22 450 278 (subpatch) 0; +#X array \$0-freq 20 float 3; +#A 0 0.0652173 6956.52 6956.52 8260.87 9347.82 10434.8 11956.5 13478.2 +15000 16521.7 17608.7 18478.2 19130.4 18913 18260.8 14782.6 11304.3 +9347.82 8695.65 0.608692; +#X coords 0 20000 20 0 199 92 1 0 0; +#X restore 397 328 graph; +#X obj 30 107 noise~; +#X obj 30 525 faustgen~ examples/resonator; +#X obj 119 177 list trim; +#X obj 119 155 list prepend gain 0; +#X obj 119 133 array get \$0-gains; +#X obj 119 112 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X text 17 13 Use lists of values to control the lists of parameters. +The first element of the list must be the name of the parameter \, +the second argument is the index of the first parameters the other +arguments are the list., f 44; +#X obj 139 291 list trim; +#X obj 139 227 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X obj 139 248 array get \$0-decays 2 4; +#X obj 139 270 list prepend decay 2; +#X text 44 145 Print to display the parameters' information, f 11 +; +#X obj 203 320 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X msg 203 362 freq 4 \$1; +#X obj 203 341 array get \$0-decays 3 1; +#X text 395 10 Change the value of the arrays and use the bangs to +send them to the faustgen~ object, f 33; +#X text 116 84 Set the values of all the "gain" parameters, f 23; +#X text 137 199 Set the values of 4 "decay" parameters starting with +the index 2, f 36; +#X text 201 292 Set the value of the 3rd "freq" parameter, f 23; +#X obj 201 481 list trim; +#X obj 201 417 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 +-1 -1; +#X obj 256 416 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 +-262144 -1 -1 0 256; +#X obj 312 416 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 +-262144 -1 -1 0 256; +#X obj 201 438 array get \$0-decays; +#X obj 201 460 list prepend decay 0; +#X text 199 388 Dynamic approach, f 9; +#X text 254 398 Index; +#X text 312 398 Size; +#X obj 303 107 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X text 301 86 Turn DSP on; +#X obj 303 128 switch~; +#X connect 1 0 6 0; +#X connect 5 0 6 0; +#X connect 6 0 0 0; +#X connect 6 0 0 1; +#X connect 7 0 6 0; +#X connect 8 0 7 0; +#X connect 9 0 8 0; +#X connect 10 0 9 0; +#X connect 12 0 6 0; +#X connect 13 0 14 0; +#X connect 14 0 15 0; +#X connect 15 0 12 0; +#X connect 17 0 19 0; +#X connect 18 0 6 0; +#X connect 19 0 18 0; +#X connect 24 0 6 0; +#X connect 25 0 28 0; +#X connect 26 0 28 1; +#X connect 26 0 29 1; +#X connect 27 0 28 2; +#X connect 28 0 29 0; +#X connect 29 0 24 0; +#X connect 33 0 35 0; +#X restore 287 243 pd control lists; +#X obj 103 305 snapshot~; +#X obj 103 326 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -8 0 10 +-262144 -1 -1 0 256; +#X obj 103 284 metro 100; +#X obj 103 264 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 +1; +#X obj 31 242 faustgen~ examples/gain; +#X text 26 413 faustgen~ website: github.com/CICM/faust-pd; +#X connect 1 0 2 0; +#X connect 4 0 18 0; +#X connect 5 0 6 0; +#X connect 6 0 4 0; +#X connect 18 0 27 0; +#X connect 19 0 27 0; +#X connect 23 0 24 0; +#X connect 25 0 23 0; +#X connect 26 0 25 0; +#X connect 27 0 3 0; +#X connect 27 0 3 1; +#X connect 27 0 23 0; diff --git a/external/faust~-help.pd b/external/faust~-help.pd deleted file mode 100644 index 7b2479d..0000000 --- a/external/faust~-help.pd +++ /dev/null @@ -1,46 +0,0 @@ -#N canvas 364 281 470 537 10; -#X obj 12 15 cnv 15 360 17 empty empty faust~ 2 9 0 14 -233017 -66577 -0; -#X obj 286 155 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 -1; -#X msg 286 175 \; pd dsp \$1; -#X obj 32 308 dac~ 1 2; -#X obj 32 255 faust~ noise; -#X msg 62 208 reload; -#X obj 32 158 nbx 5 14 0 1 0 0 empty empty empty 0 -8 0 10 -262144 --1 -1 0 256; -#X msg 32 177 Volume \$1; -#X obj 32 116 loadbang; -#X msg 32 137 0; -#X text 10 36 The first argument is the name of the file FAUST DSP -file to read. The path is relative to the patch. Extra arguments can -be used to define compilation options \, see the FAUST documentation -for further information. Use the debug level 3 to displays information -about the code in the Pd console.; -#X obj 192 305 faust~ noise -vs 64 -vec; -#X text 26 341 FAUST institution: GRAME; -#X text 26 355 FAUST website: faust.grame.fr; -#X text 132 370 Yann Orlarey \, Stéphane Letz \, Dominique Fober \, -...; -#X text 26 369 FAUST developers:; -#X text 26 417 faust~ developer: Pierre Guillot; -#X text 26 439 This object is inspired by faustgen~ for Max developed -by Martin Di Rollo and Stéphane Letz., f 50; -#X text 26 389 faust~ institutions: CICM - ANR MUSICOLL; -#X text 192 256 Use compilation options. See the FAUST documentation -for further information, f 24; -#X text 95 16 the FAUST compiler embedded in a Pd external; -#X text 26 403 fauts~ website: github.com/grame-cncm/faust-pd; -#X text 26 469 Another faust~ object has been developed by Albert Graef -using the programming language "Pure" : https://github.com/agraef/pure-lang. -, f 67; -#X text 95 155 Control the parameters with their names, f 15; -#X text 113 206 Reload the FAUST file; -#X connect 1 0 2 0; -#X connect 4 0 3 0; -#X connect 4 0 3 1; -#X connect 5 0 4 0; -#X connect 6 0 7 0; -#X connect 7 0 4 0; -#X connect 8 0 9 0; -#X connect 9 0 6 0; diff --git a/external/noise.dsp b/external/noise.dsp deleted file mode 100644 index 8544f4a..0000000 --- a/external/noise.dsp +++ /dev/null @@ -1,52 +0,0 @@ -// WARNING: This a "legacy example based on a deprecated library". Check noises.lib -// for more accurate examples of noise functions - -declare name "Noise"; -declare version "1.1"; -declare author "Grame"; -declare license "BSD"; -declare copyright "(c)GRAME 2009"; - -//----------------------------------------------------------------- -// Noise generator and demo file for the Faust math documentation -//----------------------------------------------------------------- - - -\section{Presentation of the "noise.dsp" Faust program} -This program describes a white noise generator with an interactive volume, using a random function. - -\subsection{The random function} -The \texttt{random} function describes a generator of random numbers, which equation follows. You should notice hereby the use of an integer arithmetic on 32 bits, relying on integer wrapping for big numbers. -random - -\subsection{The noise function} -The white noise then corresponds to: -noise - - -random = +(12345)~*(1103515245); -noise = random/2147483647.0; - - -\subsection{Just add a user interface element to play volume!} -Endly, the sound level of this program is controlled by a user slider, which gives the following equation: -process - - - -\section{Block-diagram schema of process} -This process is illustrated on figure 1. -process - - -process = noise * vslider("Volume[style:knob][acc: 0 0 -10 0 10]", 0.5, 0, 1, 0.1); - - -\section{Notice of this documentation} -You might be careful of certain information and naming conventions used in this documentation: - - -\section{Listing of the input code} -The following listing shows the input Faust code, parsed to compile this mathematical documentation. -

- diff --git a/faust b/faust index 3b7e311..2b54fef 160000 --- a/faust +++ b/faust @@ -1 +1 @@ -Subproject commit 3b7e311c6a25f55ffc9ec282ecb746618a344855 +Subproject commit 2b54fef899f84c31e0874fd19292f787bb7b4b19 diff --git a/pd.build b/pd.build index 5365682..ed7591e 160000 --- a/pd.build +++ b/pd.build @@ -1 +1 @@ -Subproject commit 53656824ee7977f0084a801208effe20e640c8f5 +Subproject commit ed7591eecb239970158bd2fa2550b63280a16e2d diff --git a/pure-data b/pure-data index f83c88b..f9b0ad8 160000 --- a/pure-data +++ b/pure-data @@ -1 +1 @@ -Subproject commit f83c88ba7ac68368248797ef0d0febc3526432bb +Subproject commit f9b0ad81387d4af3091857dc16852e221fe96310 diff --git a/src/faust_tilde.c b/src/faust_tilde.c deleted file mode 100644 index 66687d6..0000000 --- a/src/faust_tilde.c +++ /dev/null @@ -1,809 +0,0 @@ -/* -// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. -// For information on usage and redistribution, and for a DISCLAIMER OF ALL -// WARRANTIES, see the file, "LICENSE.txt," in this distribution. -*/ - -#include - -#include -#include - -#include - -#define MAXFAUSTSTRING 4096 -#define MAXFAUSTOPTIONS 128 - -typedef struct _faust_param -{ - t_symbol* p_label; - int p_type; - FAUSTFLOAT* p_zone; - FAUSTFLOAT p_min; - FAUSTFLOAT p_max; - FAUSTFLOAT p_step; - FAUSTFLOAT p_saved; -}t_faust_param; - -typedef struct _faust_tilde -{ - t_object f_obj; - llvm_dsp_factory* f_dsp_factory; - llvm_dsp* f_dsp_instance; - size_t f_nsignals; - t_sample** f_signals; - t_float f_f; - - MetaGlue f_meta_glue; - UIGlue f_ui_glue; - size_t f_nparams; - t_faust_param* f_params; - - t_canvas* f_canvas; - t_symbol* f_dsp_name; - - size_t f_ncompile_options; - char* f_compile_options[MAXFAUSTOPTIONS]; - - size_t f_ninlets; - t_inlet** f_inlets; - size_t f_noutlets; - t_outlet** f_outlets; - char f_allocated; -} t_faust_tilde; - -static t_class *faust_tilde_class; - -////////////////////////////////////////////////////////////////////////////////////////////////// -// PURE DATA IO DYNAMIC // -////////////////////////////////////////////////////////////////////////////////////////////////// -static void faust_tilde_free_ioputs(t_faust_tilde *x) -{ - if(x->f_inlets) - { - freebytes(x->f_inlets, sizeof(t_inlet*) * x->f_ninlets); - x->f_inlets = NULL; - x->f_ninlets = 0; - } - if(x->f_outlets) - { - freebytes(x->f_outlets, sizeof(t_outlet*) * x->f_noutlets); - x->f_outlets = NULL; - x->f_noutlets = 0; - } - if(x->f_signals) - { - freebytes(x->f_signals, sizeof(t_sample*) * x->f_nsignals); - x->f_signals = NULL; - x->f_nsignals = 0; - } -} - -static char faust_tilde_resize_inputs(t_faust_tilde *x, int const nins) -{ - t_inlet** ninlets; - size_t i; - size_t const cins = x->f_ninlets > 1 ? x->f_ninlets : 1; - size_t const rnins = (size_t)nins > 1 ? (size_t)nins : 1; - if(rnins == cins) - { - return 0; - } - for(i = rnins; i < cins; ++i) - { - inlet_free(x->f_inlets[i]); - x->f_inlets[i] = NULL; - } - ninlets = (t_inlet **)resizebytes(x->f_inlets, sizeof(t_inlet*) * cins, sizeof(t_inlet*) * rnins); - if(ninlets) - { - for(i = cins; i < rnins; ++i) - { - ninlets[i] = signalinlet_new((t_object *)x, 0); - } - x->f_inlets = ninlets; - x->f_ninlets = rnins; - return 0; - } - pd_error(x, "faust~: memory allocation failed - inputs"); - return 1; -} - -static char faust_tilde_resize_outputs(t_faust_tilde *x, int const nins) -{ - t_outlet** noutlets; - size_t i; - size_t const couts = x->f_noutlets; - size_t const rnouts = (size_t)nins > 0 ? (size_t)nins : 0; - if(rnouts == couts) - { - return 0; - } - for(i = rnouts; i < couts; ++i) - { - outlet_free(x->f_outlets[i]); - x->f_outlets[i] = NULL; - } - noutlets = (t_outlet **)resizebytes(x->f_outlets, sizeof(t_outlet*) * couts, sizeof(t_outlet*) * rnouts); - if(noutlets) - { - for(i = couts; i < rnouts; ++i) - { - noutlets[i] = outlet_new((t_object *)x, &s_signal); - } - x->f_outlets = noutlets; - x->f_noutlets = rnouts; - return 0; - } - pd_error(x, "faust~: memory allocation failed - outputs"); - return 1; -} - -static char faust_tilde_resize_ioputs(t_faust_tilde *x, int const nins, int const nouts) -{ - char valid = 0; - t_sample** nsignals; - int const redraw = (x->f_canvas && glist_isvisible(x->f_canvas) && (!x->f_canvas->gl_isdeleting) - && glist_istoplevel(x->f_canvas) && x->f_allocated); - if(redraw) - { - gobj_vis((t_gobj *)x, x->f_canvas, 0); - } - valid = faust_tilde_resize_inputs(x, nins) ? 1 : valid; - valid = faust_tilde_resize_outputs(x, nouts) ? 1 : valid; - nsignals = (t_sample **)resizebytes(x->f_signals, - x->f_nsignals * sizeof(t_sample *), - (x->f_noutlets + x->f_ninlets) * sizeof(t_sample *)); - - if(nsignals) - { - x->f_nsignals = x->f_noutlets + x->f_ninlets; - x->f_signals = nsignals; - } - else - { - pd_error(x, "faust~: memory allocation failed - signals"); - valid = 1; - } - if(redraw) - { - gobj_vis((t_gobj *)x, x->f_canvas, 1); - canvas_fixlinesfor(x->f_canvas, (t_text *)x); - } - return valid; -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// FILE LOCALIZATION // -////////////////////////////////////////////////////////////////////////////////////////////////// - -static char* faust_tilde_get_dsp_file_path(t_faust_tilde *x) -{ - if(x->f_canvas) - { - t_symbol const* name = x->f_dsp_name; - t_symbol const* path = canvas_getdir(x->f_canvas); - if(path && path->s_name && name && name->s_name) - { - char* file = (char *)calloc(MAXFAUSTSTRING, sizeof(char)); - if(file) - { - sprintf(file, "%s/%s.dsp", path->s_name, name->s_name); - return file; - } - else - { - pd_error(x, "faust~: memory allocation failed"); - } - } - else - { - pd_error(x, "faust~: invalid canvas directory or DSP file name"); - } - } - else - { - pd_error(x, "faust~: invalid canvas"); - } - return NULL; -} - -static char* faust_tilde_get_default_include_path(t_faust_tilde *x) -{ - char const* path = class_gethelpdir(faust_tilde_class); - if(path) - { - char* include_path = (char *)calloc(MAXFAUSTSTRING, sizeof(char)); - if(include_path) - { - sprintf(include_path, "%s/libs/", path); - return include_path; - } - else - { - pd_error(x, "faust~: memory allocation failed - include path"); - } - } - else - { - pd_error(x, "faust~: cannot locate the include path"); - } - return NULL; -} - -static int faust_tilde_parse_compile_options(t_faust_tilde *x, int argc, t_atom* argv) -{ - int i = 0; - char has_include = 0; - for(i = 0; i < argc && i < MAXFAUSTOPTIONS; ++i) - { - x->f_compile_options[i] = (char *)calloc(MAXFAUSTSTRING, sizeof(char)); - if(x->f_compile_options[i]) - { - if(argv[i].a_type == A_FLOAT) - { - sprintf(x->f_compile_options[i], "%i", (int)argv[i].a_w.w_float); - } - else if(argv[i].a_type == A_SYMBOL && argv[i].a_w.w_symbol) - { - sprintf(x->f_compile_options[i], "%s", argv[i].a_w.w_symbol->s_name); - if(!strncmp(x->f_compile_options[i], "-I", 2)) - { - has_include = 1; - } - } - else - { - pd_error(x, "faust~: option type invalid"); - memset(x->f_compile_options[i], 0, MAXFAUSTSTRING); - } - x->f_ncompile_options = i+1; - } - else - { - pd_error(x, "faust~: memory allocation failed - compile option"); - x->f_ncompile_options = i; - return -1; - } - } - if(!has_include) - { - x->f_compile_options[i] = (char *)calloc(MAXFAUSTSTRING, sizeof(char)); - if(x->f_compile_options[i]) - { - sprintf(x->f_compile_options[i], "%s", "-I"); - } - else - { - pd_error(x, "faust~: memory allocation failed - compile option"); - x->f_ncompile_options = i; - return -1; - } - ++i; - x->f_compile_options[i] = faust_tilde_get_default_include_path(x); - if(!x->f_compile_options[i]) - { - pd_error(x, "faust~: memory allocation failed - compile option"); - x->f_ncompile_options = i; - return -1; - } - x->f_ncompile_options = i+1; - } - return 0; -} - -static void faust_tilde_free_compile_options(t_faust_tilde *x) -{ - if(x->f_compile_options) - { - size_t i; - for(i = 0; i < x->f_ncompile_options; ++i) - { - if(x->f_compile_options[i]) - { - free(x->f_compile_options[i]); - } - } - } -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// FAUST INTERFACE // -////////////////////////////////////////////////////////////////////////////////////////////////// - -static void faust_tilde_delete_instance(t_faust_tilde *x) -{ - if(x->f_dsp_instance) - { - deleteCDSPInstance(x->f_dsp_instance); - x->f_dsp_instance = NULL; - } -} - -static void faust_tilde_delete_factory(t_faust_tilde *x) -{ - if(x->f_dsp_factory) - { - faust_tilde_delete_instance(x); - deleteCDSPFactory(x->f_dsp_factory); - x->f_dsp_factory = NULL; - } -} - -static void faust_tilde_ui_open_tab_box(t_faust_tilde* x, const char* label) -{ - //pd_error(x, "faust~: open tab box not supported yet (%s)", label); -} - -static void faust_tilde_ui_open_horizontal_box(t_faust_tilde* x, const char* label) -{ - //pd_error(x, "faust~: open horizontal box not supported yet (%s)", label); -} - -static void faust_tilde_ui_open_vertical_box(t_faust_tilde* x, const char* label) -{ - //pd_error(x, "faust~: open vertical box not supported yet (%s)", label); -} - -static void faust_tilde_ui_close_box(t_faust_tilde* x) -{ - //pd_error(x, "faust~: close box not supported yet"); -} - - - -static void faust_tilde_delete_params(t_faust_tilde *x) -{ - if(x->f_params) - { - freebytes(x->f_params, x->f_nparams * sizeof(t_faust_param)); - x->f_params = NULL; - x->f_nparams = 0; - } -} - -static void faust_tilde_save_params(t_faust_tilde *x) -{ - size_t i; - for(i = 0; i < x->f_nparams; ++i) - { - x->f_params[i].p_saved = *x->f_params[i].p_zone; - } -} - -static void faust_tilde_restore_params(t_faust_tilde *x) -{ - size_t i; - for(i = 0; i < x->f_nparams; ++i) - { - *x->f_params[i].p_zone = x->f_params[i].p_saved; - } -} - -static void faust_tilde_add_params(t_faust_tilde *x, const char* label, int const type, FAUSTFLOAT* zone, - FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) -{ - t_faust_param *newmemory; - size_t size = x->f_nparams; - if(x->f_params) - { - newmemory = (t_faust_param *)resizebytes(x->f_params, size * sizeof(t_faust_param), (size + 1) * sizeof(t_faust_param)); - if(!newmemory) - { - pd_error(x, "faust~: memory allocation failed - parameter"); - return; - } - } - else - { - newmemory = (t_faust_param *)getbytes(sizeof(t_faust_param)); - if(!newmemory) - { - pd_error(x, "faust~: memory allocation failed - parameter"); - return; - } - } - if(strnlen(label, MAXFAUSTSTRING) == 0 || label[0] == '0') - { - char temp[MAXFAUSTSTRING]; - sprintf(temp, "param%i", (int)size+1); - newmemory[size].p_label = gensym(temp); - logpost(x, 3, "faust~: parameter has no label, empty string replace with '%s'", temp); - } - else - { - newmemory[size].p_label = gensym(label); - } - newmemory[size].p_type = type; - newmemory[size].p_zone = zone; - newmemory[size].p_min = min; - newmemory[size].p_max = max; - newmemory[size].p_step = step; - *newmemory[size].p_zone = init; - x->f_params = (t_faust_param *)newmemory; - x->f_nparams++; -} - -static void faust_tilde_ui_add_button(t_faust_tilde* x, const char* label, FAUSTFLOAT* zone) -{ - faust_tilde_add_params(x, label, 0, zone, 0, 0, 0, 0); -} - -static void faust_tilde_ui_add_check_button(t_faust_tilde* x, const char* label, FAUSTFLOAT* zone) -{ - faust_tilde_add_params(x, label, 1, zone,0, 0, 1, 1); -} - -static void faust_tilde_ui_add_vertical_slider(t_faust_tilde* x, const char* label, FAUSTFLOAT* zone, - FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) -{ - faust_tilde_add_params(x, label, 2, zone, init, min, max, step); -} - -static void faust_tilde_ui_add_horizontal_slider(t_faust_tilde* x, const char* label, FAUSTFLOAT* zone, - FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) -{ - faust_tilde_add_params(x, label, 2, zone, init, min, max, step); -} - -static void faust_tilde_ui_add_number_entry(t_faust_tilde* x, const char* label, FAUSTFLOAT* zone, - FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) -{ - faust_tilde_add_params(x, label, 2, zone, init, min, max, step); -} - - - - -static void faust_tilde_ui_add_horizontal_bargraph(t_faust_tilde* x, const char* label, - FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) -{ - pd_error(x, "faust~: add horizontal bargraph not supported yet"); -} - -static void faust_tilde_ui_add_vertical_bargraph(t_faust_tilde* x, const char* label, - FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) -{ - pd_error(x, "faust~: add vertical bargraph not supported yet"); -} - -static void faust_tilde_ui_add_sound_file(t_faust_tilde* x, const char* label, const char* filename, struct Soundfile** sf_zone) -{ - pd_error(x, "faust~: add sound file not supported yet"); -} - -static void faust_tilde_ui_declare(t_faust_tilde* x, FAUSTFLOAT* zone, const char* key, const char* value) -{ - //pd_error(x, "faust~: ui declare %s: %s", key, value); -} - - - - -static void faust_tilde_meta_declare(t_faust_tilde* x, const char* key, const char* value) -{ - logpost(x, 3, " %s: %s", key, value); -} - -static void faust_tilde_print(t_faust_tilde *x) -{ - size_t i; - startpost("faust~: compile options\n"); - for(i = 0; i < x->f_ncompile_options; i++) - { - poststring(x->f_compile_options[i]); - } - endpost(); -} - -static void faust_tilde_reload(t_faust_tilde *x) -{ - int dspstate = canvas_suspend_dsp(); - char* filepath = faust_tilde_get_dsp_file_path(x); - if(filepath) - { - char errors[MAXFAUSTSTRING]; - faust_tilde_delete_instance(x); - faust_tilde_delete_factory(x); - faust_tilde_delete_params(x); - - x->f_dsp_factory = createCDSPFactoryFromFile(filepath, - (int)x->f_ncompile_options, (const char**)x->f_compile_options, - "", errors, -1); - if(strnlen(errors, MAXFAUSTSTRING)) - { - pd_error(x, "faust~: try to load %s", filepath); - size_t i; - for (i = 0; i < x->f_ncompile_options; ++i) - { - if(x->f_compile_options[i]) - { - pd_error(x, "faust~: option %s", x->f_compile_options[i]); - } - } - pd_error(x, "faust~: %s", errors); - x->f_dsp_factory = NULL; - } - else - { - x->f_dsp_instance = createCDSPInstance(x->f_dsp_factory); - if(x->f_dsp_instance) - { - if(!faust_tilde_resize_ioputs(x, - getNumInputsCDSPInstance(x->f_dsp_instance), - getNumOutputsCDSPInstance(x->f_dsp_instance))) - { - logpost(x, 3, "\nfaust~: compilation from source '%s' succeeded", x->f_dsp_name->s_name); - metadataCDSPInstance(x->f_dsp_instance, &x->f_meta_glue); - buildUserInterfaceCDSPInstance(x->f_dsp_instance, &x->f_ui_glue); - - logpost(x, 3, " %s: %i", "number of inputs", - getNumInputsCDSPInstance(x->f_dsp_instance)); - logpost(x, 3, " %s: %i", "number of outputs", - getNumOutputsCDSPInstance(x->f_dsp_instance)); - size_t i; - for (i = 0; i < x->f_nparams; ++i) - { - logpost(x, 3, " parameter %i: %s", (int)i, x->f_params[i].p_label->s_name); - } - } - - } - else - { - pd_error(x, "faust~: memory allocation failed - instance"); - } - } - free(filepath); - } - else - { - pd_error(x, "faust~: source file not defined"); - } - canvas_resume_dsp(dspstate); -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -// PURE DATA GENERIC INTERFACE // -////////////////////////////////////////////////////////////////////////////////////////////////// - -static void faust_tilde_anything(t_faust_tilde *x, t_symbol* s, int argc, t_atom* argv) -{ - t_float value; - if(x->f_dsp_instance) - { - size_t i; - for(i = 0; i < x->f_nparams; ++i) - { - if(x->f_params[i].p_label == s) - { - if(x->f_params[i].p_type == 0) - { - *x->f_params[i].p_zone = !(*x->f_params[i].p_zone != 0.f); - if(argc) - { - pd_error(x, "faust~: parameter '%s' too many arguments: 0 expected", s->s_name); - } - } - else if(x->f_params[i].p_type == 1) - { - if(argc < 1 || argv[0].a_type != A_FLOAT) - { - pd_error(x, "faust~: parameter '%s' wrong arguments: 0 expected", s->s_name); - return; - } - *x->f_params[i].p_zone = argv[0].a_w.w_float != 0.f; - if(argc > 1) - { - pd_error(x, "faust~: parameter '%s' too many arguments: 1 float expected", s->s_name); - } - } - else if(x->f_params[i].p_type == 2) - { - if(argc < 1 || argv[0].a_type != A_FLOAT) - { - pd_error(x, "faust~: parameter '%s' wrong arguments: 0 expected", s->s_name); - return; - } - value = argv[0].a_w.w_float; - value = value > x->f_params[i].p_min ? value : x->f_params[i].p_min; - value = value < x->f_params[i].p_max ? value : x->f_params[i].p_max; - *x->f_params[i].p_zone = value; - if(argc > 1) - { - pd_error(x, "faust~: parameter '%s' too many arguments: 1 float expected", s->s_name); - } - } - else - { - pd_error(x, "faust~: wrong parameter '%s'", s->s_name); - } - return; - } - } - pd_error(x, "faust~: parameter '%s' not defined", s->s_name); - } -} - -static void faust_tilde_bang(t_faust_tilde *x, t_float f) -{ - faust_tilde_anything(x, &s_, 0, NULL); -} - -static void faust_tilde_symbol(t_faust_tilde *x, t_symbol* s) -{ - faust_tilde_anything(x, s, 0, NULL); -} - -static void faust_tilde_list(t_faust_tilde *x, t_symbol* s, int argc, t_atom* argv) -{ - faust_tilde_anything(x, s, argc, argv); -} - -static t_int *faust_tilde_perform(t_int *w) -{ - computeCDSPInstance((llvm_dsp *)w[1], (int)w[2], (float **)w[3], (float **)w[4]); - return (w+5); -} - -static char faust_tilde_is_valid(t_faust_tilde *x) -{ - size_t fnins, fnouts; - if(!x->f_dsp_instance) - { - return -1; - } - fnins = (size_t)getNumInputsCDSPInstance(x->f_dsp_instance); - fnouts = (size_t)getNumOutputsCDSPInstance(x->f_dsp_instance); - if(fnins == 0) - fnins = 1; - if(fnins != x->f_ninlets) - { - pd_error(x, "faust~: number of inlets is invalid"); - return -1; - } - if(fnouts!= x->f_noutlets) - { - pd_error(x, "faust~: number of outlets is invalid"); - return -1; - } - if(x->f_nsignals != x->f_ninlets + x->f_ninlets) - { - pd_error(x, "faust~: number of signals is invalid"); - return -1; - } - if(!x->f_signals) - { - pd_error(x, "faust~: signals are not allocated"); - return -1; - } - return 0; -} - -static void faust_tilde_dsp(t_faust_tilde *x, t_signal **sp) -{ - if(!faust_tilde_is_valid(x)) - { - size_t i; - size_t const ninlets = x->f_ninlets; - size_t const noutlets = x->f_noutlets; - faust_tilde_save_params(x); - initCDSPInstance(x->f_dsp_instance, sp[0]->s_sr); - for(i = 0; i < ninlets + noutlets; ++i) - { - x->f_signals[i] = sp[i]->s_vec; - } - dsp_add((t_perfroutine)faust_tilde_perform, 4, - (t_int)x->f_dsp_instance, (t_int)sp[0]->s_n, (t_int)x->f_signals, (t_int)(x->f_signals+ninlets)); - faust_tilde_restore_params(x); - } -} - -static void faust_tilde_free(t_faust_tilde *x) -{ - faust_tilde_delete_instance(x); - faust_tilde_delete_factory(x); - faust_tilde_delete_params(x); - faust_tilde_free_compile_options(x); - faust_tilde_free_ioputs(x); -} - -static void *faust_tilde_new(t_symbol* s, int argc, t_atom* argv) -{ - t_faust_tilde* x = (t_faust_tilde *)pd_new(faust_tilde_class); - if(x) - { - size_t i; - x->f_dsp_factory = NULL; - x->f_dsp_instance = NULL; - x->f_nsignals = 0; - x->f_signals = NULL; - x->f_f = 0; - - x->f_meta_glue.metaInterface = x; - x->f_meta_glue.declare = (metaDeclareFun)faust_tilde_meta_declare; - - x->f_ui_glue.uiInterface = x; - x->f_ui_glue.openTabBox = (openTabBoxFun)faust_tilde_ui_open_tab_box; - x->f_ui_glue.openHorizontalBox = (openHorizontalBoxFun)faust_tilde_ui_open_horizontal_box; - x->f_ui_glue.openVerticalBox = (openVerticalBoxFun)faust_tilde_ui_open_vertical_box; - x->f_ui_glue.closeBox = (closeBoxFun)faust_tilde_ui_close_box; - - x->f_ui_glue.addButton = (addButtonFun)faust_tilde_ui_add_button; - x->f_ui_glue.addCheckButton = (addCheckButtonFun)faust_tilde_ui_add_check_button; - x->f_ui_glue.addVerticalSlider = (addVerticalSliderFun)faust_tilde_ui_add_vertical_slider; - x->f_ui_glue.addHorizontalSlider = (addHorizontalSliderFun)faust_tilde_ui_add_horizontal_slider; - x->f_ui_glue.addNumEntry = (addNumEntryFun)faust_tilde_ui_add_number_entry; - - x->f_ui_glue.addHorizontalBargraph = (addHorizontalBargraphFun)faust_tilde_ui_add_horizontal_bargraph; - x->f_ui_glue.addVerticalBargraph = (addVerticalBargraphFun)faust_tilde_ui_add_vertical_bargraph; - x->f_ui_glue.addSoundFile = (addSoundFileFun)faust_tilde_ui_add_sound_file; - x->f_ui_glue.declare = (declareFun)faust_tilde_ui_declare; - - x->f_nparams = 0; - x->f_params = NULL; - - x->f_canvas = canvas_getcurrent(); - x->f_dsp_name = atom_getsymbolarg(0, argc, argv); - - x->f_ncompile_options = 0; - for(i = 0; i < MAXFAUSTOPTIONS; ++i) - { - x->f_compile_options[i] = NULL; - } - x->f_ninlets = 1; - x->f_inlets = NULL; - x->f_noutlets = 0; - x->f_outlets = NULL; - x->f_allocated = 0; - - if(argc == 0 || argv == NULL) - { - return x; - } - if(faust_tilde_parse_compile_options(x, argc-1, argv+1)) - { - faust_tilde_free(x); - return NULL; - } - faust_tilde_reload(x); - x->f_allocated = 1; - if(!x->f_dsp_instance) - { - faust_tilde_free(x); - return NULL; - } - } - return x; -} - -void faust_tilde_setup(void) -{ - t_class* c = class_new(gensym("faust~"), - (t_newmethod)faust_tilde_new, (t_method)faust_tilde_free, - sizeof(t_faust_tilde), CLASS_DEFAULT, A_GIMME, 0); - if(c) - { - class_addmethod(c, (t_method)faust_tilde_dsp, gensym("dsp"), A_CANT); - class_addmethod(c, (t_method)faust_tilde_reload, gensym("reload"), A_NULL); - class_addmethod(c, (t_method)faust_tilde_print, gensym("print"), A_NULL); - class_addbang(c, (t_method)faust_tilde_bang); - class_addsymbol(c, (t_method)faust_tilde_symbol); - class_addlist(c, (t_method)faust_tilde_list); - class_addanything(c, (t_method)faust_tilde_anything); - - CLASS_MAINSIGNALIN(c, t_faust_tilde, f_f); - - logpost(NULL, 3, "Faust website: faust.grame.fr"); - logpost(NULL, 3, "Faust development: GRAME"); - - logpost(NULL, 3, "faust~ compiler version: %s", getCLibFaustVersion()); - logpost(NULL, 3, "faust~ include directory: %s", class_gethelpdir(c)); - logpost(NULL, 3, "faust~ institutions: CICM - ANR MUSICOLL"); - logpost(NULL, 3, "faust~ external author: Pierre Guillot"); - logpost(NULL, 3, "faust~ website: github.com/grame-cncm/faust-pd"); - } - - faust_tilde_class = c; -} - diff --git a/src/faust_tilde_io.c b/src/faust_tilde_io.c new file mode 100644 index 0000000..eeb35ca --- /dev/null +++ b/src/faust_tilde_io.c @@ -0,0 +1,327 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + + +#include "faust_tilde_io.h" +#include +#include + +typedef struct _faust_io_manager +{ + t_object* f_owner; + t_canvas* f_canvas; + + size_t f_nsignals; + t_sample** f_signals; + + size_t f_ninlets; + t_inlet** f_inlets; + + size_t f_noutlets; + t_outlet** f_outlets; + t_outlet* f_extra_outlet; + + char f_valid; +}t_faust_io_manager; + +////////////////////////////////////////////////////////////////////////////////////////////////// +// PURE DATA IO DYNAMIC // +////////////////////////////////////////////////////////////////////////////////////////////////// + + +// FREE METHODS +////////////////////////////////////////////////////////////////////////////////////////////////// +static void faust_io_manager_free_signals(t_faust_io_manager *x) +{ + if(x->f_signals) + { + freebytes(x->f_signals, sizeof(t_sample*) * x->f_nsignals); + } + x->f_signals = NULL; + x->f_nsignals = 0; +} + +static void faust_io_manager_free_inputs(t_faust_io_manager *x) +{ + if(x->f_inlets && x->f_ninlets) + { + freebytes(x->f_inlets, sizeof(t_inlet*) * x->f_ninlets); + } + x->f_inlets = NULL; + x->f_ninlets = 0; +} + +static void faust_io_manager_free_outputs(t_faust_io_manager *x) +{ + if(x->f_outlets && x->f_noutlets) + { + freebytes(x->f_outlets, sizeof(t_outlet*) * x->f_noutlets); + } + x->f_outlets = NULL; + x->f_noutlets = 0; +} + +// ALLOCATE-RESIZE METHODS +////////////////////////////////////////////////////////////////////////////////////////////////// + +static char faust_io_manager_resize_signals(t_faust_io_manager *x, size_t nsignals) +{ + t_sample** nsigs; + if(x->f_nsignals == nsignals) + { + return 0; + } + nsigs = (t_sample **)resizebytes(x->f_signals, x->f_nsignals * sizeof(t_sample*), nsignals * sizeof(t_sample*)); + if(nsigs) + { + x->f_nsignals = nsignals; + x->f_signals = nsigs; + return 0; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - signals"); + return 4; +} + +static char faust_io_manager_resize_inputs(t_faust_io_manager *x, size_t const nins) +{ + t_inlet** ninlets; + size_t i; + size_t const cins = faust_io_manager_get_ninputs(x); + size_t const rnins = nins; + if(rnins == cins) + { + return 0; + } + for(i = cins; i > rnins; --i) + { + inlet_free(x->f_inlets[i-1]); + x->f_inlets[i-1] = NULL; + } + ninlets = (t_inlet **)resizebytes(x->f_inlets, sizeof(t_inlet*) * cins, sizeof(t_inlet*) * rnins); + if(ninlets) + { + for(i = cins; i < rnins; ++i) + { + ninlets[i] = signalinlet_new((t_object *)x->f_owner, 0); + if(!ninlets[i]) + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - input %i", (int)i); + } + } + x->f_inlets = ninlets; + x->f_ninlets = rnins; + return 0; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - inputs"); + return 2; +} + +static char faust_io_manager_resize_outputs(t_faust_io_manager *x, size_t const nouts, char const extraout) +{ + t_outlet** noutlets; + size_t i; + size_t const couts = faust_io_manager_get_noutputs(x); + size_t const rnouts = nouts; + + if(rnouts == couts) + { + if(faust_io_manager_has_extra_output(x) && !extraout) + { + outlet_free(x->f_extra_outlet); + x->f_extra_outlet = NULL; + return 0; + } + else if(!faust_io_manager_has_extra_output(x) && extraout) + { + x->f_extra_outlet = outlet_new((t_object *)x->f_owner, NULL); + if(x->f_extra_outlet) + { + return 0; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - extra output"); + return 1; + } + return 0; + } + + if(faust_io_manager_has_extra_output(x)) + { + outlet_free(x->f_extra_outlet); + x->f_extra_outlet = NULL; + } + for(i = couts; i > rnouts; --i) + { + outlet_free(x->f_outlets[i-1]); + x->f_outlets[i-1] = NULL; + } + noutlets = (t_outlet **)resizebytes(x->f_outlets, sizeof(t_outlet*) * couts, sizeof(t_outlet*) * rnouts); + if(noutlets) + { + for(i = couts; i < rnouts; ++i) + { + noutlets[i] = outlet_new((t_object *)x->f_owner, gensym("signal")); + if(!noutlets[i]) + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - output %i", (int)i); + } + } + x->f_outlets = noutlets; + x->f_noutlets = rnouts; + if(extraout) + { + x->f_extra_outlet = outlet_new((t_object *)x->f_owner, NULL); + if(x->f_extra_outlet) + { + return 0; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - extra output"); + return 1; + } + return 0; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - output"); + return 1; +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC INTERFACE // +////////////////////////////////////////////////////////////////////////////////////////////////// + +t_faust_io_manager* faust_io_manager_new(t_object* owner, t_canvas* canvas) +{ + t_faust_io_manager* x = (t_faust_io_manager*)getbytes(sizeof(t_faust_io_manager)); + if(x) + { + x->f_owner = owner; + x->f_canvas = canvas; + x->f_nsignals = 0; + x->f_signals = NULL; + x->f_ninlets = 1; + x->f_inlets = getbytes(sizeof(t_inlet *)); + x->f_noutlets = 0; + x->f_outlets = NULL; + x->f_extra_outlet = NULL; + x->f_valid = 0; + } + return x; +} + +void faust_io_manager_free(t_faust_io_manager* x) +{ + faust_io_manager_free_inputs(x); + faust_io_manager_free_outputs(x); + faust_io_manager_free_signals(x); + freebytes(x, sizeof(t_faust_io_manager)); +} + +size_t faust_io_manager_get_ninputs(t_faust_io_manager *x) +{ + return x->f_ninlets; +} + +size_t faust_io_manager_get_noutputs(t_faust_io_manager *x) +{ + return x->f_noutlets; +} + +char faust_io_manager_has_extra_output(t_faust_io_manager *x) +{ + return x->f_extra_outlet != NULL; +} + +t_outlet* faust_io_manager_get_extra_output(t_faust_io_manager *x) +{ + return x->f_extra_outlet; +} + +char faust_io_manager_init(t_faust_io_manager *x, int const nins, int const nouts, char const extraout) +{ + char valid = 0; + char const redraw = x->f_owner->te_binbuf && gobj_shouldvis((t_gobj *)x->f_owner, x->f_canvas) && glist_isvisible(x->f_canvas); + if(redraw) + { + gobj_vis((t_gobj *)x->f_owner, x->f_canvas, 0); + } + size_t const rnins = nins > 1 ? nins : 1; + valid += faust_io_manager_resize_inputs(x, (size_t)rnins); + valid += faust_io_manager_resize_outputs(x, (size_t)nouts, extraout); + valid += faust_io_manager_resize_signals(x, (size_t)rnins + (size_t)nouts); + if(redraw) + { + gobj_vis((t_gobj *)x->f_owner, x->f_canvas, 1); + canvas_fixlinesfor(x->f_canvas, (t_text *)x->f_owner); + } + x->f_valid = (valid == 0); + return valid; +} + +#include + +static char faust_io_manager_is_valid(t_faust_io_manager *x) +{ + if(!x->f_signals || !x->f_valid) + { + pd_error(x->f_owner, "faustgen~: something wrong happened during iolets allocation"); + return 0; + } + if(obj_nsiginlets(x->f_owner) != x->f_ninlets) + { + pd_error(x->f_owner, "faustgen~: number of signal inlets %i incompatible with internal %i", (int)x->f_ninlets, (int)obj_nsiginlets(x->f_owner)); + return 0; + } + if(obj_nsiginlets(x->f_owner) != x->f_ninlets) + { + pd_error(x->f_owner, "faustgen~: number of signal inlets %i incompatible with internal %i", (int)x->f_ninlets, (int)obj_nsiginlets(x->f_owner)); + return 0; + } + if(obj_nsigoutlets(x->f_owner) != x->f_noutlets) + { + pd_error(x->f_owner, "faustgen~: number of signal outlets %i incompatible with internal %i", (int)x->f_noutlets, (int)obj_nsigoutlets(x->f_owner)); + return 0; + } + if(x->f_ninlets + x->f_noutlets != x->f_nsignals) + { + pd_error(x->f_owner, "faustgen~: number of signals %i incompatible with number of iolets %i", (int)x->f_nsignals, (int)(x->f_ninlets + x->f_noutlets)); + return 0; + } + return 1; +} + +char faust_io_manager_prepare(t_faust_io_manager *x, t_signal **sp) +{ + size_t i; + if(!faust_io_manager_is_valid) + { + return 1; + } + for(i = 0; i < x->f_nsignals; ++i) + { + x->f_signals[i] = sp[i]->s_vec; + if(x->f_signals[i] == NULL) + { + pd_error(x->f_owner, "faustgen~: the signal vector %i is empty", (int)i); + return 1; + } + } + return 0; +} + +t_sample** faust_io_manager_get_input_signals(t_faust_io_manager *x) +{ + return x->f_signals; +} + +t_sample** faust_io_manager_get_output_signals(t_faust_io_manager *x) +{ + return x->f_signals+x->f_ninlets; +} + +void faust_io_manager_print(t_faust_io_manager* x, char const log) +{ + logpost(x->f_owner, 2+log, " number of inputs: %i", (int)faust_io_manager_get_ninputs(x)); + logpost(x->f_owner, 2+log, " number of outputs: %i", (int)faust_io_manager_get_noutputs(x)); + logpost(x->f_owner, 2+log, " extra output: %s", faust_io_manager_has_extra_output(x) ? "true" : "false"); +} diff --git a/src/faust_tilde_io.h b/src/faust_tilde_io.h new file mode 100644 index 0000000..1f606a3 --- /dev/null +++ b/src/faust_tilde_io.h @@ -0,0 +1,37 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#ifndef FAUST_TILDE_IO_H +#define FAUST_TILDE_IO_H + +#include + +struct _faust_io_manager; +typedef struct _faust_io_manager t_faust_io_manager; + +t_faust_io_manager* faust_io_manager_new(t_object* owner, t_canvas* canvas); + +void faust_io_manager_free(t_faust_io_manager* x); + +size_t faust_io_manager_get_ninputs(t_faust_io_manager *x); + +size_t faust_io_manager_get_noutputs(t_faust_io_manager *x); + +char faust_io_manager_has_extra_output(t_faust_io_manager *x); + +t_outlet* faust_io_manager_get_extra_output(t_faust_io_manager *x); + +char faust_io_manager_init(t_faust_io_manager *x, int const nins, int const nouts, char const extraout); + +char faust_io_manager_prepare(t_faust_io_manager *x, t_signal **sp); + +t_sample** faust_io_manager_get_input_signals(t_faust_io_manager *x); + +t_sample** faust_io_manager_get_output_signals(t_faust_io_manager *x); + +void faust_io_manager_print(t_faust_io_manager* x, char const log); + +#endif diff --git a/src/faust_tilde_options.c b/src/faust_tilde_options.c new file mode 100644 index 0000000..e3afbc0 --- /dev/null +++ b/src/faust_tilde_options.c @@ -0,0 +1,223 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + + +#include "faust_tilde_options.h" +#include + +#define MAXFAUSTSTRING 4096 + +typedef struct _faust_opt_manager +{ + t_object* f_owner; + char* f_default_include; + size_t f_noptions; + char** f_options; + t_symbol* f_directory; + t_symbol* f_temp_path; + char f_use_default_include; +}t_faust_opt_manager; + + +// LOCATE DEFAULT INCLUDE PATH +////////////////////////////////////////////////////////////////////////////////////////////////// +static void faust_opt_manager_get_default_include_path(t_faust_opt_manager *x) +{ + char const* path = class_gethelpdir(pd_class((t_pd *)x->f_owner)); + if(path) + { + x->f_default_include = (char *)getbytes((strnlen(path, MAXPDSTRING) + 7) * sizeof(char)); + if(x->f_default_include) + { + sprintf(x->f_default_include, "%s/libs/", path); + return; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - include path"); + return; + } + pd_error(x->f_owner, "faustgen~: cannot locate the include path"); + return; +} + +static void faust_opt_manager_free_default_include_path(t_faust_opt_manager *x) +{ + if(x->f_default_include) + { + freebytes(x->f_default_include, strnlen(x->f_default_include, MAXPDSTRING) * sizeof(char)); + } + x->f_default_include = NULL; +} + +// COMPILE OPTIONS +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_opt_manager_free_compile_options(t_faust_opt_manager *x) +{ + if(x->f_options && x->f_noptions) + { + size_t i; + size_t noptions = x->f_use_default_include ? x->f_noptions - 1 : x->f_noptions; + for(i = 0; i < noptions; ++i) + { + if(x->f_options[i]) + { + freebytes(x->f_options[i], strnlen(x->f_options[i], MAXFAUSTSTRING)); + } + x->f_options[i] = NULL; + } + freebytes(x->f_options, x->f_noptions * sizeof(char *)); + } + x->f_options = NULL; + x->f_noptions = 0; + x->f_use_default_include = 0; +} + +char faust_opt_manager_parse_compile_options(t_faust_opt_manager *x, size_t const argc, const t_atom* argv) +{ + size_t i; + char has_include = 0; + faust_opt_manager_free_compile_options(x); + x->f_options = getbytes(argc * sizeof(char *)); + if(x->f_options) + { + for(i = 0; i < argc; ++i) + { + x->f_options[i] = (char *)getbytes(MAXFAUSTSTRING * sizeof(char)); + if(x->f_options[i]) + { + if(argv[i].a_type == A_FLOAT) + { + sprintf(x->f_options[i], "%i", (int)argv[i].a_w.w_float); + } + else if(argv[i].a_type == A_SYMBOL && argv[i].a_w.w_symbol) + { + sprintf(x->f_options[i], "%s", argv[i].a_w.w_symbol->s_name); + if(!strncmp(x->f_options[i], "-I", 2)) + { + has_include = 1; + } + } + else + { + pd_error(x->f_owner, "faustgen~: option type invalid"); + memset(x->f_options[i], 0, MAXFAUSTSTRING); + } + x->f_noptions = i+1; + } + else + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - compile option %i", (int)i); + x->f_noptions = i; + return -1; + } + } + } + else + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - compile options"); + x->f_noptions = 0; + return -1; + } + if(!has_include) + { + char **temp = resizebytes(x->f_options, (argc * sizeof(char *)), ((argc + 2) * sizeof(char *))); + if(temp) + { + x->f_options = temp; + x->f_options[argc] = (char *)getbytes(3 * sizeof(char)); + if(x->f_options[argc]) + { + sprintf(x->f_options[argc], "%s", "-I"); + } + else + { + pd_error(x, "faustgen~: memory allocation failed - compile option"); + x->f_noptions = argc; + return -1; + } + + x->f_options[argc+1] = x->f_default_include; + x->f_noptions = argc+2; + x->f_use_default_include = 1; + return 0; + } + else + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - compile options for default include"); + return -1; + } + } + return 0; +} + + +////////////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC INTERFACE // +////////////////////////////////////////////////////////////////////////////////////////////////// + +t_faust_opt_manager* faust_opt_manager_new(t_object* owner, t_canvas* canvas) +{ + t_faust_opt_manager* x = (t_faust_opt_manager*)getbytes(sizeof(t_faust_opt_manager)); + if(x) + { + x->f_owner = owner; + x->f_default_include = NULL; + x->f_options = NULL; + x->f_noptions = 0; + x->f_use_default_include = 0; + x->f_directory = canvas_getdir(canvas); + faust_opt_manager_get_default_include_path(x); + } + return x; +} + +void faust_opt_manager_free(t_faust_opt_manager* x) +{ + faust_opt_manager_free_default_include_path(x); + freebytes(x, sizeof(t_faust_opt_manager)); +} + +size_t faust_opt_manager_get_noptions(t_faust_opt_manager* x) +{ + return x->f_noptions; +} + +char const** faust_opt_manager_get_options(t_faust_opt_manager* x) +{ + return (char const**)x->f_options; +} + +char const* faust_opt_manager_get_full_path(t_faust_opt_manager* x, char const* name) +{ + if(sys_isabsolutepath(name)) + { + return name; + } + else if(x->f_directory && x->f_directory->s_name && name) + { + char* file = (char *)getbytes(MAXFAUSTSTRING * sizeof(char)); + if(file) + { + sprintf(file, "%s/%s.dsp", x->f_directory->s_name, name); + x->f_temp_path = gensym(file); + freebytes(file, MAXFAUSTSTRING * sizeof(char)); + return x->f_temp_path->s_name; + } + pd_error(x->f_owner, "faustgen~: memory allocation failed - path"); + return NULL; + } + pd_error(x->f_owner, "faustgen~: invalid path or name"); + return NULL; +} + +void faust_opt_manager_print(t_faust_opt_manager* x, char const log) +{ + size_t i; + for(i = 0; i < x->f_noptions; ++i) + { + logpost(x->f_owner, 2+log, " option %i: %s", (int)i, x->f_options[i]); + } +} diff --git a/src/faust_tilde_options.h b/src/faust_tilde_options.h new file mode 100644 index 0000000..a984cff --- /dev/null +++ b/src/faust_tilde_options.h @@ -0,0 +1,29 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#ifndef FAUST_TILDE_OPTIONS_H +#define FAUST_TILDE_OPTIONS_H + +#include + +struct _faust_opt_manager; +typedef struct _faust_opt_manager t_faust_opt_manager; + +t_faust_opt_manager* faust_opt_manager_new(t_object* owner, t_canvas* canvas); + +void faust_opt_manager_free(t_faust_opt_manager* x); + +char faust_opt_manager_parse_compile_options(t_faust_opt_manager *x, size_t const argc, const t_atom* argv); + +size_t faust_opt_manager_get_noptions(t_faust_opt_manager* x); + +char const** faust_opt_manager_get_options(t_faust_opt_manager* x); + +char const* faust_opt_manager_get_full_path(t_faust_opt_manager* x, char const* name); + +void faust_opt_manager_print(t_faust_opt_manager* x, char const log); + +#endif diff --git a/src/faust_tilde_ui.c b/src/faust_tilde_ui.c new file mode 100644 index 0000000..3cbefb4 --- /dev/null +++ b/src/faust_tilde_ui.c @@ -0,0 +1,481 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + + +#include "faust_tilde_ui.h" +#include +#include +#include + +#define MAXFAUSTSTRING 4096 +#define FAUST_UI_TYPE_BUTTON 0 +#define FAUST_UI_TYPE_TOGGLE 1 +#define FAUST_UI_TYPE_NUMBER 2 +#define FAUST_UI_TYPE_BARGRAPH 3 + +typedef struct _faust_ui +{ + t_symbol* p_name; + t_symbol* p_longname; + int p_type; + FAUSTFLOAT* p_zone; + FAUSTFLOAT p_min; + FAUSTFLOAT p_max; + FAUSTFLOAT p_step; + FAUSTFLOAT p_default; + FAUSTFLOAT p_saved; +}t_faust_ui; + +typedef struct _faust_ui_manager +{ + UIGlue f_glue; + t_object* f_owner; + t_clock* f_clock; + t_faust_ui* f_active_uis; + size_t f_nactive_uis; + t_faust_ui* f_temp_ui; + t_faust_ui* f_passive_uis; + size_t f_npassive_uis; + t_symbol** f_names; + size_t f_nnames; + MetaGlue f_meta_glue; +}t_faust_ui_manager; + + +static void faust_ui_manager_clear_active_uis(t_faust_ui_manager *x) +{ + if(x->f_active_uis && x->f_nactive_uis) + { + freebytes(x->f_active_uis, x->f_nactive_uis * sizeof(t_faust_ui)); + } + x->f_active_uis = NULL; + x->f_nactive_uis = 0; +} + +static void faust_ui_manager_clear_passive_uis(t_faust_ui_manager *x) +{ + if(x->f_passive_uis && x->f_npassive_uis) + { + freebytes(x->f_passive_uis, x->f_npassive_uis * sizeof(t_faust_ui)); + } + x->f_passive_uis = NULL; + x->f_npassive_uis = 0; +} + +static void faust_ui_manager_clear_names(t_faust_ui_manager *x) +{ + if(x->f_names && x->f_nnames) + { + freebytes(x->f_names, x->f_nnames * sizeof(t_symbol *)); + } + x->f_names = NULL; + x->f_nnames = 0; +} + +static t_faust_ui* faust_ui_manager_get_active_uis(t_faust_ui_manager *x, t_symbol* name) +{ + size_t i; + for(i = 0; i < x->f_nactive_uis; ++i) + { + if(x->f_active_uis[i].p_name == name || + x->f_active_uis[i].p_longname == name) + { + return x->f_active_uis+i; + } + } + return NULL; +} + +static t_faust_ui* faust_ui_manager_get_passive_uis(t_faust_ui_manager *x, t_symbol* name) +{ + size_t i; + for(i = 0; i < x->f_npassive_uis; ++i) + { + if(x->f_passive_uis[i].p_name == name || + x->f_passive_uis[i].p_longname == name) + { + return x->f_passive_uis+i; + } + } + return NULL; +} + +static t_symbol* faust_ui_manager_get_long_name(t_faust_ui_manager *x, const char* label) +{ + size_t i; + char name[MAXFAUSTSTRING]; + memset(name, 0, MAXFAUSTSTRING); + for(i = 0; i < x->f_nnames; ++i) + { + strncat(name, x->f_names[i]->s_name, MAXFAUSTSTRING); + strncat(name, "/", 1); + } + strncat(name, label, MAXFAUSTSTRING); + return gensym(name); +} + +static void faust_ui_manager_add_params(t_faust_ui_manager *x, const char* label, int const type, FAUSTFLOAT* zone, + FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) +{ + t_faust_ui *newmemory = NULL; + t_faust_ui *oldmemory = (type == FAUST_UI_TYPE_BARGRAPH) ? x->f_passive_uis : x->f_active_uis; + size_t size = (type == FAUST_UI_TYPE_BARGRAPH) ? x->f_npassive_uis : x->f_nactive_uis; + if(oldmemory) + { + newmemory = (t_faust_ui *)resizebytes(oldmemory, size * sizeof(t_faust_ui), (size + 1) * sizeof(t_faust_ui)); + if(!newmemory) + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - ui glue"); + return; + } + } + else + { + newmemory = (t_faust_ui *)getbytes(sizeof(t_faust_ui)); + if(!newmemory) + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - ui glue"); + return; + } + } + + newmemory[size].p_name = gensym(label); + newmemory[size].p_longname = faust_ui_manager_get_long_name(x, label); + newmemory[size].p_type = type; + newmemory[size].p_zone = zone; + newmemory[size].p_min = min; + newmemory[size].p_max = max; + newmemory[size].p_step = step; + newmemory[size].p_default = init; + newmemory[size].p_saved = init; + *(newmemory[size].p_zone) = init; + if(type == FAUST_UI_TYPE_BARGRAPH) + { + x->f_passive_uis = (t_faust_ui *)newmemory; + x->f_npassive_uis = size + 1; + } + else + { + x->f_active_uis = (t_faust_ui *)newmemory; + x->f_nactive_uis = size + 1; + } + +} + +////////////////////////////////////////////////////////////////////////////////////////////////// +// PRIVATE INTERFACE // +////////////////////////////////////////////////////////////////////////////////////////////////// + +// NAME PATH +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_ui_manager_ui_open_box(t_faust_ui_manager* x, const char* label) +{ + if(x->f_nnames) + { + t_symbol** temp = (t_symbol**)resizebytes(x->f_names, x->f_nnames * sizeof(t_symbol *), (x->f_nnames + 1) * sizeof(t_symbol *)); + if(temp) + { + x->f_names = temp; + x->f_names[x->f_nnames] = gensym(label); + x->f_nnames = x->f_nnames + 1; + return; + } + else + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - ui box"); + return; + } + } + else + { + x->f_names = getbytes(sizeof(t_symbol *)); + if(x->f_names) + { + x->f_names[0] = gensym(label); + x->f_nnames = 1; + return; + } + else + { + pd_error(x->f_owner, "faustgen~: memory allocation failed - ui box"); + return; + } + } +} + +static void faust_ui_manager_ui_close_box(t_faust_ui_manager* x) +{ + if(x->f_nnames > 1) + { + t_symbol** temp = (t_symbol**)resizebytes(x->f_names, x->f_nnames * sizeof(t_symbol *), (x->f_nnames - 1) * sizeof(t_symbol *)); + if(temp) + { + x->f_names = temp; + x->f_nnames = x->f_nnames - 1; + return; + } + else + { + pd_error(x->f_owner, "faustgen~: memory de-allocation failed - ui box"); + return; + } + } + else if(x->f_nnames) + { + freebytes(x->f_names, sizeof(t_symbol *)); + x->f_names = NULL; + x->f_nnames = 0; + } +} + + +// ACTIVE UIS +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_ui_manager_ui_add_button(t_faust_ui_manager* x, const char* label, FAUSTFLOAT* zone) +{ + faust_ui_manager_add_params(x, label, FAUST_UI_TYPE_BUTTON, zone, 0, 0, 0, 0); +} + +static void faust_ui_manager_ui_add_toggle(t_faust_ui_manager* x, const char* label, FAUSTFLOAT* zone) +{ + faust_ui_manager_add_params(x, label, FAUST_UI_TYPE_TOGGLE, zone, 0, 0, 1, 1); +} + +static void faust_ui_manager_ui_add_number(t_faust_ui_manager* x, const char* label, FAUSTFLOAT* zone, + FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) +{ + faust_ui_manager_add_params(x, label, FAUST_UI_TYPE_NUMBER, zone, init, min, max, step); +} + +// PASSIVE UIS +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_ui_manager_ui_add_bargraph(t_faust_ui_manager* x, const char* label, + FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max) +{ + faust_ui_manager_add_params(x, label, FAUST_UI_TYPE_BARGRAPH, zone, 0, min, max, 0); +} + +static void faust_ui_manager_ui_add_sound_file(t_faust_ui_manager* x, const char* label, const char* filename, struct Soundfile** sf_zone) +{ + pd_error(x->f_owner, "faustgen~: add sound file not supported yet"); +} + +// DECLARE UIS +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_ui_manager_ui_declare(t_faust_ui_manager* x, FAUSTFLOAT* zone, const char* key, const char* value) +{ + //logpost(x->f_owner, 3, "%s: %s - %f", key, value, *zone); +} + +// META UIS +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_ui_manager_meta_declare(t_faust_ui_manager* x, const char* key, const char* value) +{ + logpost(x->f_owner, 3, " %s: %s", key, value); +} + + +////////////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC INTERFACE // +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faust_ui_manager_tick(t_faust_ui_manager* x); + +t_faust_ui_manager* faust_ui_manager_new(t_object* owner) +{ + t_faust_ui_manager* ui_manager = (t_faust_ui_manager*)getbytes(sizeof(t_faust_ui_manager)); + if(ui_manager) + { + ui_manager->f_glue.uiInterface = ui_manager; + ui_manager->f_glue.openTabBox = (openTabBoxFun)faust_ui_manager_ui_open_box; + ui_manager->f_glue.openHorizontalBox = (openHorizontalBoxFun)faust_ui_manager_ui_open_box; + ui_manager->f_glue.openVerticalBox = (openVerticalBoxFun)faust_ui_manager_ui_open_box; + ui_manager->f_glue.closeBox = (closeBoxFun)faust_ui_manager_ui_close_box; + + ui_manager->f_glue.addButton = (addButtonFun)faust_ui_manager_ui_add_button; + ui_manager->f_glue.addCheckButton = (addCheckButtonFun)faust_ui_manager_ui_add_toggle; + ui_manager->f_glue.addVerticalSlider = (addVerticalSliderFun)faust_ui_manager_ui_add_number; + ui_manager->f_glue.addHorizontalSlider = (addHorizontalSliderFun)faust_ui_manager_ui_add_number; + ui_manager->f_glue.addNumEntry = (addNumEntryFun)faust_ui_manager_ui_add_number; + + ui_manager->f_glue.addHorizontalBargraph = (addHorizontalBargraphFun)faust_ui_manager_ui_add_bargraph; + ui_manager->f_glue.addVerticalBargraph = (addVerticalBargraphFun)faust_ui_manager_ui_add_bargraph; + ui_manager->f_glue.addSoundFile = (addSoundFileFun)faust_ui_manager_ui_add_sound_file; + ui_manager->f_glue.declare = (declareFun)faust_ui_manager_ui_declare; + + ui_manager->f_owner = owner; + ui_manager->f_clock = clock_new(ui_manager, (t_method)faust_ui_manager_tick); + ui_manager->f_active_uis = NULL; + ui_manager->f_nactive_uis = 0; + ui_manager->f_passive_uis = NULL; + ui_manager->f_npassive_uis = 0; + ui_manager->f_names = NULL; + ui_manager->f_nnames = 0; + + ui_manager->f_meta_glue.metaInterface = ui_manager; + ui_manager->f_meta_glue.declare = (metaDeclareFun)faust_ui_manager_meta_declare; + } + return ui_manager; +} + +void faust_ui_manager_free(t_faust_ui_manager *x) +{ + faust_ui_manager_clear(x); + freebytes(x, sizeof(t_faust_ui_manager)); +} + +void faust_ui_manager_init(t_faust_ui_manager *x, void* dspinstance) +{ + faust_ui_manager_clear(x); + buildUserInterfaceCDSPInstance((llvm_dsp *)dspinstance, (UIGlue *)&(x->f_glue)); + faust_ui_manager_clear_names(x); + metadataCDSPInstance((llvm_dsp *)dspinstance, &x->f_meta_glue); +} + +void faust_ui_manager_clear(t_faust_ui_manager *x) +{ + faust_ui_manager_clear_active_uis(x); + faust_ui_manager_clear_passive_uis(x); + faust_ui_manager_clear_names(x); +} + +static void faust_ui_manager_tick(t_faust_ui_manager* x) +{ + if(x->f_temp_ui) + { + *(x->f_temp_ui->p_zone) = 0; + } + x->f_temp_ui = NULL; +} + +char faust_ui_manager_has_passive_ui(t_faust_ui_manager *x) +{ + return x->f_npassive_uis > 0; +} + +char faust_ui_manager_set(t_faust_ui_manager *x, t_symbol* name, t_float f) +{ + t_faust_ui* ui = faust_ui_manager_get_active_uis(x, name); + if(ui) + { + if(ui->p_type == FAUST_UI_TYPE_BUTTON) + { + *(ui->p_zone) = 0; + *(ui->p_zone) = 1; + x->f_temp_ui = ui; + clock_delay(x->f_clock, 1.5); + return 0; + } + else if(ui->p_type == FAUST_UI_TYPE_TOGGLE) + { + *(ui->p_zone) = (FAUSTFLOAT)(f > FLT_EPSILON); + return 0; + } + else if(ui->p_type == FAUST_UI_TYPE_NUMBER) + { + const FAUSTFLOAT v = (FAUSTFLOAT)(f); + if(v < ui->p_min) + { + *(ui->p_zone) = ui->p_min; + return 0; + } + if(v > ui->p_max) + { + *(ui->p_zone) = ui->p_max; + return 0; + } + *(ui->p_zone) = v; + return 0; + } + } + return 1; +} + +char faust_ui_manager_get(t_faust_ui_manager *x, t_symbol* name, t_float* f) +{ + t_faust_ui* ui = faust_ui_manager_get_passive_uis(x, name); + if(ui) + { + *f = (t_float)(*(ui->p_zone)); + return 0; + } + return 1; +} + +void faust_ui_manager_save_states(t_faust_ui_manager *x) +{ + size_t i; + for(i = 0; i < x->f_nactive_uis; ++i) + { + x->f_active_uis[i].p_saved = *(x->f_active_uis[i].p_zone); + } +} + +void faust_ui_manager_restore_states(t_faust_ui_manager *x) +{ + size_t i; + for(i = 0; i < x->f_nactive_uis; ++i) + { + *(x->f_active_uis[i].p_zone) = x->f_active_uis[i].p_saved; + } +} + +void faust_ui_manager_restore_default(t_faust_ui_manager *x) +{ + size_t i; + for(i = 0; i < x->f_nactive_uis; ++i) + { + *(x->f_active_uis[i].p_zone) = x->f_active_uis[i].p_default; + } +} + +const char* faust_ui_manager_get_parameter_char(int type) +{ + if(type == FAUST_UI_TYPE_BUTTON) + return "button"; + else if(type == FAUST_UI_TYPE_TOGGLE) + return "toggle"; + else if(type == FAUST_UI_TYPE_NUMBER) + return "number"; + else + return "bargraph"; +} + +void faust_ui_manager_print(t_faust_ui_manager* x, char const log) +{ + size_t i; + logpost(x->f_owner, 2+log, " active parameters: %i", (int)x->f_nactive_uis); + for(i = 0; i < x->f_nactive_uis; ++i) + { + logpost(x->f_owner, 2+log, " %i: %s [path:%s - type:%s - init:%g - min:%g - max:%g - current:%g]", (int)i, + x->f_active_uis[i].p_name->s_name, + x->f_active_uis[i].p_longname->s_name, + faust_ui_manager_get_parameter_char(x->f_active_uis[i].p_type), + x->f_active_uis[i].p_default, + x->f_active_uis[i].p_min, + x->f_active_uis[i].p_max, + *x->f_active_uis[i].p_zone); + } + logpost(x->f_owner, 2+log, " passive parameters: %i", (int)x->f_npassive_uis); + for(i = 0; i < x->f_npassive_uis; ++i) + { + logpost(x->f_owner, 2+log, " %i: %s [path:%s - type:%s - init:%g - min:%g - max:%g - current:%g]", (int)i, + x->f_passive_uis[i].p_name->s_name, + x->f_passive_uis[i].p_longname->s_name, + faust_ui_manager_get_parameter_char(x->f_passive_uis[i].p_type), + x->f_passive_uis[i].p_default, + x->f_passive_uis[i].p_min, + x->f_passive_uis[i].p_max, + *x->f_passive_uis[i].p_zone); + } +} + + diff --git a/src/faust_tilde_ui.h b/src/faust_tilde_ui.h new file mode 100644 index 0000000..3806e98 --- /dev/null +++ b/src/faust_tilde_ui.h @@ -0,0 +1,35 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#ifndef FAUST_TILDE_UI_H +#define FAUST_TILDE_UI_H + +#include + +struct _faust_ui_manager; +typedef struct _faust_ui_manager t_faust_ui_manager; + +t_faust_ui_manager* faust_ui_manager_new(t_object* owner); + +void faust_ui_manager_init(t_faust_ui_manager *x, void* dspinstance); + +void faust_ui_manager_free(t_faust_ui_manager *x); + +void faust_ui_manager_clear(t_faust_ui_manager *x); + +char faust_ui_manager_has_passive_ui(t_faust_ui_manager *x); + +char faust_ui_manager_set(t_faust_ui_manager *x, t_symbol* name, t_float f); + +char faust_ui_manager_get(t_faust_ui_manager *x, t_symbol* name, t_float* f); + +void faust_ui_manager_save_states(t_faust_ui_manager *x); + +void faust_ui_manager_restore_states(t_faust_ui_manager *x); + +void faust_ui_manager_print(t_faust_ui_manager* x, char const log); + +#endif diff --git a/src/faustgen_tilde.c b/src/faustgen_tilde.c new file mode 100644 index 0000000..0462cb6 --- /dev/null +++ b/src/faustgen_tilde.c @@ -0,0 +1,409 @@ +/* +// Copyright (c) 2018 - GRAME CNCM - CICM - ANR MUSICOLL - Pierre Guillot. +// For information on usage and redistribution, and for a DISCLAIMER OF ALL +// WARRANTIES, see the file, "LICENSE.txt," in this distribution. +*/ + +#include +#include +#include +#include +#include +#include + +#include + +#include "faust_tilde_ui.h" +#include "faust_tilde_io.h" +#include "faust_tilde_options.h" + +#define MAXFAUSTSTRING 4096 +#define MAXFAUSTOPTIONS 128 + +typedef struct _faustgen_tilde +{ + t_object f_obj; + llvm_dsp_factory* f_dsp_factory; + llvm_dsp* f_dsp_instance; + + FAUSTFLOAT** f_signal_matrix; + FAUSTFLOAT* f_signal_aligned; + size_t f_signal_aligned_size; + + t_faust_ui_manager* f_ui_manager; + t_faust_io_manager* f_io_manager; + t_faust_opt_manager* f_opt_manager; + + t_symbol* f_dsp_name; + t_float f_dummy; + t_clock* f_clock; + double f_clock_time; + long f_time; +} t_faustgen_tilde; + +static t_class *faustgen_tilde_class; + + +////////////////////////////////////////////////////////////////////////////////////////////////// +// FAUST INTERFACE // +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faustgen_tilde_delete_instance(t_faustgen_tilde *x) +{ + if(x->f_dsp_instance) + { + deleteCDSPInstance(x->f_dsp_instance); + } + x->f_dsp_instance = NULL; +} + +static void faustgen_tilde_delete_factory(t_faustgen_tilde *x) +{ + faustgen_tilde_delete_instance(x); + if(x->f_dsp_factory) + { + deleteCDSPFactory(x->f_dsp_factory); + } + x->f_dsp_factory = NULL; +} + +static void faustgen_tilde_compile(t_faustgen_tilde *x) +{ + char const* filepath; + int dspstate = canvas_suspend_dsp(); + if(!x->f_dsp_name) + { + return; + } + filepath = faust_opt_manager_get_full_path(x->f_opt_manager, x->f_dsp_name->s_name); + if(filepath) + { + char errors[MAXFAUSTSTRING]; + int noptions = (int)faust_opt_manager_get_noptions(x->f_opt_manager); + char const** options = faust_opt_manager_get_options(x->f_opt_manager); + faustgen_tilde_delete_instance(x); + faustgen_tilde_delete_factory(x); + faust_ui_manager_clear(x->f_ui_manager); + + x->f_dsp_factory = createCDSPFactoryFromFile(filepath, noptions, options, "", errors, -1); + if(strnlen(errors, MAXFAUSTSTRING)) + { + pd_error(x, "faustgen~: try to load %s", filepath); + pd_error(x, "faustgen~: %s", errors); + x->f_dsp_factory = NULL; + + canvas_resume_dsp(dspstate); + return; + } + + x->f_dsp_instance = createCDSPInstance(x->f_dsp_factory); + if(x->f_dsp_instance) + { + const int ninputs = getNumInputsCDSPInstance(x->f_dsp_instance); + const int noutputs = getNumOutputsCDSPInstance(x->f_dsp_instance); + logpost(x, 3, "\nfaustgen~: compilation from source '%s' succeeded", x->f_dsp_name->s_name); + faust_ui_manager_init(x->f_ui_manager, x->f_dsp_instance); + faust_io_manager_init(x->f_io_manager, ninputs, noutputs, faust_ui_manager_has_passive_ui(x->f_ui_manager)); + + canvas_resume_dsp(dspstate); + return; + } + + pd_error(x, "faustgen~: memory allocation failed - instance"); + canvas_resume_dsp(dspstate); + return; + } + pd_error(x, "faustgen~: source file not found %s", x->f_dsp_name->s_name); + canvas_resume_dsp(dspstate); +} + +static void faustgen_tilde_compile_options(t_faustgen_tilde *x, t_symbol* s, int argc, t_atom* argv) +{ + faust_opt_manager_parse_compile_options(x->f_opt_manager, argc, argv); + faustgen_tilde_compile(x); +} + +static void faustgen_tilde_read(t_faustgen_tilde *x, t_symbol* s) +{ + x->f_dsp_name = s; + faustgen_tilde_compile(x); +} + +static long faustgen_tilde_get_time(t_faustgen_tilde *x) +{ + struct stat attrib; + stat(faust_opt_manager_get_full_path(x->f_opt_manager, x->f_dsp_name->s_name), &attrib); + return attrib.st_ctime; +} + +static void faustgen_tilde_autocompile_tick(t_faustgen_tilde *x) +{ + long ntime = faustgen_tilde_get_time(x); + if(ntime != x->f_time) + { + x->f_time = ntime; + faustgen_tilde_compile(x); + } + clock_delay(x->f_clock, x->f_clock_time); +} + +static void faustgen_tilde_autocompile(t_faustgen_tilde *x, t_symbol* s, int argc, t_atom* argv) +{ + float state = atom_getfloatarg(0, argc, argv); + if(fabsf(state) > FLT_EPSILON) + { + float time = atom_getfloatarg(1, argc, argv); + x->f_clock_time = (time > FLT_EPSILON) ? (double)time : 100.; + x->f_time = faustgen_tilde_get_time(x); + clock_delay(x->f_clock, x->f_clock_time); + } + else + { + clock_unset(x->f_clock); + } +} + +static void faustgen_tilde_print_parameters(t_faustgen_tilde *x) +{ + faust_io_manager_print(x->f_io_manager, 0); + faust_opt_manager_print(x->f_opt_manager, 0); + faust_ui_manager_print(x->f_ui_manager, 0); +} + + +////////////////////////////////////////////////////////////////////////////////////////////////// +// PURE DATA GENERIC INTERFACE // +////////////////////////////////////////////////////////////////////////////////////////////////// + +static void faustgen_tilde_anything(t_faustgen_tilde *x, t_symbol* s, int argc, t_atom* argv) +{ + if(x->f_dsp_instance) + { + if(!argc) + { + t_float value; + if(!faust_ui_manager_get(x->f_ui_manager, s, &value)) + { + t_atom av; + SETFLOAT(&av, value); + outlet_anything(faust_io_manager_get_extra_output(x->f_io_manager), s, 0, &av); + return; + } + pd_error(x, "faustgen~: passive parameter '%s' not defined", s->s_name); + return; + } + else if(argc == 1) + { + if(argv[0].a_type != A_FLOAT) + { + pd_error(x, "faustgen~: active parameter requires a float value"); + return; + } + if(!faust_ui_manager_set(x->f_ui_manager, s, argv[0].a_w.w_float)) + { + return; + } + pd_error(x, "faustgen~: active parameter '%s' not defined", s->s_name); + return; + } + else + { + int i, start; + char name[MAXFAUSTSTRING]; + if(argv[0].a_type != A_FLOAT) + { + pd_error(x, "faustgen~: list parameters requires a first index"); + return; + } + start = (int)argv[0].a_w.w_float; + for(i = 0; i < argc - 1; ++i) + { + if(start+i < 10) + { + sprintf(name, "%s %i", s->s_name, start+i); + } + else if(start+i < 100) + { + sprintf(name, "%s %i", s->s_name, start+i); + } + else + { + sprintf(name, "%s%i", s->s_name, start+i); + } + if(argv[i+1].a_type != A_FLOAT) + { + pd_error(x, "faustgen~: active parameter requires a float value"); + } + if(faust_ui_manager_set(x->f_ui_manager, gensym(name), argv[i+1].a_w.w_float)) + { + pd_error(x, "faustgen~: active parameter '%s' not defined", name); + return; + } + } + return; + } + } + pd_error(x, "faustgen~: no dsp instance"); +} + +static t_int *faustgen_tilde_perform(t_int *w) +{ + int i, j; + llvm_dsp *dsp = (llvm_dsp *)w[1]; + int const nsamples = (int)w[2]; + int const ninputs = (int)w[3]; + int const noutputs = (int)w[4]; + FAUSTFLOAT** faustsigs = (FAUSTFLOAT **)w[5]; + t_sample const** realinputs = (t_sample const**)w[6]; + t_sample** realoutputs = (t_sample **)w[7]; + for(i = 0; i < ninputs; ++i) + { + for(j = 0; j < nsamples; ++j) + { + faustsigs[i][j] = (FAUSTFLOAT)realinputs[i][j]; + } + } + computeCDSPInstance(dsp, nsamples, faustsigs, faustsigs+ninputs); + for(i = 0; i < noutputs; ++i) + { + for(j = 0; j < nsamples; ++j) + { + realoutputs[i][j] = (t_sample)faustsigs[ninputs+i][j]; + } + } + return (w+8); +} + +static void faustgen_tilde_free_signal(t_faustgen_tilde *x) +{ + if(x->f_signal_aligned) + { + free(x->f_signal_aligned); + } + x->f_signal_aligned = NULL; + if(x->f_signal_matrix) + { + free(x->f_signal_matrix); + } + x->f_signal_matrix = NULL; +} + +static void faustgen_tilde_dsp(t_faustgen_tilde *x, t_signal **sp) +{ + if(x->f_dsp_instance) + { + char initialized = getSampleRateCDSPInstance(x->f_dsp_instance) != sp[0]->s_sr; + if(initialized) + { + faust_ui_manager_save_states(x->f_ui_manager); + initCDSPInstance(x->f_dsp_instance, sp[0]->s_sr); + } + if(!faust_io_manager_prepare(x->f_io_manager, sp)) + { + size_t i; + size_t const ninputs = faust_io_manager_get_ninputs(x->f_io_manager); + size_t const noutputs = faust_io_manager_get_noutputs(x->f_io_manager); + size_t const nsamples = (size_t)sp[0]->s_n; + + faustgen_tilde_free_signal(x); + x->f_signal_aligned = (t_sample *)malloc((ninputs + noutputs) * nsamples * sizeof(FAUSTFLOAT)); + if(!x->f_signal_aligned) + { + pd_error(x, "memory allocation failed"); + return; + } + x->f_signal_matrix = (FAUSTFLOAT **)malloc((ninputs + noutputs) * sizeof(FAUSTFLOAT *)); + if(!x->f_signal_matrix) + { + pd_error(x, "memory allocation failed"); + return; + } + for(i = 0; i < (ninputs + noutputs); ++i) + { + x->f_signal_matrix[i] = (x->f_signal_aligned+(i*nsamples)); + } + dsp_add((t_perfroutine)faustgen_tilde_perform, 7, + (t_int)x->f_dsp_instance, (t_int)nsamples, (t_int)ninputs, (t_int)noutputs, + (t_int)x->f_signal_matrix, + (t_int)faust_io_manager_get_input_signals(x->f_io_manager), + (t_int)faust_io_manager_get_output_signals(x->f_io_manager)); + } + if(initialized) + { + faust_ui_manager_restore_states(x->f_ui_manager); + } + } +} + +static void faustgen_tilde_free(t_faustgen_tilde *x) +{ + faustgen_tilde_delete_instance(x); + faustgen_tilde_delete_factory(x); + faust_ui_manager_free(x->f_ui_manager); + faust_io_manager_free(x->f_io_manager); + faust_opt_manager_free(x->f_opt_manager); +} + +static void *faustgen_tilde_new(t_symbol* s, int argc, t_atom* argv) +{ + t_faustgen_tilde* x = (t_faustgen_tilde *)pd_new(faustgen_tilde_class); + if(x) + { + x->f_dsp_factory = NULL; + x->f_dsp_instance = NULL; + + x->f_signal_matrix = NULL; + x->f_signal_aligned = NULL; + x->f_signal_aligned_size = 0; + + x->f_ui_manager = faust_ui_manager_new((t_object *)x); + x->f_io_manager = faust_io_manager_new((t_object *)x, canvas_getcurrent()); + x->f_opt_manager = faust_opt_manager_new((t_object *)x, canvas_getcurrent()); + x->f_dsp_name = atom_getsymbolarg(0, argc, argv); + x->f_clock = clock_new(x, (t_method)faustgen_tilde_autocompile_tick); + faust_opt_manager_parse_compile_options(x->f_opt_manager, argc-1, argv+1); + if(!argc) + { + return x; + } + faustgen_tilde_compile(x); + if(!x->f_dsp_instance) + { + faustgen_tilde_free(x); + return NULL; + } + } + return x; +} + +void faustgen_tilde_setup(void) +{ + t_class* c = class_new(gensym("faustgen~"), + (t_newmethod)faustgen_tilde_new, (t_method)faustgen_tilde_free, + sizeof(t_faustgen_tilde), CLASS_DEFAULT, A_GIMME, 0); + + if(c) + { + class_addmethod(c, (t_method)faustgen_tilde_dsp, gensym("dsp"), A_CANT); + class_addmethod(c, (t_method)faustgen_tilde_compile, gensym("compile"), A_NULL); + class_addmethod(c, (t_method)faustgen_tilde_compile_options, gensym("compileoptions"), A_GIMME); + class_addmethod(c, (t_method)faustgen_tilde_autocompile, gensym("autocompile"), A_GIMME); + class_addmethod(c, (t_method)faustgen_tilde_print_parameters, gensym("print"), A_NULL); + + //class_addmethod(c, (t_method)faustgen_tilde_read, gensym("read"), A_SYMBOL); + class_addanything(c, (t_method)faustgen_tilde_anything); + + CLASS_MAINSIGNALIN(c, t_faustgen_tilde, f_dummy); + logpost(NULL, 3, "Faust website: faust.grame.fr"); + logpost(NULL, 3, "Faust development: GRAME"); + + logpost(NULL, 3, "faustgen~ compiler version: %s", getCLibFaustVersion()); + logpost(NULL, 3, "faustgen~ default include directory: %s", class_gethelpdir(c)); + logpost(NULL, 3, "faustgen~ institutions: CICM - ANR MUSICOLL"); + logpost(NULL, 3, "faustgen~ external author: Pierre Guillot"); + logpost(NULL, 3, "faustgen~ website: github.com/CICM/faust-pd"); + } + + faustgen_tilde_class = c; +} +