Personal tools
You are here: Home documentation tutorials/howtos TipsAndTricks
Views

Here you will find some useful tips and tricks around your favourite dataflow software Pd. To add your own tip or trick, please underline the headline with enough "----" to make it appear in the main table of contents.

Replacing a lot of objects in a lot of Pd patches

Using Perl

Install Perl, then you can use this little one-liner:

$ perl -pi.bak -e 's/^(#X obj \d+ \d+) OLD_NAME([ ;])/$1 NEW_NAME$2/' *.pd

"OLD_NAME" is the name of the object to replace with "NEW_NAME". Here's an example:

$ perl -pi.bak -e 's/^(#X obj \d+ \d+) line~([ ;])/$1 vline~$2/' test.pd
$ diff test.pd test.pd.bak
7c7
< #X obj 176 364 vline~;
---
> #X obj 176 364 line~;

This replaced all [line~] objects with [vline~] objects, keeping the original patch in test.pd.bak. diff was used to check if everything went fine.

Additionally, to replace externals with full path (ex. [ead~] with [creb/ead~]) the / character must be escaped with \. For Example:

$ perl -pi.bak -e 's/^(#X obj \d+ \d+) OBJECT([ ;])/$1 LIBRARY\/OBJECT$2/' *.pd

Using SED

'sed' (the streaming editor) is a small standard tool that should be installed on every unix-system. To achieve almost the same as the above perl example, you can use the following on GNU-sed:

$ sed -i -e 's/^\(#X obj [0-9]\+ [0-9]\+\) OLDNAME\([ ;]\)/\1 NEWNAME\2/' *.pd

Note that this will only work on GNU-sed, since it uses the '-i' flag for in-place replacing. With other sed-versions you will have to use a temporary (backup) file for each patch you want to reiterate through (this will of course work with GNU-sed too). e.g.:

for f in *.pd
do
 cp ${f} ${f}.bak
 sed -e 's/^\(#X obj [0-9]\+ [0-9]\+\) line~\([ ;]\)/\1 vline~\2/'  ${f}.bak > $f
done

will replace all occurences of [line~] by [vline~] in all patches in the directory. Backups of the original patches are made (e.g. the original "test.pd" will now be called "test.pd.bak")

Reciproce a number

Techniques

"In mathematics, the reciprocal, or multiplicative inverse, of a number x is the number which, when multiplied by x, yields 1." Max users use [inv] for this, but Pd doesn't have [inv]. So what can you do? There are many solutions. ASCII mode on:

number
|
[1 $1(
|
[/ ]

num
|
[expr 1/$f1]

num
|
[pow -1]

number
|
[swap 1]
|    /
[/ ]

Example: BPM and [metro]

Using the reciprocal converting between a tempo specified in BPM (beats per minute) and a period usable for [metro] becomes easy. BPM is a frequency (something per time unit) and a period is the inverse of that, a time span. But [metro] wants its times in milliseconds, while BPM counts in minutes. So we need to first convert minutes to milliseconds. Here are some facts:

  • 1 minute == 60 seconds == 60000 milliseconds
  • 1 beat per minute == 1 beat per 60000 milliseconds
  • Duration of 1 beat at 1 BPM == 1 minute or 60000 milliseconds.
  • 2 beats per minute == 2 beat per 60000 milliseconds
  • Duration of 1 beat at 2 BPM == 1 minute / 2 beats == 0.5 minutes or 60000 msec / 2 beats
  • Beats in one minute, if every beat takes 30000 msec: 2 beats == 60000 msec / 30000 msec

So the general formula is this: 1 beat at x BPM = x / 60000 and the other way around: BPM, if 1 beat comes every x msec == x / 60000. In Pd this means:

bpm or period  
|
[expr 60000 / $f1]
|
period or bpm

So to display a BPM-input to control a metro you use this:

      [120\ numberbox for bpm
      |
      [expr 60000 / $f1]
      |
[metro]  <= this is runnig at 500 now. 

PI

Sometimes you need to use the value of the number PI: 3.14159... If you don't want to memorize it, you can use this expression object to calculate it on the fly:

expr 4*atan(1)

Just bang this and get PI out.

sidenote: it is not such a good idea to try and create an object [f 3.141592657], since pd will trunkate numbers when saving the patch to disk; the next time you open it, ypir PI will have become significantly (depending on your original precision) different.

Getting $0 into messages

I repeat: There is no $0 in a message box!

Messages boxes only know about $1, $2, $3,... and so on. What if you have to use $0 in a message box, for example to send something to a $0-receiver using a semicolon message? Use [pack] and $1, $2, $3, ... instead like this:

[440\
|
[pack 0 $0]
|
[; $2-frequency $1(

[r $0-frequency]
|
[440\

But what if you want to send a message to a $0-subpatch, for example to clear a subpatch called [pd $0-sub]? The receiver of this subpatch is pd-$0-name, but (for now) you cannot use $-variables inside of a symbol (only at the beginning) and you cannot use $0 in messages at all. The solution is [makefilename]:

[f $0]
|
[makefilename pd-%d-sub]
|
[; $1 clear(

or alternatively use this:

[symbol $0-sub]
|
[makefilename pd-%s]
|
[; $1 clear(

With newer versions of Pd (0.40 and up) you can also use this:

[clear(
|
[s pd-$0-subpatch]

Undocumented pd internal messages:

These messages can be useful if running pd without gui, or for building patches dynamically. Some of them should be self-explanatory. Some other have no documentation at all. Note: documentation for each msg is missing :(

pd messages

you can send these messages to the pd selector:

init [gimme]
filename [symbol] [symbol]
open [symbol] [symbol]
quit
foo [gimme]
dsp [gimme]
meters [float]
key [gimme]
audiostatus
finderror
ping

patch messages

you can send these messages to the pd-patch.pd selector:

obj [gimme]
msg [gimme]
floatatom [gimme]
symbolatom [gimme]
text [gimme]
graph [gimme]
array
scalar [gimme]
bng [gimme]
toggle [gimme]
vslider [gimme]
hslider [gimme]
radio [gimme]
vumeter [gimme]
mycnv [gimme]
connect [float] [float] [float] [float]
restore [gimme]
write [symbol] [defsymbol]
read [symbol] [defsymbol]
mergefile [symbol] [defsymbol]
sort
click [float] [float] [float] [float]
mouseup [float] [float] [float]
key [gimme]
motion [float] [float] [float]
print [symbol]
menusave
menusaveas
menuclose [deffloat]
saveto [symbol] [symbol]
cut
copy
paste
duplicate
selectall
tidy
texteditor
editmode [deffloat]
protectmode [deffloat]
print [symbol]
pop [deffloat]
loadbang
relocate [symbol] [symbol]
menufont
font [float] [float] [float]
find [gimme]
findagain
findparent
vis [float]
properties [float] [float]
help [float] [float]
arraydialog [symbol] [float] [float] [float]
map [float]
clear
intatom [gimme]
atom [gimme]

Moving shortcuts

You can move selected objects with the arrow cursor keys. Shift-Arrow moves objects in bigger steps.

Keep your patches nice, clean and tidy

It might sound boring, but developing a clean patching style is important for a lot of reasons. I won't state all here, but the most important one is better readability. Here are some hints how to make a patch cleaner:

  1. try to avoid patch cords crossing over objects and over each other
  2. rearrange objects and use [trigger] to make the patch cords run in straight vertical lines where possible.
  3. use sends and receives instead of patch cords, where rearranging isn't possible.
  4. use subpatches to group objects by functionality
  5. use abstractions for functionality that is used more than once.

The next two images illustrate the effect of points 1.) and 2.) from above. The first image is the uncleaned patch. Cords run through each other and make quite a mess. Rearranging objects and [trigger] was used to clean up a bit. I didn't use any send or receive objects, but these would make the patch even cleaner.

/Members/fbar/img/dirty.png

A dirty patch before cleanup.

/Members/fbar/img/cleaner.png

The same patch cleaned up a bit.

Instance-specific dynamic patching

You can send messages to a specific instance of an abstraction, by renaming the abstraction using namecanvas. The renaming can be automated using $0 expansion as follows:

/Members/jb/images/dynamic-namecanvas

Add more entries to the Path and Library dialogs

Question: I want to add another path/library to the Path/Library settings dialog, but I've run out of textfields, they are all already used?

Answer: You can add more than one entry to each of the textfields by seperating them with colons (":") like this:

Path: 
/usr/lib/pd/extra:/home/me/pd/abstractions:/home/me/pd/externals

Libs:
Gem:msd:zexy:my_library

Then just "Save" and "Save all settings" as usual.

How to Avoid Audio Drop-outs

there are some situations, where audio drop outs can occur. if you know why a certain kind of drop-happens, you probably will find a way to overcome the problem.

  • fileIO: all objects, that read files from disk, will block audio, until they finished executing. so do load all files beforehand. when you need to load soundfiles during performance into tables, don't use [soundfiler]. miller once suggested using [readsf~] in a subpatch with upsampling, so it will load the sample faster than reading it in realtime, but not block dsp during loadtime. it seems, that some people do load only the very first part of each file, that will be used during a performance into a table, and do read the rest from disk.
  • recompiling dsp-graph. loading patches or creating objects dynamically can cause audio dropouts. for performance situations open all used patches beforehand and switch (with [switch~]) all parts off, that you don't need. and do not use dynamic patching.
  • many operations in one tick. don't use things like [100000(- ![until]?. since pd wants to process it in 0 logical time, it will probably will cause a drop out.
  • sending too much data to [netsend]/[netclient]/[netserver]/[tcpsend] etc. these object classes have a certain internal buffer (4kB, iirc). if the buffer is full, these objects will block processing of pd, until the buffer is emtptied again. try to send not too big chunks of data in one go, but use a kind of a drip mechanism to artificially limit the bandwidth.

Getting Table/Array Size

One way to get the table or array size is to use the external called arraysize. Another is to use the expr external which is shipped with vanilla Pd. It can be used as show below to get the array size.

In the following array1 is the name of an example array.:

[bang(
|
[expr size("array1")]
|
[print arraysize]

or:

[symbol array1(
|
[expr size("$s1")]
|
[print arraysize]



Powered by IEM Powered by Plone Section 508 WCAG Valid XHTML Valid CSS Usable in any browser