Draw music: Coffin dance in Pure Data

Programming and Memes


Programming is a process on the verge of science and creativity. Without a well-designed program, a computer is a helpless unit that spends electricity. Most modern specialists work with declarative symbolic languages ​​- they make programs from text commands: simple - assignment, multiplication; and complex - checking conditions, executing routines in a loop.

But not all programming languages ​​are designed to solve system problems. Some are created for training, presentations, and digital shows. When performance and functionality fade into the background, original solutions such as the Pure Data visual programming environment come into being.

In 2020, the dance from the archived video of the funeral ceremony of the Dada awu agency from Ghana became the most popular meme in Russia. Today we have to step by step recreate the legendary musical theme Coffin Dance, using the environment of algorithmic sound description Pure Data.

About visual programming


By visual programming it is customary to understand the process of describing a program for a computing device using functional graphic elements. So, the use of the WPF form designer in the Visual Studio development environment can be called visual programming of the interface. Graphic designers appeared along with the first personal computers. Now at lessons in computer science, Visual Pascal is being studied at some schools. and half of the standard improvements in 1C can be done without writing a line of code.

But full-fledged visual programming environments appeared later. When it comes to creating a programming language that consists only of graphic commands, a number of difficulties arise, because of which the functionality of the language itself has to be curtailed.
So, multiple calls of the same subprogram in different parts of the C ++ code are natural for the programmer. In a graphical environment, a subroutine call can be represented, for example, by an arrow from an object in the text of the main program to an object-subroutine, and when there are too many such arrows, the graphic code becomes unreadable. Developers of educational development environments often themselves impose a limit (on the number of calls, objects in the program, variables used) to protect the user and make the visual programming process more visual.
An example of a simple Sanscript program:

image

But if you distract from programming in the broad sense, you can find important applied problems that are graphically solved more conveniently and more efficiently than in symbolic. One such task: a description of virtual instruments. Back in the 80s of the last century, most of the musical recordings were made live. Digital synthesizers were inferior in sound quality to acoustic instruments, and truly “musical” digital systems were expensive.

Everything has changed with the introduction of VST technology, introduced in 1996 as a voluminous library for working with sound. Functionality VST allowed us to describe the architecture of real digital synthesizers, effect processors and very accurately emulate their work on a computer. However, only a team of qualified programmers and sound engineers could construct such a description. The question of creating custom virtual instruments remained open.

In those same years, in an attempt to popularize sound synthesis among amateurs, the experimental Pure Data project appeared - a visual development environment focused on the description of simple synthesizers. Around Pure Data, a small group of “fans” formed who promoted visual programming in FB, Youtube: they wrote and translated training materials, published synthesizer examples and whole music mixes on one patch (this is the name of the Pure Data program by analogy with patches in modular hardware synthesizers ) But the environment has not received wide distribution in the world.

Pure Data Basics


The Pure Data development environment can be downloaded for free from the official website. The program distributes open source and is available for users of Windows, Linux and MacOS X. Install and run Pure Data. In the File menu, create a new patch. The following editing window will appear:

image

The Put menu contains a list of graphical objects from which we will make our first synthesizer. After selecting the appropriate item, the element is added to the graphic field (Canvas) of the current patch. Elements can be edited (change the signature, which affects their behavior, as well as moved) and connected by lines (by holding the left mouse button on one of the output of the source object, moving the cursor to the input of the destination object and releasing it). For an example we will create one element of type "Object" with the name key and one element of type "Number". The inputs of the element are highlighted in black and are located above the frame of the element itself, and the outputs are below it. Connect the output of the key object to the input of the Number element.
We get:

image

All this time we were in patch editing mode. To go into run mode, go to the Edit menu and uncheck the Edit Mode item. The mouse pointer on the outline should change from hand to arrow. Now press any key on the main keyboard. We will see how the value of Number changes when pressed:

image

Let's analyze the result of the patch. After assigning the name key to the object, it has one output, but no inputs. An object with this name listens to the keyboard and sends out a key code each time it is pressed in runtime. The Number element has one input and one output. Taking a number as input, Number displays it on the screen and sends the same value to the output. Note that after releasing the key, the number continues to be displayed. This shows that the inputs retain the last value they accept.

Go back to edit mode and add another object named sel 49. It will have two inputs and two outputs. This object sends a signal to the first output each time a value arrives at one of the inputs and it matches the value stored on the other input. If the input receives a value other than the accumulated one, the signal is sent to the second output. The first part of the sel name specifies the type of object, the second 49 - writes the default value for the second input. 49 is the key code "1".

A signal is a special data type that cannot be simply output, for example, by sending Number to the input. But with the help of signals, you can "start" the work of some elements.

Go back to the Put menu and add the Bang element to our patch. Connect the Number output to the first sel 49 input and the first sel 49 output to the Bang input. We will receive the following patch:

image

We will pass to a mode of execution. By pressing various keys their codes will appear. When you press the “special key” with code 49, the sel object will generate a singal, which, when hit the bang button, will automatically press it:

image

The bang object generates a signal at its only output when it is pressed in run mode, the signal or value gets to the input. Add a little sound to our project. For the patch to work correctly with audio data, the Media menu should have a checkmark opposite the DSP On item. You will also need to enter the Midi Settings menu and install the output device. On Windows:

image

Click OK and return to edit mode. To work with Midi signals, 2 elements are most often used: makenote and noteout objects. Add one such object, and also create several Message messages with the following values:

image

Message is an element of visual programming with complex behavior. If the message is called a certain number, then by clicking on the message or upon receipt of a signal at its input, in both cases this number and signal will be output simultaneously.

The noteout object, when it receives the value at the first input, generates sound on one of the MIDI channels. The channel number can be indicated explicitly in the name of the object (in our case 1 - piano) or transferred to the third input noteout. The first input takes the pitch in terms of midi: (60 - this is to the first octave and then +1 - increase by a half tone, -1 - decrease by a half tone), and the second - description of the note: volume, duration, nature of sound production.
The makenote object receives the pitch to the first input and to the second volume (0 - silence, 127 - maximum volume) translates the pitch to the first output, and generates a note description for the second input noteout on the second output. The default values ​​for the first and second makenote inputs are specified immediately after the object name. Connect the elements as shown in the figure and go to run mode:

image

When you click on a message, a note should sound corresponding to the pitch in the message name. 60 - note to, 62 - re, 67 - la. Now in edit mode, connect the first output of the selector (sel object) with message 60. Add 2 more selectors with codes for keys 2 and 3 on the keyboard and get the simplest synthesizer:

image

Pressing keys 1-3 in makenote will send a message with the appropriate pitch and a note will sound. In the next section, we will try to describe a complex melody that will be played sequentially note by note when sending only one signal.

Recreating Coffin Dance


Music


To describe a complex melody, we need to study 2 important objects - metro and f, as well as a number of auxiliary objects. Consider a simple example:

image

The metro object has two inputs. The first signal is received. Any signal other than stop includes a metronome. To disable, use the output signal of the message with the text stop. The second input, metro, is given an interval in milliseconds. When the metronome is turned on, it will immediately send a signal to its only output and will re-send the signal every n milliseconds. The interval n can be specified by the default value in the object name or transferred to the second input. Having entered the run mode, we can start the metronome with the bang button above it and see how the button below it is pressed every 0.4 seconds. By sending a message with a new interval, we will speed up or slow down the frequency of sending signals. After the stop message is sent, the signaling stops.

Recall the music from Coffin Dance:


The main melody can be described by a sequence of 64 notes and pauses of the 8th duration, i.e. at 8 measures in 4/4. So, we need to organize the cyclic sending of the 64th signals to the corresponding note messages. To do this, use the object f.

F - from float - represents a real variable. Object f has two inputs. At the second input, you can submit a numerical value (for example, from the output of the message or the output of Number), which is written as the value of the variable. The default value is 0. With the first entry and exit, things are a little more complicated. Consider an example:

image

So, we found a magical connection between the memes “Press F to pay respect” and “Coffin dance”. Let's switch to run mode. When you click on message 3, the value will be written to the object variable f, but in number we will not see this. If you submit the signal to the first input f with the bang button, what happens in terms of Pure Data is an iteration, namely:

  • Output f will send the current value of the variable (3)
  • Object + 5 will receive the number 3 on the first input and will return the sum of two inputs 8 (here the value at the second input is set by default after the name + addition object)
  • Object% 40 will receive the number 8 on the first input and return the remainder of dividing the 8th by 40 (the value of the second input is set by default)
  • The variable f will receive the value (3 + 5)% 40 = 8 on the second input. The iteration is completed

Thus, after the first iteration, we see the value 3 at the input number and has a real value of 8 for the variable f. At the next iteration, number will get the eight saved earlier, and f will increase by another 5 and take the value 13. When it comes to iteration with output 38, we get the value (38 + 5)% 40 = 3 for the variable f. Thus, f values ​​and output values ​​will be cyclically repeated. Using addition and division modulo allows you to get a cycle with any period and any values ​​for iterations.

Connect the metronome output to the first input f, and set several selectors and buttons at the output f. Launch the metronome and see how the buttons light up in turn and after automatically pressing the last button, the cycle repeats. Patch:

image

In order for the loop to run each time from value 3, I connected the output of the stop message to the input of message 3 sending the initial value to f.

Let’s describe the melody. To do this, create a clean patch and describe the metronome with an interval of 230 (exactly 230 milliseconds lasts one eighth note in the melody) and a cycle of 64 notes. To select the values, we use the variable f and the new element moses for us, the functionality of which will be described below. We also add several makenote objects, messages with notes, noteout with channels 1 (piano) and 10 (drums), and combine the moses selectors of each iteration with the corresponding notes. Get the patch:

image

As you can see, with visual programming, the use of a large number of objects reduces the readability of the program. In fact, a patch is a combination of simple elements. Consider the following "routine":

image

The moses object stores a number on the second input, which can be set by default. If the first input receives a number smaller than the stored value of the second input, then a signal is sent from the first output of moses, otherwise the signal is sent from the second output. Thus, the first output of moses 1 behaves similarly to the first output of sel 0. Let's look at a bunch of + 63% 64. It allows you to reduce the values ​​in the loop by one. If one was input, then the output will be 0, for input 0 the output will be 63 - we will get a cycle of 64 elements in the reverse order. If we connect the output of this bundle to the input of the following construction + 63% 64 and connect moses 1 to the output of each bundle, but for each of the 64 possible values ​​of f, exactly one moses will send a signal to the first output. So, the number 7 needs to be reduced 7 times by 1,to get 0, then the 7th moses 1 at iteration 7 will receive 0 on the first input and send a signal to the corresponding note. If for 64 selectors you need to manually edit the default values ​​of the parameters, then the routines + 63% 64 moses 1 can be copied and connecting the outputs of the previous% 64 to the inputs + 63 get a complex 64-position cyclic selector.

The melody patch uses duplication of noteout objects. This technique allows you to increase the volume bypassing the limit mark. So, if you connect the same makenote 67 127 to 2 noteout 1, but when sending a signal from the first makenote input, the note la (code 67, first octave) will be played with a volume of 127 * 2 = 254. MIDI instruments in Pure Data very quiet, so this technique is useful in creating ensemble melodies (in our case, 2 pianos are played on channels 1 and 5 and drum kit 10 with triple volume).

To decorate the simulation (the process of moving data between objects of the patch code in runtime), it is convenient to use duplicated buttons. In the example above, their 6 bang objects have a silhouette of the Play button, which is automatically highlighted when the extreme bang button is pressed on the right. Bang signal processing is a resource-intensive process, but in the next section we will place a whole array of such buttons and try to depict a dance from the video with their help.

Animation


For animation, we need all the same variables f, objects - arithmetic operators and a metronome, as well as selectors. This time we need only 8 frames, so we will use sel objects. Create a 20x10 field from the bang buttons (we will use the copy operation). After placing the patch with the melody in the center, we get the following figure:

image

You can simply connect the left outputs of each selector to the buttons that should be pressed on this frame and send the signal from the metronome to the input of a new variable of cycle f. But this approach has 2 flaws:

  • 0.23 sec per frame - too fast for our dance. And the use of the second metronome will knock us off the beat: noteout and bang have different delay in response to the signal;
  • the button remains pressed for 0.05 seconds from the moment the signal was received, which means that for the remaining 0.18 seconds the “screen” of the animation will be blank and the picture in the loop will flash.

To solve these problems, we use division. The following construction:

image

takes the input f value of the main cycle-melody. After dividing by 2, we get a slowdown of the frame change: for 0 and 1, frame 1 will be shown, for 2 and 3, frame 2 and so on. For each frame, one signal is still sent every 0.23 seconds. Now let's use another loop:

image

To synchronize with the main melody, a delay has been added to it: the inclusion signal passes from the selector first through the button and only then to the first input of the metronome. Now, if you create a bang and connect its output to all the pixel buttons of a certain frame, then the frame above you can highlight the frame every 0.046 seconds, which is faster than the update frequency of the buttons, i.e. the frame will light continuously until the next frame changes. A cycle of 5 iterations ensures that frames will not be layered, since 0.046 * 5 = 0.23 sec - the period of frame selectors.

When creating an animation, the computer crashed regularly, but it was possible to draw 5 different pictures and create a cycle of 8 frames from them in the order:

1 2 3 2 1 4 5 2

The final patch with Coffin Dance (many decorative elements - buttons and comments added) in edit mode:

image

It is hardly possible to parse the source code of the simulation in this infernal picture, however the patch works correctly:

image

In the lower right corner a counter is used to automatically stop the player after the 121st notes. Initially, an animation of 48x24 pixels was supposed, but the computer categorically refused it with a mournful roar of the cooler and an unexpected restart of Windows in safe mode. The original pixel art 48x24 from the artist LikaLou attached at the end of the video. So, after 3 days of “drawing music” we have Coffin Dance in Pure Data:


Conclusion


Visual programming of memes is a fun activity, although it takes a lot of time and sometimes destroys your hardware. Even such a seemingly simple, funeral dance task requires a modular approach to creating a program, knowledge of the features of not only the implementation language, but also the development environment.

Using the example patch for Coffin Dance, you can judge the level of development of visual programming. There are graphical languages ​​that cope well with some application tasks, if convenient development environments. But the visual programming industry as a whole is in its infancy.

References


Pure Data official website
Basics of visual programming in Pure Data
About the VST standard
Coffin Dance article on Wikipedia
Coffin Dance in Pure Data: original video

All Articles