Académique Documents
Professionnel Documents
Culture Documents
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
OK, carrying on from yesterdays patch, lets get the stepping and clock for the sequencer.
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.
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.
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.