In this tutorial, we look at using the
itable object for data storage, data transformation and histogram tracking. The
itable object can be drawn into, or can be set using various formulae. We will also look at using the
uzi object to quickly generate many
bang messages or streams of ascending numbers, both of which can be used to quickly create lots of algorithmically generated data.
Using a two-dimensional data structure (like
itable) gives us the opportunity to create data transformations that are easy to set up. These
transfer functions allow you to create irregular curves, probability tables that weigh the output based on the input, and random patterns that are easy to visualize. Additionally, the introduction of the
uzi object for the quick generation of procedural messages helps us find a way to create the functions necessary to load these
itable objects in interesting ways.
The
itable object used in this tutorial is virtually equivalent to the
table object, which has its own window and can be typed into a regular object box. The
itable is used here simply because it appears embedded visually in a patcher, rather than in a separate editor window.
In this tutorial's patcher, you will see a few display/drawing patches (labeled with numbers) and several small calculations (labeled with letters). We will start working with the patch area labeled
1. This patch features an
itable object; an object that provides a visual interface to a two-dimensional data structure called a
table. The
table/
itable structure gives us an X/Y combination and a simple interface to this data: send in an number that represents an index on the X axis, and you will receive the corresponding Y axis value.
When you first open the patch, the
itable contains a random distribution of values. If we move the
slider at the top of the patch, it scans the
itable values, and outputs the Y value from its left outlet for the X position represented by the
slider. We have this connected to a
number box and
slider, so we can see the results of the transfer function described by the
itable. Next to the input
slider are a pair of
message boxes with two-integer lists; these will set the location of the first integer (X) to the value of the second integer (Y). Thus, with the first
message box, the value at location
50 will be set to
80. If we click on this
message box, then move the
slider (or
number box) to
50, we can see that the output of the
itable is
80. Likewise, if we click on the second
message box (
100 20), we can see that an input value of
100 outputs a value of
20.
The
clear message “erases” the
itable view, but values are still intrinsic to the
itable; when cleared, the
itable simply assigns a
0 value to every possible data point. Another way to change the values of the
itable is to draw within the
itable itself. If you place the mouse inside the
itable and click-drag the mouse, you can draw in the function contents you desire. If you need to make straight lines, you can hold down the shift key while you move the mouse, and click the mouse to commit the new line. Using these drawing commands gives you an easy way to manually create interesting transfer functions.
Below the patch are three small patches that utilize
uzi objects to generate all of the points in the
itable. If you click on the
A button, a function is created where the input value is the same as the output value. Clicking on
B produces the opposite: input values ranging from
0-127 are converted into a
127-0 range. The
C button produces a
random distribution similar to the starting contents of the
itable object.
Let’s look more closely at these function-generating routines, and particularly at the
uzi object. The
uzi object, as its name implies, is made to rapidly fire off
bang messages. A single
bang to an
uzi object’s input will generate as many
bang messages as are specified in the object's argument; therefore,
uzi 128 will send out
128 bang messages from the left outlet. In order to keep track of the current
bang number, the
rightmost outlet produces a count (starting with
1) – this output is what we are using for the index to the
itable object. In patch segment
A, this count is decremented by
1 (so that it begins with
0, the start of the
itable range), and used for both the X and Y values, giving us the straight line output for a function.
The
B segment is similar, except that the Y value uses the
!- object to subtract the incoming value from
127. This results in a similar ramp, but heading in the opposite direction – the lowest X values have the highest Y values. The
C segment uses a random number generator to create random values as part of the output list. It has to use the
swap object (which simply "swaps" the left and right values it receives) to reverse the order of the list contents so that the
random object's output is used for the Y value instead of the X value.
Let’s alter the
B segment a little to see how different functions could be created. If we change the
!- object to be a division (
/) object with an argument of
4, we will reduce the range of the Y values to only 1/4th of the vertical range. Likewise, if we multiply (
*) the value by
2, we will hit the Y range maximum halfway through the X values. Obviously, with a little manipulation, you can use
uzi and a little math to create many complex functions.
The right-hand patch area (labeled
2) provides an interesting use of the
itable system, as well as several formula patches and a new object called
histo. The
histo object performs a histogram function: it keeps a count of how many times a number has come into its input. Whenever a value comes into the input, the object produces the number of times it has been received out its
right outlet followed immediately by the value itself out its
left outlet - it can then be fed directly into the
itable object, where the left inlet becomes the X and the right inlet becomes the Y. If you use the
slider at the top of the patch to “scratch” in a lot of numbers, you will see the
itable object show the relative distribution of the values you have sent. If you want to clear the
itable and the
histo objects, you can hit the return key on your keyboard (ASCII
13).
Turn on the
metro object with the
toggle at the top of the patch; this will cause
bang messages to be sent to the
itable object. This produces a random “quantile” output to be generated – a random but weighted output value from the
itable object. The result is that the
lcd area below the
itable will begin drawing small circles where the density is roughly equivalent to the distribution curve shown in the
itable routine. If you want to clear the
lcd, you can hit the space bar (ASCII
32) to restart drawing.
As with our first drawing patch, we have a number of smaller patch areas that can be used to generate functions into the
itable object. However, instead of drawing discrete functions, these generate “fuzzy” distributions by sending random and semi-random values into the
histo object; this histogram is then fed to the
itable to generate a probability map. Segments
D and
E use
random and
drunk, respectively, to generate the values. Clicking on the attached
button objects repeatedly will show how each affects the distribution curve –
random hits all of the values fairly evenly, but
drunk is much more “lumpy” in its distribution. Again, we can clear the histogram at any time with the return key.
Patch segments
F and
G take a somewhat different approach. Segment
F generates two
random numbers, then uses the
minimum object to choose the
lower of the two numbers. This will tend to emphasize the lower numbers in the range; repeatedly clicking on the connected
button will show the lower numbers being used more often than the higher values. Segment
G does the opposite: it uses the higher of two
random numbers by putting them into the
maximum object. Thus, repeatedly clicking on the connected
button will tend to generate more high numbers.
Finally, segment
H creates an average of 3
random numbers by generating the numbers, adding them together, then dividing the sum by
3. If you clear the
itable and repeatedly hit the
H button, you will see a “bell-shaped” curve being generated, since the average of three random numbers will tend to be in the middle of the range. This is a simple type of
Gaussian (or normal) distribution, and is commonly found in statistical research when most subjects fall within the middle of a range of possible values.
In each of these cases, having the
metro running during our function generation should cause the drawing to simulate the distribution curve in the
itable object. To test more radical curves, you can draw sharp lines within the
itable object to force certain output curves; you can also use the
slider to “shade” in parts of the equation, causing the drawing output to shade in segments in response to the new distribution curve.
Many different processes depend on the ability to create functions that transform an input range into an output range. In previous tutorials, we saw how the
scale object could do this for us. However, if we want to manually change the distribution of values, or if we want to use a formula for data transformation, we need to use a more complex system. As we’ve seen in this tutorial, the
table/
itable objects serve this purpose perfectly, giving us the ability to either manufacture or manually draw a transfer function.
Using the
histo object, we also saw how we can generate the sort of distribution curves that serve as common random techniques in generative art and stochastic music. Whether the fuzziness of true random generation, or the tendencies found with more discrete math, these curves can be used to both generate and guide results to a desired outcome.
See Also
Name |
Description |
table |
Store and graphically edit an array of numbers
|
itable |
A table in a patcher window
|
uzi |
Send a specific number of bang messages
|
swap |
Reverse the sequential order of two integers
|
histo |
Make a histogram of the numbers received
|
minimum |
Output the smallest in a list of numbers
|
maximum |
Output the greatest in a list of numbers
|