Vous êtes sur la page 1sur 22

Patch-a-Day November 2011 Day 14 Data Structure Basics (part 1)

Posted in Patch-A-Day, Pure Data - 16 November 2011 - No comment

Starting at the beginning with data structures. Theres a lot to take in, but its pretty cool once
you get down to it. I found the old patches I wrote when I was getting to grips with it all the
first time round which is pretty helpful but this time Ill actually write things down heh.
First up, you can think of Data Structures in PD as lists of items, where each list has a specific
name, and the items they contain can be floats, symbols, arrays, or a list of other data
structures. To navigate around these lists you use pointers, which literally just point to a
position on the list.
When creating a patch that uses data structures, there are three parts that really make the
structure. These are a template, a struct and a datawindow. The template is a subpatch that
contains a struct. The struct defines what data the structure contains and the datawindow will
contain the data.
The data is stored as an ordered list of scalars, where a scalar would contain an entry for each
of the values defined in the struct. The lists are navigated by using pointers, one of the PD data
types, that literally just point to a single scalar in the list.
Lets have a look at a patch to try and clear some of this up.

Basic data structure


In the top left are the three objects that make up the data structure. The template1 subpatch
contains a single struct object. The struct defines a structure called struct1 with a single field,
the float a. The datawindow1 subpatch has no objects in it. One thing to note at this point, the
name of the struct has to be unique throughout PD otherwise youll get an error being thrown,
the same goes for the datawindow.
Now that the data object has been constructed, we need to add some data to it and we can do
this using the append object. This takes a pointer into its rightmost inlet and then the values to
store are entered using the other inlet. Append is given the name of the struct that it will be
modifying and also an argument for each value in the struct we want to modify. If you have a

struct with multiple values then you dont need to modify all of them.
The pointer object gets given a message to tell it which datawindow its pointing to and then a
bang to get it to output the value of its current pointer. When we first initialise it with a
traverse message the pointer will point to the head of the list. This isnt actually a scalar but is
the position in front of the first scalar element so any value appended to it will get added after
this. The pointer goes to the append object to tell it where it will be appending the values.
Sending the pointer a next message will get it to move to the next scalar in the list, to begin
with that will result in an error because there arent any other values, but if there were it
would mean we could append after any position in the list.
The append object will increment the pointer it has itself, so all thats needed is to send it the
pointer then send whatever values we want to store in the left inlet.
To retrieve them you can use the get object. This works in a similar way to append with the
arguments tell it what struct and what values its dealing with and the pointer telling it which
scalar to retrieve. This time its necessary to step through manually and you can do that with
next.
Heres an example of how easy it is to extend this to more float values if you want.

Data structure with multiple values


Not sure Ill be able to get another post out tonight unfortunately, relearning this stuff has been
a bit of a crash course and took longer than I expected. Either way, I know the direction Ill be
heading with this over the next few days so I shouldnt have any problems working out what I
want to patch.

Patch-a-Day November 2011 Day 15 Data Structure Basics (part 2)


Posted in Patch-A-Day, Pure Data - 18 November 2011 - No comment

Apologies for missing yesterday, I was at the London Hackspace for the weekly music hackers
meetup thats been gathering steam and I find that now I know a few more people there I
quickly get sucked in and dont get around to working on the patches like I should be.
Ive also realised that, unlike last time I did the patch a day month, I have a lot more projects
and a fair bit more socialising going on. So I think Im going to not worry too heavily about
getting a new patch done every evening and instead just concentrate on getting them done in a
timely manner and making them good. That said, Patch-a-day-ish Month plus some days
doesnt have the same ring to it.
Anyway, onto the patch for tonight. Getting data from specific positions in a data structure list.

Getting specific values from a data structure


The left hand side is the template, struct and data window which should be familiar to you now.
The right hand section can be used to automatically fill a data structure list with some data. It
sets the pointer to the head of the list and sends it to the append object. Then it increments a
counter using the until object and gives each of these values to the append as data, quickly
filling it up.
The central section is the important part here. It takes an integer and then outputs the value
stored at that position in the data structure. To do this, first the pointer object is given a
traverse message, setting it so that it points to the head of the list. The until object then sends
out the specified number of bangs which trigger next messages, incrementing the position of
the list pointer.
Because we only want the specific value and not all the values, the pointer value that comes out
at each next message is stored in a second pointer object. These work pretty much like float
objects where a value passed into the right inlet is stored but not output. Once the until has
stopped the value from the second pointer is output to the get object which puts out our value.
Its worth mentioning the bang object hanging off the first pointer. This is so that if we give a
value greater than the length of the list we wont get errors being printed out. When the next
messages cause the pointer to hit the end of the list it will output a bang from the right outlet,
this is sent to the until to stop it running so we end up just getting the last value.
Next stop is setting specific values in lists, then Im going to start tackling some of the visual
stuff you can do.

Patch-a-Day November 2011 Day 16 Data Structure Basics (part 3)


Posted in Patch-A-Day, Pure Data - 19 November 2011 - No comment

I almost think that tonights patch and last nights should have been rolled together into one
post but Ive also been thinking that some of these post can suffer from being too long and Id
prefer to have a greater number of smaller, more understandable posts.
This time Im looking at the set object, but in truth theres really not much too it.

Setting values for specific data structure items


The set object is located at the bottom of the patch and is really just a slightly modified version
of the get section. The until object gets given a value, it increments the pointer to that position
in the data structure list and then the value can easily be updated. This idea of incrementing
pointers to get to specific places in a data structure is pretty important to grasp I feel.
Im going to do one post on using the graphical capabilities of the data structures next but Im
only planning to spend a single post on it for the moment. Other possibilities to play with I
think.

Patch-a-Day November 2011 Day 17 Data Structure Basics (part 4)


Posted in Patch-A-Day, Pure Data - 19 November 2011 - No comment

Drawing basic polygon shapes with the data structures is actually pretty easy it turns out. This
is one of the things that had confused me the first time I looked at it but having spent the
morning reading up, it turns out its not that tricky. Have a look at the patch below first of all
and then Ill run through what it does.

Drawing polygons with data structures


The top left section with the border is the contents of the template1 subpatch. Theres a struct
which defines eight float values, and a filledpolygon object with a bunch of arguments, most of
which match values in the struct. Looking at the main patch, the collection of objects here will
fill the data window with some number of struct1 objects. These objects will have random
numbers for six of their eight values, with the other two, x and y, defaulting to zero.
The filled polygon object is what does all the work here. It tells PD that in the datawindow we
want to draw a polygon with a certain number of points, a specific centre colour and a border
with a specific colour and thickness. The argument order is :
1. Internal colour in RGB value.
60 here means 060 which translates to medium green
2. Border colour in RGB.
1 here means very dark blue
3. Border width in pixels
4. List of points to join as (x,y) coordinates
In this patch, the coordinates are actually values stored in the struct. This means that any
polygons drawn will have three edges, with points at (xa,xb), (ya,yb), (za,zb). Hit the message
box with the 5 in it and have a look at the data window. You should see something like this,

Polygons in data window


Five green triangles with black borders, each of them representing a scalar in our data
structure. The cool part about this is that if the patch is locked, when you can select one of the
points on a triangle and move it around this will affect the data in the struct. Using this its
possible to create some quite interesting user interfaces and ways of more simply manipulating
complex data sets. To see the values of the scalar that defines the shape, right click on it and
select properties.
One last thing to point out. In the struct there are two float values called x and y. These are
actually special and are used to set the overall position of the shape. Unlock the patch, select a
shape and then move it around. This will only affect the x and y values, not the position values.
Hopefully youve grasped everything thats happened so far with the data structures, if not go
back and have a read of the previous posts. Ive actually found learning the polygon drawing
stuff to be quite interesting so I might come back to it at some point. For the next couple of
days though I want to start building a data storage and preset system. Its something that
should end up being pretty useful and Ive been meaning to get to it for a while.

Patch-a-Day November 2011 Day 18 Data Structure Basics (part 5)


Posted in Patch-A-Day, Pure Data - 21 November 2011 - No comment

Ok, not quite done with data structures yet. I realised that I should probably go over how you
store symbols and arrays in a data structure. Tonight its a quick post on symbols, Ill try to
cover all of arrays tomorrow.
The first thing to know is that storing symbols in a data structure is almost, but not quite like,
storing floats. You cant actually use the append objects to create a new scalar with a symbol
directly. You instead have to create the scalar, then set the symbol element once its made. This
feels really kludgy to me and Im going to be doing some investigating to see if theres
something Ive missed. But this appears to be the way its done.

Storing symbols in a data structure


The struct were dealing with defines a float and a symbol. I realised that you need to have a
float as an element in the struct because otherwise I cant see a way to create a new scalar. The
set object can only update values, not create new scalars. So the append object is used to
create some scalar entries in our data structure. The set object can then be used to update the
values for our symbol.
Notice that theres now a -symbol flag there. This means the set object will accept symbols BUT
can only accept symbols. There would need to be two different set objects now, one to set the
value of a, the other for b.
The get object still works exactly the same, the outlet for a sends out its float, b sends out its
symbol.
I realised that symbol storage is actually pretty important, mostly just so in a preset storage
system you can give names to the presets. The array storage Im still working on at the moment
though its not too much more complex. Patches will be with you tomorrow.

Patch-a-Day November 2011 Day 19 Data Structure Basics (part 6)


Posted in Patch-A-Day, Pure Data - 22 November 2011 - No comment

Arrays in data structures are a little tricky it seems. Not too tricky, but they require a couple of
extra objects and like symbols, it seems that you cant have a scalar with just arrays. This is
because to modify an array field in a data structure scalar, you need to first create that scalar,
and you can apparently only create a scalar using a float sent into an append object. If Ive
got this wrong then someone feel free to tell me.
Anyway, there are three new objects to use with data structure arrays, setsize and getsize
should be pretty obvious, element maybe not so much. Have a look at the patch and Ill go
through whats going on.

Array manipulation in data structures


There are now two templates in the patch, each of which contains a struct. The first struct is
called struct 1, it defines a float field called a, and an array field called array1. When defining
an array its necessary to give a third argument which is the name of a struct that will hold the
array information. That second struct is held in the second template, is called testarray and has
a single field, y.
Two things worth pointing out here. First, you can draw arrays in data windows like we did
with the polygons, and like with the polygons, the field y is special. This is the value that will be
used to draw the height of the polygon. This actually leads into the second point, the struct
thats used to define the array is really just a normal struct, and so can store data in the same
way. If you download the repository then theres a second patch called nested structures,
where this second array has another float field and a symbol field. This should explain
somewhat why the y field is special, because its just the same as with regular polygons and
data structures. In short, a data structure array is actually just an array of other nested data
structures.
In the top right of the patch theres an append setup. This is just there so that when the patch
loads a new scalar object is created in struct 1. This needs to be done because to operate on
the array, we have to have an array in the first place.
Below this is the interesting stuff. First a pointer object is told to traverse the datawindow and

then increment onto the first scalar element, the one created above. This goes to a setsize and
getsize object which, unsurprisingly, set and get the size of the array. All arrays have a
minimum of one scalar element.
The pointer also goes to the element object, which has arguments pointing it to the data
structure struct1, and the field array1. This object takes a float in the left inlet and will send
out a pointer to that position in the array. It plays the role of the until + counter setup weve
previously used to get to specific scalars in a data structure. Bear in mind that you can only get
a pointer to a scalar in the array that exists, so better increase the size of the field using
setsize.
The pointer from element can be passed to set and get objects which work exactly like they do
with normal data structure scalars.
Have a play and investigate, its pretty much the best way to get a grasp of whats going on
here. Once you have it however it should be pretty useful, especially with the preset patches
that I will get to tomorrow.

Patch-a-Day November 2011 Day 20 Preset saving


Posted in Patch-A-Day, Pure Data - 23 November 2011 - No comment

Preset saving, done the simple way.


Well, maybe not that simple, this isnt some magical system that can be used like MaxMSPs
autopattr system, but it should give a fair degree over the saving, loading and control of
presets in PD. Ive dug out the synth voices patch from Day 3 again and Im going to be
modifying the control abstraction so that that also stores the presets. This should again show
that a nicely arranged and abstracted patch is a good thing which allows you to modify and
extend without messing things around. Have a look at the main section of it.

Control abstraction with presets


All thats actually added here is a couple of extra control, a loadbang to set the preset number
and a small subpatch called preset. Its the internals of this that are whats interesting.

Preset saving patch


First things first, the section on the right is there to create the ten scalars well be saving our
preset values in. At the moment this clears the window on start up and creates ten new scalars.
This isnt really that useful if we want to have our presets saved with the patch itself, but this is
just temporary while we build it so ignore it for now.
The data template and data window patches are contained here, both with names to make sure
theyre unique throughout the patch. The data structure has a float field for each of the
settings were saving (and an extra one here called number which isnt actually needed, I just
forgot to take it out). The right hand inlet of the patch takes in the preset number, i.e., the
position we want to save our values at. This value gets sent to a trusty bang into until into next
into pointer setup so that as the preset number choice changes, the set object will always be
saving to the correct place.
The clever bit here is that were able to reuse the param objects from the previous patch. As
values on the controls are updated in the control abstraction, those values are now also sent
into these param objects as well. When the save button is pressed, it makes these objects dump
out their values, these are fed into the set object making sure to keep the order of execution
right. Hey presto, preset saving! Really not much to it.
Tomorrow (or maybe Friday night) Ill show how the presets can be loaded back out.

Patch-a-Day November 2011 Day 21 Preset loading


Posted in Patch-A-Day, Pure Data - 25 November 2011 - No comment

And now for the patch to load values out of the saved preset and into our settings. This might
seem a little under whelming because theres not much to it, but a lot of the work was already
done by the infrastructure already in place.

Preset value loading


I made a change to the previous section so that the pointer values wont be calculated until you
hit the load or save buttons. Otherwise youre just adding in a bit of needless overhead.
The loading is even simpler than the saving, the preset patch number is selected, the load
button pressed and the until object is used to calculate the pointer position. This pointer then
gets sent to a get object which retrieves the values we want from our data structure scalar. The
values then get sent straight to the gui elements in the above patch.
Simple, but pretty effective.

Patch-a-Day November 2011 Day 22 Preset file saving


Posted in Patch-A-Day, Pure Data - 27 November 2011 - No comment

The preset loader is working pretty well, but at the moment its limited to only saving presets
within one PD session. If we close and then reopen the program then all our presets are lost.
To make this really useful, you need to be able to save the data structure info and have it
loaded up next time you start the program up.
Luckily Pure Data allows you to save the data structure information to a file and then read it
back in later, and we can use that to make our preset information usable between sessions.
Heres the updated preset object.

Preset data structure files


The patch now has a third inlet that can be used to give clear, file load or file save commands.
The clear command is just the initial blank patch loadbang setup that has always been in the
patch. This means we can clear all the presets and reload ten blank presets if we want.
The fileload and filesave commands will give a symbol to a makefilename object. This will give
us a filename in the format preset_<name>.pdc actually saving or loading the data to and
from the file is as simple as sending a read or write command to the data window patch. Here
Ive had to get the $0 value worked into the setup but thats only necessary if your data window
uses it.
So now we can save presets between sessions, have multiple abstractions load and save to a
single file and can start making some much easier to use performance patches.
One thing to note that Ive found. In the file containing the data structure data it has the name
of the data window it was saved from. When you reload the data from the file, if the name
inside the file matches the data window you load into youll get a multiply defined error. This
doesnt seem to cause any issues, but I mention it to stop any confusion.

Patch-a-Day November 2011 Day 23 Generic Preset abstractions


Posted in Patch-A-Day, Pure Data - 2 December 2011 - No comment

Back on the case finally. Too many things on the go and fairly behind on Patch-a-Day. Im
planning on getting quite a few patches built this weekend so I should be finished with the 30
days by mid way through next week, hopefully.
Anyway, this evenings patch is an extension of the preset saving that weve been looking at. I
realised that actually it was very easy to move the get and set objects into their own
abstractions for each preset value youre interested in saving. Its using the same sort of
passthrough design Ive talked about and it results in much less clutter and much more useful
code I feel.

Individual preset parameter abstractions


The bottom section is whats actually in the preset-param abstraction. This time the loading
and saving are being triggered by a pointer sent into either the left side for saving, or the right
side for loading. The param objects still get and set their values using the send and receive
objects and now its very simple to add more parameters to store in our preset.
Im probably going to turn the file loading/saving and structure clearing section into an
abstraction as well, at which point this should all work as a fairly generic solution. There are a
few other things I think could be added but Im probablly going to be leaving this for the time
being.
Ive decided over the weekend Im going to build up a sequencer based on my Novation
launchpad and using the data structure and preset stuff Ive been learning. Tomorrow is a new
day, full of patching!

Patch-a-Day November 2011 Day 24 Step Sequencer Basics


Posted in Patch-A-Day, Pure Data - 3 December 2011 - No comment

Ive just noticed I think I missed out a day somewhere. This patch is patch 25 in my
repository, but its day 24. Looks like I made a patch titled Improved presets and havent
written it up but oh well. I might go back and slot it in if I think its missed out anything vital.
On with the step sequencer for the moment though. Im designing this to run on my Novation
Launchpad, the plan being to have eight tracks with 64steps each. Track selection will be done
by the left hand row of function buttons and all track steps displayed on the grid. The first
thing to do is work out how the pattern will be stored, and Ive decided that the data structures
are the right way to go about doing it. Below is the beginnings of the patch.

Beginning of the data structure sequencer


Structure and datawindow patches in the top left corner, struct has eight float fields named a
to h. The central section just clears our window and creates the data for the 64 steps. The
section on the right is just to that I can write out the data to a file for debugging and wont be
there in the final patch.
The group of daisy chained objects on the left hand side are dealing with saving and loading
the data about individual tracks. The left hand inlets/outlets deal with setting individual steps
for specific patterns. The middle is so the object can receive a pointer to a specific step and
load the value from it, the right hand inlets/outlets are where this data comes from. For the
moment only the saving works, though the loading doesnt need much more done.

Basic track abstraction


Ive realised that in patch comments are probably a good idea heh, so Ive started adding them.
As they show, the creation arguments for the abstraction are the name of the data window, the
name of the struct and the name of the field to set or get.
One of the things I decided for this was that the functionality for getting the right pointer when
setting a value should be inside the abstraction, but when getting the value the pointer should
come from outside. My reasoning was that when getting the value from a step were actually
going to want to get the value from all the steps and, because they would all use the same
pointer, it would be wasteful to repeat that functionality. When were setting a value were
usually just doing it for one track so its simpler to contain that inside the abstraction.
The abstractions all use the passthrough design so when a message comes into the left hand
inlet it is routed to the correct place by checking for the field name. From here the step
position triggers a standard traverse->until>next style setup and then the value is set using the
set object. Try sending some messages in and then saving the data to a file so you can have a
look. This works pretty well and should mean the entire sequencer itself will be pretty compact.
Tomorrow Ill get the the retrieving side of it done, then time to start on interfacing it with the
launchpad.

Patch-a-Day November 2011 Day 25 Step Sequencer Clock


Posted in Patch-A-Day, Pure Data - 4 December 2011 - No comment

OK, carrying on from yesterdays patch, lets get the stepping and clock for the sequencer.

Sequencer clock and output


The setup here is really pretty simple, but theres a couple small things to note. Im routing for
clock and reset messages, just to make things obvious when you;re controlling the sequencer.
The reset message gives the pointer a traverse message which resets it to the head of our list
of scalars. The clock message will trigger a next message to be sent to the pointer which will
then send its value to the series of daisy chained objects. This will cause all of them to output
their values and they can be seen printed out to the console.
The trigger object is there because of how the pointer deals with coming to the end of a list.
The pointer will output a bang, upon receiving a next message once it has already output the
last list element. we want that final bang to send it back to the beginning, and
then immediately output the first list element. To do that, when the pointer sends out its bang,
it first triggers a new traverse message, and then triggers another next message, meaning the
first step values get sent out.
Next Im planning to neaten this up a bit, and then we can start dealing with Launchpad input.

Patch-a-Day November 2011 Day 27 Launchpad sequencer


Posted in Patch-A-Day, Pure Data - 5 December 2011 - No comment

Right, time to hook the launchpad up to the sequencer. Ive modified the Launchpad IO
abstraction to neaten it up and make it actually deal with output and input. The sequencer
patch has been changed so that incomng grid messages are converted to a stop number and
the mode buttons select the track number to update and the main clock is now on the outside.
Lets run through them and Ill explain a bit about whats going on.

First launchpad sequencer


The sequencer is now the steps abstraction and the first argument tells it how many steps we
want to have. The basic metro clock is still there, entirely unchanged. The launchpad_io
abstraction now takes the channel as an argument as well. All simple and a bit dull.

Improved launchpad IO
The launchpad IO now just deals with outputting the MIDI in messages and sending the MIDI
out messages. All IO goes through a single inlet or outlet and all messages are prefixed with
either grid, mode or ctl to show where its from or going to. Theres also the reset option
available which sends the clear message.

Updated step sequencer


The step sequencer now has a bit more functionality. It takes the input direct from the
launchpad and pulls out the grid and mode button messages. The mode messages control
which track we are updating and do that by pre-pending the track name onto the front of the
grid message. The tracks then route for this as they do normally. Note the spigot on the mode
section, this is there so that only button on messages get through. We dont actually care about
button off messages here so we just stop them coming through.
The grid messages are converted from their XY format into a single value that gives the step
position. At this point it may be clear that there is a problem with the current setup. The grid
buttons also have button up and down messages coming through, so when we press a button
the 1 value gets stored, but as soon as its released the 0 is stored over the top of it.
For the moment Ill let you think about how you might solve this, tomorrow Ill show you how I
do it.

Patch-a-Day November 2011 Day 29 Launchpad lights


Posted in Patch-A-Day, Pure Data - 7 December 2011 - No comment

Sending output to the launchpad is pretty easy. Sending the right output, in a way thats easily
configurable and fits in with the standard is a little trickier. Ive had more of a read of the
Launchpad programming guide and have a better handle on the double buffering and so on and
Ill put some of that into practise here. The updates to the sequencer here are, I feel I should
point out, as pretty or high performance as they could be. Theres definitely a lot more
tweaking needed.
One of the things Ive found a bit of a problem is sending the large number of update messages
to the launchpad. Theres a slow down in PD whilst its going. I dont know if its due to the
MIDI output, or just trying to send a mass list of 64 messages and needing to make the process
more efficient but more investigation is needed.

Step sequencer track with light output


This is the updated track abstraction with the output for the light states. The left hand section
that updates the data structure will now also send out a message with the new value of the
updated step. The right hand sections are for dumping out the state of all the steps in the data
structure. This is used when changing tracks as we want to update the launchpad with the new
values and clear the old ones. By dumping out the state of all on or off steps we clear the old
data and fill the grid with the new. This could be made more efficient by first clearing the grid,
then just sending the steps that are on but i decided this is initially simpler to deal with.

Full sequencer with light state output


The main sequencer section has been updated as well to parse the data now being output by
the tracks. The objects right at the bottom will take the step messages, convert the step
number back into the XY coordinate and change the 1 or 0 value into the correct note velocity
for the colour we want. The clr abstraction works differently now just to point out. It takes two
arguments, one is the colour value to send out when it gets a 1 input, the second for when it
gets a 0 input. Im following the Launchpad programming guide by sending out a value of 12
for off. This apparently makes it easier to add in double buffering later which might well be
necessary.
Theres also a small section in the middle at the top that sends out the light on/off messages for
the mode lights. The tracklight patch just keeps track of the current track number and, when
the track changes, will send out an off message for the old button and an on for the new one.
As I said, theres actually a fair bit of work that needs to happen on this to make it fast enough
but its not bad as a start. Ill probably concentrate on tacking on the drum sounds for the next
patch-a-day and then call it finished for the moment.
That will also actually be my last patch-a-day patch for this round. Im going to be continuing
work on this sequencer and Ill be writing more of it up, just not worrying about doing it once a
night though heh.

Vous aimerez peut-être aussi