espd - tutorial
Hi all!
I had some time during vacations and I wanted to try running Miller's espd version. Here's a small tutorial.
The development board I bought: ESP32-LyraT > Mouser | Aliexpress
INSTALL ESP-IDF (IoT development framework)
mkdir ~/esp && cd ~/esp
git clone -b v4.4.2 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32
INSTALL ESP-ADF (audio development kit)
cd ~/esp && git clone --recursive https://github.com/espressif/esp-adf.git
SETUP ENV VAR
export ADF_PATH=~/esp/esp-adf && . ~/esp/esp-idf/export.sh
ESPD
download espd: http://msp.ucsd.edu/ideas/espd/
cd espd
git clone https://github.com/pure-data/pure-data.git pd
cd pd
git checkout 05bf346fa32510fd191fe77de24b3ea1c481f5ff
git apply ../patches/*.patch
Edit main/espd.h put your wifi credentials and the IP of the computer that will control espd:
#define CONFIG_ESP_WIFI_SSID "..."
#define CONFIG_ESP_WIFI_PASSWORD "..."
#define CONFIG_ESP_WIFI_SENDADDR "...."
mv sdkconfig.lyrat sdkconfig
idf.py build
idf.py -p /dev/ttyUSB0 flash (hold boot and then press reset on lyrat)
idf.py -p /dev/ttyUSB0 monitor (Ctrl+] to exit)
HOST
- open pd installed on (SENDADDR)
- open test-patch/host-patch.pd
If connected this message (ESPD: sendtcp: waiting for socket) will stop and you will see the mac address in the host patch.
1- click on [send pf begin-new poodle .<
2- click on [line 0, auto< to send the defined patch (esp-patch.pd)
3 - click [send pd end-new<
4 - connect headphone, play with [send f 440< and [send f 660<
Custom patch:
- Use mono [dac~ 1] only
- Add this to your patch:
- in host-patch.pd change [read your-patch< -> [text define patch] redo step 1 to 3
TODO
Would love to play more with the code, right now I am not able to load complex vanilla patch. Also using the AUX (or built-in microphone) would be awesome (but I'm wondering about the round-trip latency (would it be under 15ms)).
Controlling Pd from another programme
@Worik Not sure what you are looking for.....
If you want to open a patch from the command line you can open Pd and a patch with a batch file...... in windows it would look something like this....
"C:\Program Files (x86)\pd\bin\pd.com" -path C:\Users\David\Desktop\PDMusic\Minx -path C:\Program_Files_(x86)\pd\extra\readanysf~\ -r 44100 -asio -nomidi -audioindev 20 -audiooutdev 15 -inchannels 32 -outchannels 22 -audiobuf 2 -blocksize 64 -callback -nosleep -open Minx_Run.pd
exit`
which on my system opens Minx_run.Pd and tells Pd where to find it........ \PdMusic\Minx
It also sets a load of command line switches...... to set up audio for this very specific instance (useful!).
There will be similar methods in other os's.
When you want to close the patch (and Pd) you kill the Dos window that the batch file created.
Messages can be sent to Pd to close a specific patch..... but another patch will have to be open (probably the one receiving the message) or Pd will terminate.
It can be done from within the patch but its complicated........ https://forum.pdpatchrepo.info/topic/11710/closing-patches-without-pd-crashing-hopefully-in-an-elegant-way ...... and not easy.
If you want to keep Pd open and control from another program........ then as @seb-harmonik.ar describes........ but the menuclose message might crash Pd if another patch (any patch) is not open........ https://forum.pdpatchrepo.info/topic/4063/close-patch-window-command-object
Anyway, it is cleaner to use a second patch to receive your messages and close the desired patch.
David.
Can't install purr-data on Manjaro
Hey, I'm trying to get purr-data to work on my fresh Manjaro XFCE install, but it does not work. Any help is greatly appreciated!
$ yay purr-data
7 aur/purrdata-faust 0.18-1 (+0 0.00)
Run Faust signal processors in Pd, Purr-Data version
6 aur/purrdata-pure 0.26-1 (+0 0.00)
Loader plugin for the Pure programming language, Purr-Data version
5 aur/purrdata-lv2plugin-git 25.e00f302-1 (+0 0.00)
LV2 plugin host for Pd, Purr-Data version
4 aur/purrdata-mdnsbrowser-git 8.88d2b0c-1 (+0 0.00)
Zeroconf service advertising and discovery for Pd, Purr-Data version
3 aur/purrdata-touchosc-git 44.443c793-1 (+0 0.00)
A TouchOSC MIDI bridge for Pd, Purr-Data version
2 aur/purr-data-git 2.12.0.r4366.6d94e10b-1 (+2 0.00)
Jonathan Wilkes' nw.js variant of Pd-L2Ork (git version)
1 aur/purr-data 2.12.0.r4346.aeb24d89-1 (+6 0.03) (Out-of-date: 2021-06-17)
Jonathan Wilkes' nw.js variant of Pd-L2Ork (git version)
==> Packages to install (eg: 1 2 3, 1-3 or ^4)
==> 2
:: There are 2 providers available for gconf:
:: Repository AUR
1) gconf 2) gconf-gtk2
Enter a number (default=1): ==>
:: Checking for conflicts...
:: Checking for inner conflicts...
[Aur:2] gconf-3.2.6+11+g07808097-10 purr-data-git-2.12.0.r4366.6d94e10b-1
2 gconf (Build Files Exist)
1 purr-data-git
==> Packages to cleanBuild?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> a
:: Deleting (1/1): /home/olav/.cache/yay/gconf
:: (1/2) Downloaded PKGBUILD: gconf
:: (2/2) Downloaded PKGBUILD: purr-data-git
2 gconf (Build Files Exist)
1 purr-data-git (Build Files Exist)
==> Diffs to show?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==>
:: (1/2) Parsing SRCINFO: gconf
:: (2/2) Parsing SRCINFO: purr-data-git
==> Making package: gconf 3.2.6+11+g07808097-10 (Wed 09 Feb 2022 10:23:23 PM CET)
==> Retrieving sources...
-> Cloning gconf git repo...
Cloning into bare repository '/home/olav/.cache/yay/gconf/gconf'...
==> Making package: purr-data-git 2.12.0.r4366.6d94e10b-1 (Wed 09 Feb 2022 10:23:23 PM CET)
==> Retrieving sources...
-> Cloning purr-data-git git repo...
Cloning into bare repository '/home/olav/.cache/yay/purr-data-git/purr-data-git'...
remote: Enumerating objects: 21531, done.
remote: Enumerating objects: 63399, done.
remote: Counting objects: 100% (1852/1852), done.
remote: Compressing objects: 100% (641/641), done.
remote: Total 21531 (delta 0), reused 0 (delta 0), pack-reused 21531
Receiving objects: 100% (21531/21531), 10.88 MiB | 9.46 MiB/s, done.
Resolving deltas: 100% (17681/17681), done.1 KiB | 704.00 KiB/s
-> Found 01_xml-gettext-domain.patch388.01 KiB | 704.00 KiB/s
-> Found gconf-reload.patch
-> Found gconf-merge-schema
-> Found gconfpkg
-> Found gconf-install.hook
-> Found gconf-remove.hook
==> Validating source files with sha256sums...
gconf ... Skipped
01_xml-gettext-domain.patch ... Passed
gconf-reload.patch ... Passed
gconf-merge-schema ... Passed
gconfpkg ... Passed
gconf-install.hook ... Passed
gconf-remove.hook ... Passed
remote: Total 63399 (delta 1106), reused 1786 (delta 1052), pack-reused 61547
Receiving objects: 100% (63399/63399), 177.19 MiB | 5.71 MiB/s, done.
Resolving deltas: 100% (33721/33721), done.
-> Downloading nwjs-sdk-v0.24.4-linux-x64.tar.gz...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 86.7M 100 86.7M 0 0 3966k 0 0:00:22 0:00:22 --:--:-- 8404k
==> Validating source files with md5sums...
purr-data-git ... Skipped
==> Validating source_x86_64 files with md5sums...
nwjs-sdk-v0.24.4-linux-x64.tar.gz ... Passed
==> Making package: gconf 3.2.6+11+g07808097-10 (Wed 09 Feb 2022 10:24:19 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
-> Updating gconf git repo...
Fetching origin
-> Found 01_xml-gettext-domain.patch
-> Found gconf-reload.patch
-> Found gconf-merge-schema
-> Found gconfpkg
-> Found gconf-install.hook
-> Found gconf-remove.hook
==> Validating source files with sha256sums...
gconf ... Skipped
01_xml-gettext-domain.patch ... Passed
gconf-reload.patch ... Passed
gconf-merge-schema ... Passed
gconfpkg ... Passed
gconf-install.hook ... Passed
gconf-remove.hook ... Passed
==> Removing existing $srcdir/ directory...
==> Extracting sources...
-> Creating working copy of gconf git repo...
Cloning into 'gconf'...
done.
Switched to a new branch 'makepkg'
==> Starting prepare()...
/home/olav/.cache/yay/gconf/PKGBUILD: line 30: patch: command not found
==> ERROR: A failure occurred in prepare().
Aborting...
-> error making: gconf
And
yay purr-data
7 aur/purrdata-faust 0.18-1 (+0 0.00)
Run Faust signal processors in Pd, Purr-Data version
6 aur/purrdata-pure 0.26-1 (+0 0.00)
Loader plugin for the Pure programming language, Purr-Data version
5 aur/purrdata-lv2plugin-git 25.e00f302-1 (+0 0.00)
LV2 plugin host for Pd, Purr-Data version
4 aur/purrdata-mdnsbrowser-git 8.88d2b0c-1 (+0 0.00)
Zeroconf service advertising and discovery for Pd, Purr-Data version
3 aur/purrdata-touchosc-git 44.443c793-1 (+0 0.00)
A TouchOSC MIDI bridge for Pd, Purr-Data version
2 aur/purr-data-git 2.12.0.r4366.6d94e10b-1 (+2 0.00)
Jonathan Wilkes' nw.js variant of Pd-L2Ork (git version)
1 aur/purr-data 2.12.0.r4346.aeb24d89-1 (+6 0.03) (Out-of-date: 2021-06-17)
Jonathan Wilkes' nw.js variant of Pd-L2Ork (git version)
==> Packages to install (eg: 1 2 3, 1-3 or ^4)
==> 2
:: There are 2 providers available for gconf:
:: Repository AUR
1) gconf 2) gconf-gtk2
Enter a number (default=1): ==>
:: Checking for conflicts...
:: Checking for inner conflicts...
[Aur:2] gconf-3.2.6+11+g07808097-10 purr-data-git-2.12.0.r4366.6d94e10b-1
2 gconf (Build Files Exist)
1 purr-data-git
==> Packages to cleanBuild?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> a
:: Deleting (1/1): /home/olav/.cache/yay/gconf
:: (1/2) Downloaded PKGBUILD: gconf
:: (2/2) Downloaded PKGBUILD: purr-data-git
2 gconf (Build Files Exist)
1 purr-data-git (Build Files Exist)
==> Diffs to show?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==>
:: (1/2) Parsing SRCINFO: gconf
:: (2/2) Parsing SRCINFO: purr-data-git
==> Making package: gconf 3.2.6+11+g07808097-10 (Wed 09 Feb 2022 10:23:23 PM CET)
==> Retrieving sources...
-> Cloning gconf git repo...
Cloning into bare repository '/home/olav/.cache/yay/gconf/gconf'...
==> Making package: purr-data-git 2.12.0.r4366.6d94e10b-1 (Wed 09 Feb 2022 10:23:23 PM CET)
==> Retrieving sources...
-> Cloning purr-data-git git repo...
Cloning into bare repository '/home/olav/.cache/yay/purr-data-git/purr-data-git'...
remote: Enumerating objects: 21531, done.
remote: Enumerating objects: 63399, done.
remote: Counting objects: 100% (1852/1852), done.
remote: Compressing objects: 100% (641/641), done.
remote: Total 21531 (delta 0), reused 0 (delta 0), pack-reused 21531
Receiving objects: 100% (21531/21531), 10.88 MiB | 9.46 MiB/s, done.
Resolving deltas: 100% (17681/17681), done.1 KiB | 704.00 KiB/s
-> Found 01_xml-gettext-domain.patch388.01 KiB | 704.00 KiB/s
-> Found gconf-reload.patch
-> Found gconf-merge-schema
-> Found gconfpkg
-> Found gconf-install.hook
-> Found gconf-remove.hook
==> Validating source files with sha256sums...
gconf ... Skipped
01_xml-gettext-domain.patch ... Passed
gconf-reload.patch ... Passed
gconf-merge-schema ... Passed
gconfpkg ... Passed
gconf-install.hook ... Passed
gconf-remove.hook ... Passed
remote: Total 63399 (delta 1106), reused 1786 (delta 1052), pack-reused 61547
Receiving objects: 100% (63399/63399), 177.19 MiB | 5.71 MiB/s, done.
Resolving deltas: 100% (33721/33721), done.
-> Downloading nwjs-sdk-v0.24.4-linux-x64.tar.gz...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 86.7M 100 86.7M 0 0 3966k 0 0:00:22 0:00:22 --:--:-- 8404k
==> Validating source files with md5sums...
purr-data-git ... Skipped
==> Validating source_x86_64 files with md5sums...
nwjs-sdk-v0.24.4-linux-x64.tar.gz ... Passed
==> Making package: gconf 3.2.6+11+g07808097-10 (Wed 09 Feb 2022 10:24:19 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
-> Updating gconf git repo...
Fetching origin
-> Found 01_xml-gettext-domain.patch
-> Found gconf-reload.patch
-> Found gconf-merge-schema
-> Found gconfpkg
-> Found gconf-install.hook
-> Found gconf-remove.hook
==> Validating source files with sha256sums...
gconf ... Skipped
01_xml-gettext-domain.patch ... Passed
gconf-reload.patch ... Passed
gconf-merge-schema ... Passed
gconfpkg ... Passed
gconf-install.hook ... Passed
gconf-remove.hook ... Passed
==> Removing existing $srcdir/ directory...
==> Extracting sources...
-> Creating working copy of gconf git repo...
Cloning into 'gconf'...
done.
Switched to a new branch 'makepkg'
==> Starting prepare()...
/home/olav/.cache/yay/gconf/PKGBUILD: line 30: patch: command not found
==> ERROR: A failure occurred in prepare().
Aborting...
-> error making: gconf
[olav@AMD-Computer ~]$ yay purr-data
7 aur/purrdata-faust 0.18-1 (+0 0.00)
Run Faust signal processors in Pd, Purr-Data version
6 aur/purrdata-pure 0.26-1 (+0 0.00)
Loader plugin for the Pure programming language, Purr-Data version
5 aur/purrdata-lv2plugin-git 25.e00f302-1 (+0 0.00)
LV2 plugin host for Pd, Purr-Data version
4 aur/purrdata-mdnsbrowser-git 8.88d2b0c-1 (+0 0.00)
Zeroconf service advertising and discovery for Pd, Purr-Data version
3 aur/purrdata-touchosc-git 44.443c793-1 (+0 0.00)
A TouchOSC MIDI bridge for Pd, Purr-Data version
2 aur/purr-data-git 2.12.0.r4366.6d94e10b-1 (+2 0.00)
Jonathan Wilkes' nw.js variant of Pd-L2Ork (git version)
1 aur/purr-data 2.12.0.r4346.aeb24d89-1 (+6 0.03) (Out-of-date: 2021-06-17)
Jonathan Wilkes' nw.js variant of Pd-L2Ork (git version)
==> Packages to install (eg: 1 2 3, 1-3 or ^4)
==> 2
:: There are 2 providers available for gconf:
:: Repository AUR
1) gconf 2) gconf-gtk2
Enter a number (default=1): ==> 2
:: Checking for conflicts...
:: Checking for inner conflicts...
[Aur:2] gconf-gtk2-3.2.6-5 purr-data-git-2.12.0.r4366.6d94e10b-1
2 gconf-gtk2 (Build Files Exist)
1 purr-data-git (Build Files Exist)
==> Packages to cleanBuild?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==> a
:: Deleting (1/2): /home/olav/.cache/yay/gconf-gtk2
:: Deleting (2/2): /home/olav/.cache/yay/purr-data-git
:: (1/2) Downloaded PKGBUILD: purr-data-git
:: (2/2) Downloaded PKGBUILD: gconf-gtk2
2 gconf-gtk2 (Build Files Exist)
1 purr-data-git (Build Files Exist)
==> Diffs to show?
==> [N]one [A]ll [Ab]ort [I]nstalled [No]tInstalled or (1 2 3, 1-3, ^4)
==>
:: (1/2) Parsing SRCINFO: gconf-gtk2
:: (2/2) Parsing SRCINFO: purr-data-git
==> Making package: purr-data-git 2.12.0.r4366.6d94e10b-1 (Wed 09 Feb 2022 10:40:58 PM CET)
==> Retrieving sources...
==> Making package: gconf-gtk2 3.2.6-5 (Wed 09 Feb 2022 10:40:58 PM CET)
==> Retrieving sources...
-> Cloning purr-data-git git repo...
Cloning into bare repository '/home/olav/.cache/yay/purr-data-git/purr-data-git'...
-> Downloading GConf-3.2.6.tar.xz...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
100 1523k 100 1523k 0 0 1610k 0 --:--:-- --:--:-- --:--:-- 1610k
-> Found gconf-merge-schema
-> Found gconfpkg
-> Found gconf-reload.patch
-> Found gconf-install.hook
-> Found gconf-remove.hook
-> Found 01_xml-gettext-domain.patch
-> Found dbus-dontspew.patch
-> Found gsettings-data-convert-fix-invalid-schema-path.patch
==> Validating source files with sha256sums...
GConf-3.2.6.tar.xz ... Passed
gconf-merge-schema ... Passed
gconfpkg ... Passed
gconf-reload.patch ... Passed
gconf-install.hook ... Passed
gconf-remove.hook ... Passed
01_xml-gettext-domain.patch ... Passed
dbus-dontspew.patch ... Passed
gsettings-data-convert-fix-invalid-schema-path.patch ... Passed
remote: Enumerating objects: 63399, done.
remote: Counting objects: 100% (1852/1852), done.
remote: Compressing objects: 100% (641/641), done.
remote: Total 63399 (delta 1106), reused 1786 (delta 1052), pack-reused 61547
Receiving objects: 100% (63399/63399), 177.19 MiB | 9.76 MiB/s, done.
Resolving deltas: 100% (33721/33721), done.
-> Downloading nwjs-sdk-v0.24.4-linux-x64.tar.gz...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 86.7M 100 86.7M 0 0 11.7M 0 0:00:07 0:00:07 --:--:-- 14.4M
==> Validating source files with md5sums...
purr-data-git ... Skipped
==> Validating source_x86_64 files with md5sums...
nwjs-sdk-v0.24.4-linux-x64.tar.gz ... Passed
==> Making package: gconf-gtk2 3.2.6-5 (Wed 09 Feb 2022 10:41:26 PM CET)
==> Checking runtime dependencies...
==> Checking buildtime dependencies...
==> Retrieving sources...
-> Found GConf-3.2.6.tar.xz
-> Found gconf-merge-schema
-> Found gconfpkg
-> Found gconf-reload.patch
-> Found gconf-install.hook
-> Found gconf-remove.hook
-> Found 01_xml-gettext-domain.patch
-> Found dbus-dontspew.patch
-> Found gsettings-data-convert-fix-invalid-schema-path.patch
==> Validating source files with sha256sums...
GConf-3.2.6.tar.xz ... Passed
gconf-merge-schema ... Passed
gconfpkg ... Passed
gconf-reload.patch ... Passed
gconf-install.hook ... Passed
gconf-remove.hook ... Passed
01_xml-gettext-domain.patch ... Passed
dbus-dontspew.patch ... Passed
gsettings-data-convert-fix-invalid-schema-path.patch ... Passed
==> Removing existing $srcdir/ directory...
==> Extracting sources...
-> Extracting GConf-3.2.6.tar.xz with bsdtar
==> Starting prepare()...
/home/olav/.cache/yay/gconf-gtk2/PKGBUILD: line 39: patch: command not found
==> ERROR: A failure occurred in prepare().
Aborting...
-> error making: gconf-gtk2
Dynamically patched vslider with local send symbol
@oid This is a problem from my 2nd ever dynamic patch, so I wouldn't try to read deep meaning into my questions . Like my first dynamic patch, it's just a patch that generates the repetitive, static parts of other patches--a way to reduce the tedium of having to edit multiple send/receive names by hand, that's all. I'm expecting to have to cut and paste from this helper patch into the patch I'm really trying to write, so the value of $0 in the generating patch is irrelevant. Is that reasonable? In a patch that needed its UI to be dynamically generated, your way would make total sense, but I'm def not there yet. Also, regarding your other topic, I think the message that dynamically generates a vslider can itself be static, so I'm not sure that add2 technique is applicable.
@ingox OK, now I'm getting the same results as you, which is odd because the patch I've presented is just a small example from a larger patch that was giving me trouble. After discovering the $\$0
syntax I applied it to that larger patch, saw that it too was working, and then posted this topic. But now my larger patch is broken, which makes me believe that the system is behaving differently since running your patches (and that I wasn't previously hallucinating). But that can't be true, right?
So here's another small patch to demonstrate how my larger patch is (now) broken: dynamicPatchVerticalSlider2.pd
See how \$0
is just generating a 0
in the send symbol? When I save and reload it to test the fader (which doesn't work), the backslash gets dropped from the creation message!
So next I try falling back to the syntax I got working earlier, and the generated vslider send symbol looks good
and on reloading it I can confirm that it is good, but now I can't use my generating patch because $1 is backslash escaped!
Paths and organizing .pd files for use.
@raynovich I use the [declare]
object instead of paths, keeps the paths list shorter and more manageable and also gives you a nice list of dependencies right in the patch so you never have to wade through the patch trying to figure out what it needs if you want to share the patch or copy it to a different machine. If you need a sub-folder you just declare the sub-folder. Use absolute paths when you declare, this way you can move the patch and it will still find what it needs. I generally have a sub-patch in each patch for declares and I avoid declaring folders, just declare the abstraction directly so I never have to try and figure out which abstractions a given patch uses, just open the declare sub-patch and it is all there. In my pd folder I have all my current patches, an abstractions folder, a folder for patches I am not currently working on and a folder for reference patches. I do my best to avoid making abstractions which only have use in a single patch, I will figure out how to generalize it to make it more useful for other patches so it can live in my abstraction folder without cluttering it up and helps avoid needing folders for patches. When a patch must have a folder it goes in the pd directory with the patch and I declare it instead of keeping the patch in it's own directory, this is mainly to minimize having to navigate folders as much.
Using [declare]
to explicitly declare individual abstractions also makes it easier to clean your abstraction folder, a simple shell script can check for abstractions which are not used by any patch or ones that just get used by a single patch so you can check them out to see if they are worth keeping or should be moved too the folder of that one patch which uses them.
Few questions about oversampling
Hi,
About a year ago I started to learn a bit pure data in order to create a patch that would act as a groovebox and that should perform on limited cpu resources since I want it to run on a raspberry pi. First I tried to make somekind of fork of the Martin Brinkmann groovebox patch, even if it allowed me to learn a lot about data flow I didn't went to the core of the patch tweaking with sound generation. This led me to end this attempt at forking MNB groovebox patch because even if I could seperate GUI stuff from sound generation and run it on different thread ect... I couldn't go further in optimization in order to reduce the cpu use.
Then a few weeks ago I decided to start again from scratch my project and this time I wanted to be more patient and learn anything needed in order to be capable of optimizing my patch as much as possible. After making a functional drum machine which runs at 2/3% of cpu with 8 different tracks, 126 steps sequencer, a bit of fx ect... I tried to find synths that would opperate well aside the drum machine. And I basicly didn't find any patch that wouldn't use massive amount of cpu time. So I created my own synths, nothing incredible but I'm happy with what I got, though I noticed some aliasing. I read a bit the floss manual about anti aliasing and apply the method used in the manual(http://write.flossmanuals.net/pure-data/antialiasing/), it work well but my synths almost trippled their cpu use, even if I put all my oscilators in the same subpatch in order to use only one instance of oversampling.
I didn't tried to oversample it less than 16 time but since oversampling is so cpu intensive I'm wondering if there's no other option in order to get a good sound definition at a lower cpu cost. I'm already using banlimited waveform so I don't know what I could do in order to limit the aliasing, especialy for my fm patch where bandlimited waveform isn't very useful in order to reduce aliasing.
Since I want to have at least 4 synth track with some at least one synth having 5 voice polyphony I want to know what the best thing to do. Letting FM aside for this project and use switch~ for oversampling 2 or 4 time my synths that use bandlimited waveform ? Or should I try to run different instances of pd for each synth and controling it from a gui/control patch with netsend(though it wouldn't bring down the cpu use at least it would provide somekind of multithreading for my patch) ? Or is there another way to get some antiliasing ? Or should I review lower my expectation because there is no solution that could provide a decent antialiasing for 4 or more synth running at the same time with a low cpu use in pure data in 2021.
Thanks to everyone that would read my topic and try to give some advice in order to get the best antialising/low cpu use solution.
Closing patches without Pd crashing, hopefully in an elegant way...
EUREKA! I solved the following problem:
Problem: provide a mechanism for allowing patches to self-close without Pd crashing.
Requirements: (1) uses only Pd vanilla; (2) action to close patch starts on the very patch that will be closed.
Solution: copy patch killer.pd in the same folder as the patch to be closed, and send a message containing ";pd open killer.pd <dir>;kill_me symbol patch_to_be_closed.pd":
killer.pd
patch_to_be_closed.pd
Comments: (documented in the killer patch) Pd doesn't deal well with menuclose requests that originate (in a direct chain reaction) from the same patch that wants to be closed, so a separate killer patch is needed, which can be opened by the same patch requesting to be closed. In order to break the direct chain reaction, the solution is to postpone this request and make it appear as being originated inside the killer patch. This is done by storing the received symbol and delaying the message menuclose by 0 ms, which is enough to issue a new chain of events. The killer patch stays alive (but invisible), and any new instances of the killer patch will silently kill the previous instances so that only one killer patch is alive at any given time. [EDIT: I included a safeguard [pipe 1] in the killer patch, check the inline comments]. This implementation fixes the problems with my previous solution and also with the 3-patches method by @ingox, both of which didn't work through a send/receive pair. It also does not depend on dynamic patching.
This has been tested in Pd 0.50-2 and Ubuntu 20.04. I appreciate feedback to confirm if it works in other platforms/versions.
@whale-av Thanks again David for the suggestions (hcs, mouse clicks)! I wasn't too keen on the idea of depending on external libraries, and I also had to abandom the idea of having the killer patch embedded in the patch to be closed.
Purr Data GSoC Projects, 2.15.1
Hi all,
Purr Data 2.15.1 has been released.
We had some build issues and Albert graciously stepped up to help merge the relevant patches and posted the release on github quite quickly:
https://github.com/agraef/purr-data/releases
If you're on Gnu/Linux, do use the OBS repos that he set up. He's posted a very clear guide, and if you use it you'll get Purr updated automatically any time you update the system.
As always, report issues here:
https://git.purrdata.net/jwilkes/purr-data/-/issues
With that out of the way, I'd like to highlight the work our students did for Google Summer of Code Projects that wrapped up over a month ago.
Patch Private Abstractions
This was a feature created by Guillem Bartrina. (Actually, one of several features he added as part of his GSoC project this summer. I'll try to post about his other additions later.) It allows the user to create and use abstractions which get saved in the parent patch. Abstraction names are local to the patch which contains them, which makes for a quite workable and flexible namespacing system that's easy to use and understand.
This is a very tricky feature to design and get right, and Guillem did an excellent job considering various corner cases and optimal UX. Notice in the video that he added a few features which are useful generally for abstractions, too:
- a notification when the user has an unsaved abstraction somewhere in the running instance
- another notification when the user has two or more unsaved abstractions in the running instance. This is quite a handy feature for normal abstractions, too, as it can save you from the headache of overwriting important changes when you're working after midnight on your last cup of coffee!
There are also some helper classes that give some options to ensure that the user doesn't lose data.
Purr Data Webapp
This was another ambitious project with frontend work by Hugo Neves de Carvalho and backend, API, and merging work by Zack Lee.
This project runs the core of Purr Data and a surprisingly large number of all the externals it ships in a webpage. The front end can load, save, close, and "vis" multiple patches and run them from the same backend engine.
Thanks to the way Zack leveraged the emscripten file system, you can even save abstractions and call them from a new patch!
The patch private abstractions have already been merged into Purr Data, and we're currently working on upstreaming the webapp changes into Purr Data as well.
Optimizing pd performances to fit an RPI 3
@Nicolas Danet Thanks for the tip, I didn't knew about Perf on linux it's very handy. I ran a test on each patch/subpatch and got the following:
So I will serach about -GI__printf_fp_l _IO-vfscanf vfprintf plus_pcrf8 and delay_tsc to see to what they match in PD. But if GI_printf and vfprintf are calls used by PD for the GUI object then @alexandros was right and I will replace all GUI object by text ones.
@EEight My problem with switch~ is not that I don't know how to use its syntax but more because splitting each sound processing patch in my patch would divide it into at least 16 different subpatch(probably more). And as far as I experimented the pd~ object I have noticed that running 9 subpatches took more ressources than just running 3. Considering this I'm not sure that implementing switch~ to my patch will introduce a significant gain of processing power. And it is the case it would be effecient if I only used few tracks out of the 8 track grroovebox that I'm working on, disable Fx ect.. and as soon I want to use the full capabilities of the patch it would crash because all the audio processing patch would run with the DSP and the CPU performances would rise again to what I got now.
Maybe I didn't explain it very clearly, so I will rapidly explain it again. My main problem here is that my intitial patch(we'll called it v1) uses 10-12% of CPU, and my motherpatch for different processes(let's call it v2) uses 18-20% + subpatch 1 running at 12-15% and subpatch 2 8-10%. So I got a v1 is runniingn 50% on one core and V2 and its subpatches is running at 30-40 with peak at 60% on four cores. Which is kind of the worst optimization of the history of computing ^^. Though ginving the Perf result I have something to investigate to see where the problem come from. I'll give you update as soon as I found out what to do.
EDIT: I did a bit of search it seems that IO-getc, GI-printf, IO-vfscanf and vfprintf are all functions used to manages stram of data. I'm not sure but I'm sending the value from my GUI/input patch to my auddi processing patch via netsend, maybe the way I'm doing it is not optimal, maybe I should switch to osc~ because it's more effective to stream large numbers of value. Maybe I messed up the way to through values into the subpatches(because if my netsending method is messy it does not explain why I see the same problematic function calls in the subpatches). It coould also be link to the GUI elements since data streaming could be used in in those. But it does not explain why there's the function call in my mother patch that isn't using any GUI elements. To get better result I will find directly in PD source code.
EDIT 2: I found vfprintf in this PD source file "pa_debugprint.c" so it don't validate the few hypothesis I made before, but in my pd window I got repeated messages like "output snd_pcm_delay failed: Unknown error 476 astate 3" they could be the reason of this. Then I also found plus.perf8 here "d_arithmetic.c" it seems relied to operators (/ * = -) I use them to set value to my synth ect... so getting rid of them would be very difficult if not impossible.
Optimizing pd performances to fit an RPI 3
Hello everyone, I'm currently working on somekind of "fork" of a patch I found(it's a groovebox patch coded by Martin Birkmann). It consume quite a lot of CPU, on my current Laptop equiped with an Intel® Core™ i3-6006U CPU, it ran up 50% on the first core. Since i want to be able to run it on a Raspberry Pi 3, running the patch at about 1 ghz on a single core is just not possible. Then I looked up how I could optimizes the use of the cpu, I tried to use some puredata command flag, tried to simplify and hide most of the GUI and even tried to split up the patch with subprocesses with pd~.
First flags, changes of priority, realtime ect... doesn't do anything for the use of CPU. Secondly hiding some GUI maybe help to grab 1% or 2% of CPU. Finaly, I had great hope that pd~ would allow to spread the CPU all across the proccessor allowing me to run it on the RPI 3, but no it's strange the mother patch of the subprocesses is running at 18-20% of CPU use(about 60% on a single core) consuming more than the initial patch that runs at 10-12% of CPU use. And when I'm running the pd subprocesses they also grasp a load of cpu use, They consume about as much as the mother patch, which is quite the opposite of what I wanted...
So is it normal that the use of pd~ just increases the need of CPU time for pd ? Is there another way to split the audio processing in different pd instances s the calculation is shared by different cores ? Is there some things I could improve in the audio processing section that could help lowering the use of CPU ?
Then I have another problem whenever I wanted to activate the dsp when I was on my RPI pure data craches. Is there someone here that knows why ? What command should I use to use the dsp without crash on a rpi ?
If you don't see any solution to my problem then you maybe can help me in an another way? Since my problem is mainly optimisation, if you have some recommandation to gave about some pure data open source groovebox patch that run well on low spec system it would be great.