Introduction to PD

PD, which stands for "Pure Data" or "Public Domain," is a graphical programming environment for MIDI and digital audio. This introduction is intended to help the reader better understand the design of my OSCAR system. Those who wish to become aquatinted with PD from a user's standpoint should consult PD's documentation, as well as the FAQ at Pure-Data.org. PD's interface is very similar to that of Max/MSP. Max's excellent documentation serves as an good introduction to PD as well.

Objects

In the simplest terms, PD consists of boxes (called "objects") that "do stuff." These boxes have inlets and outlets, allowing them to be connected with other boxes via patch chords. It is through the interconnection of different objects that PD can achieve complex behavior.

The |float| object (or, in ASCII shorthand, |float|) is a very simple object; it stores a floating-point number. The "0" after the word "float" is an initialization argument; this |float| is created with an initial value of zero. The two black bars at the top of the object are inlets, and the black bar at the bottom of the object is an outlet. When a number is entered into the right inlet of a |float|, the number is stored. When the left inlet receives a BANG message (BANG universally tells objects in PD to do whatever it is they are supposed to do), the stored number is output from the object's outlet. When a number is entered into a |float|'s left inlet, the number is both stored and sent out of the outlet. Like |float|, most, if not all, objects in PD have a "hot" left inlet; information entering into the left inlet causes the object to actively output. Information entered into other inlets changes data that is internal to the object (such as the value that is stored in a |float|), but does not cause the object to output.

PD has a class of graphical objects, incorporated from the IEM library of PD externals. One such object is |bng|, called |bng| or, by the name of it's Max cousin, "button". When clicked, the center of the object flashes, and a BANG is sent out it's outlet. Also, when |bng| receive any input, it flashes and outputs a BANG. The object's size, color, and behavior can all be changed internally by the user.

A Simple Patch
Example PD patch

This is an example of a simple PD patch (a program in PD is called a "patch"). The patch counts the number of times you click on the |bng| labeled "count." The number of clicks counted is displayed in a number box. The count is reset if you click on the |bng| labeled "reset." Clicking the "count" |bng| causes it to output a BANG message. This BANG causes the leftmost |float| to output it's value. This value is input into the |+ 1| object, which simply adds 1 to its input and outputs the result. The output from the |+| is sent to the number box, and is sent to the right inlet of the |float|. The value that is stored in the |float|, and the value that is sent to the number box, is increased by one with each click. Clicking on the "reset" |bng| causes the |float -1| to enter -1 into the |+| object; the number box and the value in the leftmost |float| are reset to zero.

Encapsulation
|counterex|

Patches can be encapsulated within other patches. This patch is an improved version of the simple counter created above. In place of |bng| objects, this patch has two |inlet| objects. |inlet| objects allow messages to be sent into a patch from the outside world. Similarly, |outlet| objects send information out of the patch; here, the number box is replaced with an |outlet|.

|counterex2A|

In this patch, the counter we created above is encapsulated and nested inside another patch. The |counter| object contains our improved counter patch. The two inlets and one outlet of the |counter| object correspond directly to the two |inlet|'s and one |outlet| in the counter patch. Therefore, clicking on the left |bng| will increment the counter, and clicking on the right |bng| resets the counter. The count comes out of |counter|'s outlet and into a number box.

Encapsulation has two purposes. First, it makes complex patches visually simpler by hiding a potentially large number of objects inside a single object box. Secondly, and more importantly, encapsulation allows the user to create a basic abstraction that can be reused repeatedly. Furthermore, specific instances of an abstraction can be given specific characteristics through the use of initialization arguments.

|counterex4|

This example patch is identical to our encapsulated counter, with the addition of the |*| object, which multiplies it's input by a number (which comes either from the object's right inlet or from it's initialization argument). In this case, rather than supply the |*| with a constant, it contains the string "$1. This string will be replaced by the initialization argument supplied when an instance of the object is created. Specifically, "$1" will be replaced by the first initialization argument, "$2" by the second argument, and so forth.

|counterex5|

This patch contains three instances of our |counter| object, each with a different initialization argument. As you can see, the argument sets the factor by which the count is multiplied before being output. The initialization argument essentially replaces the "$1" string inside the encapsulated patch. Through the use of initialization arguments, a user can create a template abstraction, and allow the instances of the abstraction to have different characteristics.

Scheduling

In order for a patch to work, it is essential that operations defined within it be scheduled and executed in the correct order. The order of execution is defined by the layout of objects on the screen: PD works top-to-bottom and right-to-left. Furthermore, if an object's outlet is connected a number of other objects, the output is sent to the connected objects in the order in which they were connected by the user. This ordering can easily be checked and adjusted by viewing the patch with a standard text editor: the objects will be listed in the order in which they were connected.


Email Greg OSCAR Main Page