PureData Programming. Part 0
- From the sandbox
Some general information
PureData is a visual programming language for creating interactive programs (in this case they are more often referred to as “patches”) used to play and record computer music, sound design, and visualizations. People familiar, for example, with Max / MSP, will recognize their usual graphic code, since PureData is one of the languages of the MAX-like family.
To put it simply and slightly exaggerated - this is a language sharpened by the programming of synthesizers and effects.
In this article I will describe some elements of the language, as well as the basic principles on which sound processing in PureData is based.
PureData - cross-platform, there are assemblies for Windows, MacOS, Linux and FreeBSD ; works as with standard drivers ( ALSA, MMIO), and with jack , ASIO , midi transfer is also supported . All versions are available for download from the official site . I recommend downloading the extended version, since it contains a large set of external libraries out of the box, which are extremely necessary in most cases.
Digital sound presentation
And here you can recall the gramophone and the record. What is the principle of recording sound on vinyl? A cutter that scratches a vinyl disc is forced to vibrate under the influence of a certain source (a microphone signal, for example), due to which the cut on the surface of the disc becomes tortuous, and this trace perfectly repeats the vibrations of the cutter. Subsequently, when the needle moves along this winding path, it oscillates, precisely repeating the oscillations of the source. Those. the needle will sound. So, if this track is presented in the form of a graph, and the coordinates of the points of the graph are recorded with a small step, we will get a sound file. Thus, WAV is nothing more than an array of numbers that are points of a certain curve. This process — splitting the wave into points — is called sampling, and the frequency at which the points are taken to write to the file is the sampling frequency.
From this, the first aspect of program synthesis is born : to describe mathematically sound as a certain line, which is a graphic representation of the vibrations we need. This approach is universal and can be implemented in any language that has libraries of interaction with sound devices. Although in fact, this is not necessary, since the array of values can simply be added to a file by hanging the WAV extension.
This representation is logical and universal, but not always convenient. It is much easier and more convenient to control the operation of a software synthesizer if the interaction of the elements interface resembles a modular synthesizer. For those who do not know: a modular synthesizer is a device consisting of various independent components (so-called modules: generators, filters, converters, etc.), interconnected by wires. In this case, the contractor knows which module is responsible for what, in what order they follow each other, and, importantly, the configuration can be changed “to hot”.
This approach, from the point of view of building code, is implemented in MAX-like languages:
So, the second aspect of software synthesis on PD:The interaction of language elements is built by analogy with a modular synthesizer.
In practice, these two approaches are in symbiosis, complementing each other.
So, having learned what we will deal with, we will proceed directly to PureData.
a + b =?
In general, programming on PureData comes down to three things: transmitting “pulses”, numbers, and signals. The basic elements of the language are also few, four: objects, numerical blocks (number box), message blocks (message box) and connections similar to wires. Let's write the simplest program, make PD add up two numbers.
So, in the window with the new patch, create an object (Ctrl-1), place this rectangle somewhere and write [bng] there (it is also bang ). Virtually more than one patch is complete without this object. His task is to create and send impulse. Now let's figure out where and why. Now create two blocks with messages (Ctrl-2) and write two arbitrary numbers there, connecting bangwith each of the blocks. So now these numbers need to be added up. To do this, create the object again, and enter "+" in it. Expected, right? Connect the numerical blocks with the object "+" . Now it remains only to display the result. This can be done either in the console using the print object , or left inside the patch by sending it to the number box (Ctrl-3).
To check the patch in action, you need to block it (Ctrl-E) and click on the bang object . So, in the console or in numbreBox'e, we see the result. If it is incorrect - do not be alarmed, we will analyze everything on the line below. What happened by clicking on bang , we created an impulse that, through connections, came to message blocks and passed them on to the addition object, etc.
Now let's try to understand why some of us have the wrong result. Just hit bang again. Now right? The fact is that the correct order of arithmetic operations is influenced by the order of the elements. When building a patch similar to ours, correctness is guaranteed if the objects were connected from right to left. This is damn inconvenient, it is impossible to debug and find an error. But all this can be avoided if another object is used, the task of which is to split the input into several streams and send pulses at the same time.
This is a trigger object .
Create an object with this name. Now we’ll write down next what needs to be transmitted (bang is the momentum, float is a numerical value, anything is any). Since we break the impulse into two, the contents of the object take on the formtrigger bang bang , abbreviated as tbb . It remains to connect the outputs with numbers. Now the result will be true regardless of the connection order.
This, of course, is all wonderful, but what if we want to calculate a long expression, or use mathematical functions? After all, the simplest program written by the above method, such as searching for the roots of quadratic equations, will be too complicated and confusing. For such cases, an expression or expr object exists in PD. Using this object, you can describe mathematical and logical expressions, as well as their combinations. Consider the same addition example. $ f1 and $ f2, as you might guess, are variables, and they are counted from left to right. The leftmost input is $ f1, and then in order. The number of inputs of the expr object is equal to the number of variables used in the expression.
Afterword and F1
Today we examined the most affordable minimum and figured out the difference in ideas, in the next article I will describe the work of conditional logic and the simplest objects associated with working on signals. It remains only to talk about the help system. You have to use the help constantly, and to see information on the object, just right-click on it and select the “help” item. It will contain a description and, in most cases, examples of use. A complete list of objects and libraries is available in the Pd help browser or by hotkey Ctrl-b.
I will try to publish the following articles and lessons on PureData at least once a week. All the best.