MIDI port names on Linux
I've progressed with libpd instead :D
I know that this will probably make things more difficult with complicated patches and externals (I would have to compile libpd with support for these externals if I understand correctly), but for simple patches it seems pretty straightforward. I haven't tested it properly yet, but this small script exposes virtual ALSA-MIDI ports in a patchbay (which I can connect to anything) and just forwards notes and CCs to Pd, and receives Pd's notes and CC back and forwards it out to ALSA:
import mido
# install python-rtmidi from pip
from functools import partial
from pylibpd import *
my_client_name='My Libpd Client'
input_port_name='Input'
output_port_name='Output'
# Open Input and Output ports (Rtmidi)
# Creating multiple virtual ports will create multiple clients with the same name.
outport = mido.open_output(output_port_name,virtual=True,client_name=my_client_name)
inport = mido.open_input(name=input_port_name,virtual=True,client_name=my_client_name)
def pd_receive(*s):
print('Printed by pd:', s)
def midi_out(*s):
match s[0]:
case 'note':
if s[3] > 0:
m=mido.Message('note_on', channel=s[1], note=s[2], velocity=s[3])
else:
m=mido.Message('note_off', channel=s[1], note=s[2], velocity=s[3])
case 'cc':
m.mido.Message('control_change', channel=s[1], control=s[2], value=s[3])
outport.send(m)
# Callbacks to receive messages from Pd:
libpd_set_print_callback(pd_receive)
libpd_set_midibyte_callback(pd_receive)
libpd_set_noteon_callback(partial(midi_out,'note'))
libpd_set_controlchange_callback(partial(midi_out,'cc'))
libpd_open_patch('midi_processing.pd','.')
with inport:
for msg in inport:
match msg.type:
case 'note_on':
libpd_noteon(msg.channel,msg.note,msg.velocity)
case 'note_off':
libpd_noteon(msg.channel,msg.note,0)
case 'control_change':
libpd_controlchange(msg.channel,msg.controller,msg.value)
case 'sysex':
libpd_sysrealtime(1,msg.byte)
libpd_release()
And that's it! It's quick & dirty and it will get more complicated if I need to handle any type of MIDI messages, but notes and CCs should do for now.
Looks like this in the patchbay:

MPE support in Pure Data?
@jamcultur said:
I'm thinking about getting an MPE-capable MIDI controller to use with the synth I made in Pure Data. I'd like to enhance my synth to support the MPE features. Has anyone worked with MIDI MPE in Pure Data? Any advice or suggestions?
Based on a couple of quick reads: "In normal MIDI, Channel-wide messages (such as Pitch Bend) are applied to all notes being played on a single MIDI Channel. In MPE, each note is assigned its own MIDI Channel so that those messages can be applied to each note individually" (https://www.midi.org/midi-articles/midi-polyphonic-expression-mpe) and "MPE repurposes MIDI channels as notes instead of instruments. This means you can only have a single instrument on each port or cable and the instrument is limited to a maximum of 16‑note polyphony (one note on each of the 16 channels). Each note can have its own pitch‑bend, mod wheel and other expression messages, meaning you can now emulate the single‑string pitch vibrato of a guitar or violin without having the vibrato applied across the whole instrument" (https://www.soundonsound.com/sound-advice/mpe-midi-polyphonic-expression), it appears to be significantly less complicated than you might think.
MPE: Channel = voice number.
Where do you have voice numbers in Pd?
[clone]
Messages to [clone] should put the voice number leftmost. [notein], [ctlin] etc. put the channel number as the rightmost output. So you'd have to use [pack] and a message box to reorder the numbers. (Also note that MIDI objects report channels 1-16, but [clone 16] will produce voice numbers 0-15 -- easily handled, just don't omit the [- 1] objects.)

I'll admit that I didn't download the full spec, so there might be some fine print that I'm not aware of. But based on the online descriptions, I think it's pretty much like this.
hjh
How to send audio over the network in Pure Data?
@lucassilveira You are using a multicast address...... With multicast the listener has to join the group.... so you need to tell [udpreceive~] to listen to that address range...... [udpreceive~ 3000 2 239.255.255.250]
Open [pd multicast] in the [udpsend~] help file. You will see that you can also specify that it will multicast on only the Wi-Fi or only the Ethernet connection from your computer, and set the "Time To Live" TTL to limit how far the packets will propagate on the network.
When you receive on the same computer you are already in the multicast group as the datagrams have been looped back by the OS (usually). All ports on the host are available for UDP without a connection, unlike TCP where a return connection is necessary and could be refused by the OS...
With a broadcast address the stream is broadcast everywhere, even to the internet, so insecure, and it will flood the network...... but then you do not need to specify a "listen" address for [udpreceive~] .... just the port is enough because every machine on the network will have the port open and will be receiving.
You only need multicast if you will have multiple receivers, but it will not flood your network as it sends only to receivers that join the group.... https://ipfabric.io/blog/troubleshooting-multicast-traffic-flows/
Broadcast will also be received at multiple end points, but if you will only have one receiver then sending directly to that receivers IP address will work....... and is better, for the reasons above.
I certainly needed to play around with the buffer size for [udpreceive~] to get reliable streaming over wi-fi.
Here are a send and a receive patch that work sending from my computer to a Raspberry Pi over wi-fi.
Obviously the IP addresses will be incorrect for you, but it might help.....
stream.zip
There are 3 possible [connect( messages in the send patch..... by computer name, by IP address, and a broadcast address 255.255.255.255.
David.
fexpr~ for a flip-flop toggle but getting only 0s
@jameslo is correct. This is not "flip and flop within one cycle."
Perhaps some of the confusion is that Pd signal processing doesn't do a lot with this definition of a trigger (whereas, it's everywhere in SuperCollider -- which also natively has a ToggleFF, what set this off was, "how to do ToggleFF in Pd/Max?").
Maybe this patch illustrates better:

The [threshold~] idea is that it flips up when the wave goes above 0, and flips down when it goes below 0. But the toggle idea is that it changes state only at the shown triggers.
A use case would be, say, volume tracking, where you want to cross fade between a couple of audio sources for every amplitude trigger. Audio source A should turn on at the first trigger, and off at the second trigger. You don't want audio source A to choose an arbitrary point in between the two triggers to switch off.

hjh
Getting "consistency check failed: editor"
@CarloFavero it is because the window is not visible, try clicking on a window that is not open sometime. Try this.
pd-receive-$0 vis 1;
pd-receive-$0 editmode 1;
pd-receive-$0 mouse 15 15 0 0;
pd-receive-$0 cut;
pd-receive-$0 obj 10 10 r step-last;
pd-receive-$0 connect 1 0 0 0;
pd-receive-$0 vis 0;
As an aside, if you do not need to stick to vanilla than iemguts really makes life easier when it comes to dynamic patching.
Edit: It is often easier/more clear if you just send a [clear( to the subpatch and repatch the entire thing, this allows you to skip the mouse emulation which allows you to skip the editmode and vis stuff as well. This means you want to reduce the subpatch to its bare minimum and make it only contain the bits which must be dynmic so you do not have a large amount of objects to deal with and also means you need to replace inlets/outlets with sends and receives since even with iemguts reconnecting the i\o is more work than just using sends and receives in the first place.
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
Snail... a pure data patch for slow sounds
Hello there, this seemed an interesting patch, so i unzipped it on a folder and tried to open it but got an unusable display and a string of errors on console, something like this (its not all of it);
list fromsymbol
... couldn't create
list tosymbol: unknown function
list tosymbol
... couldn't create
pdcontrol
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
clone 1 0 3 0 (canvas->outlet) connection failed
clone 1 1 8 0 (canvas->list split) connection failed
else/receiver
... couldn't create
else/receiver
... couldn't create
text search $1
... couldn't create
text set $1
... couldn't create
text search $1
... couldn't create
text get $1
... couldn't create
text size $1
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
text delete $1
... couldn't create
text_replace.pd 31 0 6 0 (canvas->select) connection failed
text_replace.pd 31 1 34 0 (canvas->trigger) connection failed
text define $0-guithru
... couldn't create
text size
... couldn't create
text get
... couldn't create
else/loadbanger -init
... couldn't create
else/receiver
... couldn't create
else/dollsym 1
... couldn't create
else/dollsym 2
... couldn't create
text define -k $0-controls
... couldn't create
array: no method for 'set'
else/args
... couldn't create
else/break -
... couldn't create
list fromsymbol: unknown function
list fromsymbol
... couldn't create
list tosymbol: unknown function
list tosymbol
... couldn't create
pdcontrol
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
clone 1 0 3 0 (canvas->outlet) connection failed
clone 1 1 8 0 (canvas->list split) connection failed
else/receiver
... couldn't create
else/receiver
... couldn't create
text search $1
... couldn't create
text set $1
... couldn't create
text search $1
... couldn't create
text get $1
... couldn't create
text size $1
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
text delete $1
... couldn't create
text_replace.pd 31 0 6 0 (canvas->select) connection failed
text_replace.pd 31 1 34 0 (canvas->trigger) connection failed
text define $0-guithru
... couldn't create
text size
... couldn't create
text get
... couldn't create
else/loadbanger -init
... couldn't create
else/receiver
... couldn't create
else/dollsym 1
... couldn't create
else/dollsym 2
... couldn't create
text define -k $0-controls
... couldn't create
array: no method for 'set'
else/click
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
q 8 0 11 0 (canvas->outlet) connection failed
q 8 1 5 0 (canvas->+~) connection failed
q 8 2 12 1 (canvas->canvas) connection failed
else/args
... couldn't create
else/break -
... couldn't create
list fromsymbol: unknown function
list fromsymbol
... couldn't create
list tosymbol: unknown function
list tosymbol
... couldn't create
pdcontrol
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
clone 1 0 3 0 (canvas->outlet) connection failed
clone 1 1 8 0 (canvas->list split) connection failed
else/receiver
... couldn't create
else/receiver
... couldn't create
text search $1
... couldn't create
text set $1
... couldn't create
text search $1
... couldn't create
text get $1
... couldn't create
text size $1
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
text delete $1
... couldn't create
text_replace.pd 31 0 6 0 (canvas->select) connection failed
text_replace.pd 31 1 34 0 (canvas->trigger) connection failed
text define $0-guithru
... couldn't create
text size
... couldn't create
text get
... couldn't create
else/loadbanger -init
... couldn't create
else/receiver
... couldn't create
else/dollsym 1
... couldn't create
else/dollsym 2
... couldn't create
text define -k $0-controls
... couldn't create
array: no method for 'set'
else/click
... couldn't create
text define -k $0-controls
... couldn't create
array: no method for 'set'
else/args
... couldn't create
text define -k $0-controls
... couldn't create
array: no method for 'set'
else/args
... couldn't create
else/loadbanger -init
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
mode 14 0 3 0 (canvas->clip) connection failed
mode 14 1 4 0 (canvas->wrap) connection failed
mode 14 2 6 0 (canvas->abs) connection failed
mode 14 3 15 0 (canvas->moses) connection failed
else/args
... couldn't create
else/break -
... couldn't create
list fromsymbol: unknown function
list fromsymbol
... couldn't create
list tosymbol: unknown function
list tosymbol
... couldn't create
pdcontrol
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
clone 1 0 3 0 (canvas->outlet) connection failed
clone 1 1 8 0 (canvas->list split) connection failed
else/receiver
... couldn't create
else/receiver
... couldn't create
text search $1
... couldn't create
text set $1
... couldn't create
text search $1
... couldn't create
text get $1
... couldn't create
text size $1
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
text delete $1
... couldn't create
text_replace.pd 31 0 6 0 (canvas->select) connection failed
text_replace.pd 31 1 34 0 (canvas->trigger) connection failed
text define $0-guithru
... couldn't create
text size
... couldn't create
text get
... couldn't create
else/loadbanger -init
... couldn't create
else/receiver
... couldn't create
else/dollsym 1
... couldn't create
else/dollsym 2
... couldn't create
text define -k $0-controls
... couldn't create
array: no method for 'set'
else/click
... couldn't create
else/break -
... couldn't create
list fromsymbol: unknown function
list fromsymbol
... couldn't create
list tosymbol: unknown function
list tosymbol
... couldn't create
pdcontrol
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
clone 1 0 3 0 (canvas->outlet) connection failed
clone 1 1 8 0 (canvas->list split) connection failed
else/receiver
... couldn't create
else/receiver
... couldn't create
text search $1
... couldn't create
text set $1
... couldn't create
text search $1
... couldn't create
text get $1
... couldn't create
text size $1
... couldn't create
else/args
... couldn't create
else/loadbanger -init
... couldn't create
text delete $1
... couldn't create
text_replace.pd 31 0 6 0 (canvas->select) connection failed
text_replace.pd 31 1 34 0 (canvas->trigger) connection failed
text define $0-guithru
... couldn't create
text size
... couldn't create
text get
... couldn't create
else/loadbanger -init
... couldn't create
else/receiver
... couldn't create
else/dollsym 1
... couldn't create
else/dollsym 2
... couldn't create
count.pd 15 0 8 0 (canvas->+) connection failed
count.pd 15 1 14 0 (canvas->-) connection failed
else/args
... couldn't create
else/loadbanger -init
... couldn't create
display 60 0 29 0 (canvas->message) connection failed
display 60 1 31 0 (canvas->select) connection failed
display 60 2 32 0 (canvas->message) connection failed
display 60 3 31 0 (canvas->select) connection failed
Any ideas ? cheers
use table to store midi channel information
I have to admit I'm very fresh to PD, and most probably I did not really understand all of the concepts.
My idea is to split a sequence of key events received on one midi channel to several (random or round-robin) midi channel numbers.
The problem occurs with the noteOff events - there I need to recall the (random) channel-number the noteOn event was sent.
I thought of a list with 128 elements for each note number. Thus setting the channel number when receiving a noteOn Event, and when reveiving the noteOff the channel is read back from the list end send out.
That's working "almost" fine - for one note. But unfortunately the tabwrite object is getting the channel number on its left "hot" inlet just before the note-number is set. Probably because the PD handles the events for outlets from right to left, on the right most outlet the channel appears first, issuing the table writing just before the note-number is set on the right input of 'tabwrite'.
I stretch my head with triggers, routing, spigots, delay, but I can't find a way to alter the order of the inputs to get it working.
Below first - is a simple patch illustrating my problem. When pressing down the first key, the list will show the channel is set for note-number 0 (zero) instead of, e.g,, 44,, pressing the second note, e.g., 48, will store the current channel at list element 44 instead of 48 - thus the channels are always stored for the previous key event.
The second parch below shows what I was working on - including some debugging number-boxes and bangs.
Any idea or hint is highly welcome - thanks a lot
Lou


PD's scheduler, timing, control-rate, audio-rate, block-size, (sub)sample accuracy,
Hello, 
this is going to be a long one.
After years of using PD, I am still confused about its' timing and schedueling.
I have collected many snippets from here and there about this topic,
-wich all together are really confusing to me.
*I think it is very important to understand how timing works in detail for low-level programming … *
(For example the number of heavy jittering sequencers in hard and software make me wonder what sequencers are made actually for ? lol )
This is a collection of my findings regarding this topic, a bit messy and with confused questions.
I hope we can shed some light on this.

- a)
The first time, I had issues with the PD-scheduler vs. how I thought my patch should work is described here:
https://forum.pdpatchrepo.info/topic/11615/bang-bug-when-block-1-1-1-bang-on-every-sample
The answers where:
„
[...] it's just that messages actually only process every 64 samples at the least. You can get a bang every sample with [metro 1 1 samp] but it should be noted that most pd message objects only interact with each other at 64-sample boundaries, there are some that use the elapsed logical time to get times in between though (like vsnapshot~)
also this seems like a very inefficient way to do per-sample processing..
https://github.com/sebshader/shadylib http://www.openprocessing.org/user/29118
seb-harmonik.ar posted about a year ago , last edited by seb-harmonik.ar about a year ago
• 1
whale-av
@lacuna An excellent simple explanation from @seb-harmonik.ar.
Chapter 2.5 onwards for more info....... http://puredata.info/docs/manuals/pd/x2.htm
David.
“
There is written: http://puredata.info/docs/manuals/pd/x2.htm
„2.5. scheduling
Pd uses 64-bit floating point numbers to represent time, providing sample accuracy and essentially never overflowing. Time appears to the user in milliseconds.
2.5.1. audio and messages
Audio and message processing are interleaved in Pd. Audio processing is scheduled every 64 samples at Pd's sample rate; at 44100 Hz. this gives a period of 1.45 milliseconds. You may turn DSP computation on and off by sending the "pd" object the messages "dsp 1" and "dsp 0."
In the intervals between, delays might time out or external conditions might arise (incoming MIDI, mouse clicks, or whatnot). These may cause a cascade of depth-first message passing; each such message cascade is completely run out before the next message or DSP tick is computed. Messages are never passed to objects during a DSP tick; the ticks are atomic and parameter changes sent to different objects in any given message cascade take effect simultaneously.
In the middle of a message cascade you may schedule another one at a delay of zero. This delayed cascade happens after the present cascade has finished, but at the same logical time.
2.5.2. computation load
The Pd scheduler maintains a (user-specified) lead on its computations; that is, it tries to keep ahead of real time by a small amount in order to be able to absorb unpredictable, momentary increases in computation time. This is specified using the "audiobuffer" or "frags" command line flags (see getting Pd to run ).
If Pd gets late with respect to real time, gaps (either occasional or frequent) will appear in both the input and output audio streams. On the other hand, disk strewaming objects will work correctly, so that you may use Pd as a batch program with soundfile input and/or output. The "-nogui" and "-send" startup flags are provided to aid in doing this.
Pd's "realtime" computations compete for CPU time with its own GUI, which runs as a separate process. A flow control mechanism will be provided someday to prevent this from causing trouble, but it is in any case wise to avoid having too much drawing going on while Pd is trying to make sound. If a subwindow is closed, Pd suspends sending the GUI update messages for it; but not so for miniaturized windows as of version 0.32. You should really close them when you aren't using them.
2.5.3. determinism
All message cascades that are scheduled (via "delay" and its relatives) to happen before a given audio tick will happen as scheduled regardless of whether Pd as a whole is running on time; in other words, calculation is never reordered for any real-time considerations. This is done in order to make Pd's operation deterministic.
If a message cascade is started by an external event, a time tag is given it. These time tags are guaranteed to be consistent with the times at which timeouts are scheduled and DSP ticks are computed; i.e., time never decreases. (However, either Pd or a hardware driver may lie about the physical time an input arrives; this depends on the operating system.) "Timer" objects which meaure time intervals measure them in terms of the logical time stamps of the message cascades, so that timing a "delay" object always gives exactly the theoretical value. (There is, however, a "realtime" object that measures real time, with nondeterministic results.)
If two message cascades are scheduled for the same logical time, they are carried out in the order they were scheduled.
“
[block~ smaller then 64] doesn't change the interval of message-control-domain-calculation?,
Only the size of the audio-samples calculated at once is decreased?
Is this the reason [block~] should always be … 128 64 32 16 8 4 2 1, nothing inbetween, because else it would mess with the calculation every 64 samples?
How do I know which messages are handeled inbetween smaller blocksizes the 64 and which are not?
How does [vline~] execute?
Does it calculate between sample 64 and 65 a ramp of samples with a delay beforehand, calculated in samples, too - running like a "stupid array" in audio-rate?
While sample 1-64 are running, PD does audio only?
[metro 1 1 samp]
How could I have known that? The helpfile doesn't mention this. EDIT: yes, it does.
(Offtopic: actually the whole forum is full of pd-vocabular-questions)
How is this calculation being done?
But you can „use“ the metro counts every 64 samples only, don't you?
Is the timing of [metro] exact? Will the milliseconds dialed in be on point or jittering with the 64 samples interval?
Even if it is exact the upcoming calculation will happen in that 64 sample frame!?
- b )

There are [phasor~], [vphasor~] and [vphasor2~] … and [vsamphold~]
https://forum.pdpatchrepo.info/topic/10192/vphasor-and-vphasor2-subsample-accurate-phasors
“Ive been getting back into Pd lately and have been messing around with some granular stuff. A few years ago I posted a [vphasor.mmb~] abstraction that made the phase reset of [phasor~] sample-accurate using vanilla objects. Unfortunately, I'm finding that with pitch-synchronous granular synthesis, sample accuracy isn't accurate enough. There's still a little jitter that causes a little bit of noise. So I went ahead and made an external to fix this issue, and I know a lot of people have wanted this so I thought I'd share.
[vphasor~] acts just like [phasor~], except the phase resets with subsample accuracy at the moment the message is sent. I think it's about as accurate as Pd will allow, though I don't pretend to be an expert C programmer or know Pd's api that well. But it seems to be about as accurate as [vline~]. (Actually, I've found that [vline~] starts its ramp a sample early, which is some unexpected behavior.)
[…]
“
- c)

Later I discovered that PD has jittery Midi because it doesn't handle Midi at a higher priority then everything else (GUI, OSC, message-domain ect.)
EDIT:
Tryed roundtrip-midi-messages with -nogui flag:
still some jitter.
Didn't try -nosleep flag yet (see below)
- d)

So I looked into the sources of PD:
scheduler with m_mainloop()
https://github.com/pure-data/pure-data/blob/master/src/m_sched.c
And found this paper
Scheduler explained (in German):
https://iaem.at/kurse/ss19/iaa/pdscheduler.pdf/view
wich explains the interleaving of control and audio domain as in the text of @seb-harmonik.ar with some drawings
plus the distinction between the two (control vs audio / realtime vs logical time / xruns vs burst batch processing).
And the "timestamping objects" listed below.
And the mainloop:
Loop
- messages (var.duration)
- dsp (rel.const.duration)
- sleep
With
[block~ 1 1 1]
calculations in the control-domain are done between every sample? But there is still a 64 sample interval somehow?
Why is [block~ 1 1 1] more expensive? The amount of data is the same!? Is this the overhead which makes the difference? Calling up operations ect.?
Timing-relevant objects
from iemlib:
[...]
iem_blocksize~ blocksize of a window in samples
iem_samplerate~ samplerate of a window in Hertz
------------------ t3~ - time-tagged-trigger --------------------
-- inputmessages allow a sample-accurate access to signalshape --
t3_sig~ time tagged trigger sig~
t3_line~ time tagged trigger line~
--------------- t3 - time-tagged-trigger ---------------------
----------- a time-tag is prepended to each message -----------
----- so these objects allow a sample-accurate access to ------
---------- the signal-objects t3_sig~ and t3_line~ ------------
t3_bpe time tagged trigger break point envelope
t3_delay time tagged trigger delay
t3_metro time tagged trigger metronom
t3_timer time tagged trigger timer
[...]
What are different use-cases of [line~] [vline~] and [t3_line~]?
And of [phasor~] [vphasor~] and [vphasor2~]?
When should I use [block~ 1 1 1] and when shouldn't I?
[line~] starts at block boundaries defined with [block~] and ends in exact timing?
[vline~] starts the line within the block?
and [t3_line~]???? Are they some kind of interrupt? Shortcutting within sheduling???
- c) again)

https://forum.pdpatchrepo.info/topic/1114/smooth-midi-clock-jitter/2
I read this in the html help for Pd:
„
MIDI and sleepgrain
In Linux, if you ask for "pd -midioutdev 1" for instance, you get /dev/midi0 or /dev/midi00 (or even /dev/midi). "-midioutdev 45" would be /dev/midi44. In NT, device number 0 is the "MIDI mapper", which is the default MIDI device you selected from the control panel; counting from one, the device numbers are card numbers as listed by "pd -listdev."
The "sleepgrain" controls how long (in milliseconds) Pd sleeps between periods of computation. This is normally the audio buffer divided by 4, but no less than 0.1 and no more than 5. On most OSes, ingoing and outgoing MIDI is quantized to this value, so if you care about MIDI timing, reduce this to 1 or less.
„
Why is there the „sleep-time“ of PD? For energy-saving??????
This seems to slow down the whole process-chain?
Can I control this with a startup flag or from withing PD? Or only in the sources?
There is a startup-flag for loading a different scheduler, wich is not documented how to use.
- e)

[pd~] helpfile says:
ATTENTION: DSP must be running in this process for the sub-process to run. This is because its clock is slaved to audio I/O it gets from us!
Doesn't [pd~] work within a Camomile plugin!?
How are things scheduled in Camomile? How is the communication with the DAW handled?
- f)

and slightly off-topic:
There is a batch mode:
https://forum.pdpatchrepo.info/topic/11776/sigmund-fiddle-or-helmholtz-faster-than-realtime/9
EDIT:
- g)
I didn't look into it, but there is:
https://grrrr.org/research/software/
clk – Syncable clocking objects for Pure Data and Max
This library implements a number of objects for highly precise and persistently stable timing, e.g. for the control of long-lasting sound installations or other complex time-related processes.
Sorry for the mess!
Could you please help me to sort things a bit? Mabye some real-world examples would help, too.

a-d function generator (seeking advice)
hi all ~
one of the projects i'm currently working on is recreating a particular a-d function generator in pd. i'm in the early stages of development with this, and relatively new to pd, so this might be a simple question to answer. right now i have my attack and decay sliders set up to output floats to a pack, then onto a message containing $ variables which is then passed to vline. ideally this should allow for a user to modulate the attack and decay times in realtime - using some means of input (bang, note, etc.) to trigger or re-trigger the envelope. an issue i am running into is that while the decay slider can be modulated without the envelope being triggered, the attack slider triggers the envelope any time an adjustment is made. my suspicion is that this has to do with pack, as it outputs when it receives a float to its first inlet. so i suppose this is my question: is there a way to prevent pack from sending when this adjustment is made? is there another object i should be using instead to aggregate the floats? any thoughts or advice would be much appreciated!
here's a screenshot of the subpatch for reference 




