📜 ⬆️ ⬇️

Create a preset manager in PureData

Yes, Max is more perfect than Pd . Yes, a lot has been done in it for productive work. Finally, its interface does not slow down with a large number of objects in the patch. However, there is something magical in Pd that forces you to open this simple interface written in tcl / tk again and again, with its simple boxes and colors that please the night. Maybe this is the very open source magic that makes people use gentoo on the desktop?

In this article we will try to solve one sore subject of all users of this wonderful program, namely, the preservation of the parameters of numeric boxes, sliders, knobs, etc. It would seem a very important function. Why is there still no special object similar to the preset in Max ? The thing is that using the PureData API you can not access data from other objects, so you have to get out.

Of course, there were attempts to implement presets. I looked at some of them, but their implementation seemed to me difficult (yes, I didn’t understand them completely) - I wanted something light and flexible. As a result, after a day of thought and evening of patching, such a system was born.

Formulation of the problem


To save the presets, we need:
  1. constantly monitor the saved parameters;
  2. be able to extract and save them at any time;
  3. be able to restore the state of objects from stored data.

I immediately remembered the pattr and pattrstorage objects from max. The first connects with a gui object, the value of which needs to be stored, and the second is the data store. It was decided to do something similar.

We represent how everything will be


So, our “analogue” of the pattr object will monitor the parameter, and the analogue of pattrstorage 'will, if necessary, poll it and save the values. We call these objects store and storage, respectively. All this should look something like this:
')
Presets PureData. We represent how everything will be

The store object will store the current one, as well as assign a new value to the numeric box. That is why these objects are interconnected in such a way. Using the message “save” storage will send a command to the store so that it sends the current value of the numeric box to it. “Recall” will do the opposite - to ask boxing a new value.

So, the general view is clear, moving on.

Making the base


Max presets information is stored in json format. Theoretically, Pd can work with it through the PuREST library, but it is sharpened for online services, and why complicate things? The easiest way to write data to a .txt file is by using a textfile object. It can save any number of messages and display them in sequence. More information about how it works, you can read in the help, and now proceed to create objects.

Presets PureData. First sketches.

The picture above shows a screen with comments of three open patches. root is a test patch in which we will check the operation of the store and storage . In the script, at this stage it is already possible to save and restore the value of one numeric box. The procedure is as follows:
  1. change the value of the numeric box;
  2. press “get” - this will clear the textfile , after which bang will be sent to [s presetTrigger] . The recipient of this bang will be a float object located in the store , which will output the stored number through its outlet and send it back to the store , where it will be output through [r presetGetAll]], will turn into a message like “add% number_from_box%” and go to the textfile ;
  3. press “store” - this will send a “write” message to the textfile and create a text file in the folder with the root patch, which will contain all the parameters of the preset;
  4. change the value of the numeric box, then press “recall” - the previously saved value should be restored.

We increase the functionality


So, we did the main part and successfully tested performance. However, at the moment you can save only one parameter, which is not good. As we remember, the pattr object in the argument must specify the name of the parameter, the value of which will be remembered. Thus, max indexes the parameters in the json file so that you can later restore the data to the necessary gui objects. We will do something similar and do it slyly. Take a look at the screenshot:

Presets PureData. We work with several numeric boxes.

As you can see, in the root.pd patch , now three numeric boxes are connected to three objects [store one] , [store two] and [store three] . Each saved parameter is given a name. Now, if you twist the parameters of the boxes and open the preset.txt, you can see something like this:

three 67;
two 43;
one 165;


That is, each parameter in the file was added an index corresponding to the argument entered in the store object. This is done thanks to the so-called abstraction creation arguments . If you look closely at the store.pd patch, you will notice that the route and prepend objects have the argument "$ 1" - these are the arguments. The bottom line is that when using a patch as an abstraction, inside is not $ 1, $ 2, $ 3, etc. are replaced by the first, second, and third arguments, respectively. That is, the [route one] and [prepend one] objects are actually in the [store one] .

Now about that, for which, in fact, prepend and route were added. The first of them before sending the parameter in the textfile creates the same index that we saw in the text file, and route c filters out parameters with non-foreign indexes, when the entire contents of the text file are translated via [p presetSetParam] .

As mentioned earlier, with bang you can display one message from the textfile . When the last message is reached, the object displays bang through the right outlet.

In order to extract all messages, you need to go through the entire file, which makes the until object. This is a very interesting object. If you submit any number, say, ten , to the inlet, it will output 10 bang messages one by one . If the input is simply bang , then until will generate bangs until bang enters its right inlet.

Now you can figure out what happens when you click on the message "recall" . First, bang enters the “read preset.txt, rewind” message , which loads the preset.txt file into the textfile , and then sends the “rewind” message, which makes the next bang received by the object output the first parameter from the file. Then bang goes to the until object, which generates bangs one by one and sends them to the textfile until the latter takes bang out of its right outlet and stops until .

At this point in the preset, you can only save numbers, but in order to be able to be used in real patches, you must add at least the preservation of lists. We do this by creating analogs of the store store for other data types. Rename our store to sfloat and create a slist object.

Presets PureData. Save the lists (lists)

This is a slightly modified patch sfloat.pd , adapted for lists.

The next step is to add the ability to save different presets. Considering how to implement this, I came to the conclusion that it is best to save each preset to a separate file. In this case, there is no need to construct additional logic that separates lines for different presets in a text file, and the smaller the patch's complexity, the more stable its work will be (after all, it’s one thing to save two or three parameters, and another when there will be a hundred).

So, in order to be able to manage multiple presets, we need to change the contents of the message boxes “read preset.txt” and “write preset.txt”, namely change the file names for the corresponding presets. Take a look at the modified storage.pd :

Presets PureData. We work with several presets.

A new object appeared here: makefilename . It is designed to generate file names and is perfect for us. When a number enters the inlet, the object displays a message like “preset-% i.txt” , replacing % i with a number. I also had to display “rewind” in a separate message box, since I did not find an easy way to generate a complex message with a comma.

Everything, now the system works. Now add convenience by making a small gui. Open storage.pd, right-click on an empty place and select Properties. In the window that appears, check the “Graph on parent” box, after which a red rectangle appears in the patch. All interface objects, like buttons, numeric boxes and comments inside this rectangle will be displayed in the patch a la maxio bpatcher . The size and position of the rectangle are set in the canvas window using the size and margin parameters.

Presets PureData. Making a GUI.

This is how the storage object in the patch now looks like:

Presets PureData. The final version of the object [storage].

Now Pd has become a little more comfortable :)

At last


This system of presets is not enough to save the tables, but I will postpone it for the future, as it is likely that some tricky witch would be necessary for us to be comfortable. Also, it would be nice to add an inlet to the storage for external control of the presets, so that you can pull up some MIDI controller.

You can download files from the site pattr.ru from the section "Patches" , enjoy!

direct link

Source: https://habr.com/ru/post/137019/


All Articles