Data Tutorial 2: Data Scaling
This tutorial is focused on data scaling and smoothing issues. It introduces the iter object for list iterations, and the trough, peak and slide objects for data scaling and smoothing. We will also look at additional data display options for the multislider object – in particular, the ability to set a minimum and maximum range, and using the peak-hold monitoring in that object.
Different Max objects and physical devices produce values of different ranges and formats. One of the tasks that you will often perform is altering the incoming format and scale of a data-set to match the format and scale needed for your output. While earlier tutorials described using the scale object for this function, we might need to employ other objects to find out the numerical range for our scaling first. The objects introduced in this tutorial offer new options for scaling, smoothing and viewing data to suit your programming needs.
To open the tutorial patch, click on the Open Tutorial button in the upper right-hand corner of the documentation window.
Examination of new objects
Take a look at our tutorial patcher: on the left side of the patcher is an overview of a few new objects (outlined in green). The top-most patch shows the iter object in use – it accepts a list, and outputs the individual values in order. When we click on the box, the four-value list is sent to iter, which outputs four messages – each one containing one list item. This is the simplest way to turn a list into a data stream, and (as we will soon see) is useful for atomizing the contents of a list in order to trigger a new event from each list element.
The next subpatch has examples of both the trough and peak objects. They serve complementary purposes: both objects examine an incoming number stream, with trough capturing (and outputting) the lowest value received thus far, while peak captures and sends the highest value. When we change the value in the number box, we see that the objects capture the low and high values, with new output occurring whenever a new high or low is reached.
Finally, the bottom subpatch shows three uses of the slide object. The slide object is used for smoothing out data based on a “smoothing factor”, with separate factors for upward and downward movements. The function of the smoothing factor is rather simple – it is used to divide the difference between the last received message and the current one, thereby reducing the amount of “swing” in any value transition. The smoothing factors are provided as two arguments to the object: the first argument is the factor for upward movement, and the second argument is the factor for downward movement.
For example, when you first start the patch, the “last” value is number box connected to the slide objects), you will see that the first slider moves to . This is because there was an upward transition in value, so the first factor ( ) was used: the difference between the initial value of and is ; this difference is divided by the factor ( ) to yield .. If you make an immediate transition to (which you can do by entering a value into the
The three slide objects show different smoothing factors: the first provides even factors for both upward and downward movement, the second has no upward smoothing (a factor of 1.0), and the third has a small downward factor (a factor of 10.0). As you move the input slider you will see that each output multislider responds differently – smoothing the output in relation to the upward and downward smoothing factors of each slide object.
The main patch overview
The main patch uses weather data as source material; it drives the display in our multislider, and is also used to create four-note chords for playback on the computer’s internal MIDI synthesizer. Double-click the two coll objects in the patch to become familiar with their contents - both contain twelve lines of data, where the output of one serves as the index of another. When you start the metro at the top of the patch with the toggle object, the messages are used to generate calendar information – specifically, the output of a counter (which is counting days) is used to query a small coll database that outputs the months based on what days in the calendar year they start - e.g. day of the year is the first day of month (April). This month value (in the range to ) is then used to query the coll loaded from the file weather.txt, which contains the average monthly temperatures in four cities (New York, Paris, Buenos Aires, and Tokyo). This data is unpacked (since it comes out of the coll in the form of a list) and is sent to four float (abbreviated "f") objects. The metro then bangs the float objects to create a stream of output. This is a good technique for use in systems where you require something to happen on a regular clock but the incoming data is not produced at a constant speed - in our example, the list of temperatures only come out of the coll object when the month changes.
The output of the float objects are sent to slide objects with a smoothing factor of for both upward and downward movement. This means that, while the same value may be sent as many as 31 times (since there are up to 31 days in a month), the value will still change as the smoothed output catches up to the actual value. The outputs of the four slide objects are packed together and sent into the multislider, where they are displayed. This newly created dataset is also output from the multislider, where it is split apart (by the iter object) and used to make four notes for synthesizer playback.
This multislider uses a few new techniques for data display. Open the object inspector for the multislider, and you will see that the attribute is set to , which gives us the filled bar. The option is also activated, so that the bars are colored based on the colors in the inspector. Finally, there is a option set, which causes a small bar to be located at the top of the highest point that the value reaches. This gives us a visual indicator of the peak value seen for each of the four cities.
There is a toggle connected to a message box that can turn off or turn on the peak hold function; this is a good example of using inspector-type messages to control the function of an object. Since any change to the attribute should reset the peak tracking, a companion message ( ) resets that value any time the toggle is changed.
The min/max section
The other part of this patch worth examining is the setup performed just to the left of the main patch. This patch section has a singular purpose: to set up the multislider for proper display scaling. A message (either sent by clicking the button, or generated by a loadbang) starts by setting the trough and peak objects with very high and very low thresholds, respectively - this guarantees that any new value sent to them will automatically set a new standard within the object. The then triggers a message to the coll object, which causes all of the entries to be sent from the object, one list at a time.
As the lists are output, they are processed by an iter object, that splits the lists into single-value messages. These are examined by the trough and peak objects, which find the lowest and highest values in the data set ( and , respectively). When either value is found, it causes the pak object to generate a value list, which prepend attaches to the message that is sent to the multislider. This changes the display range that will be shown, causing the multislider to limit its display to the actual range of high and low temperature that will be output by the coll. In this way, the multislider display is automatically calibrated to the temperatures stored in the weather.txt file.
In this tutorial we’ve seen how to analyze data streams (using iter, trough and peak) and smooth their output (using slide). We’ve also seen some programming patterns that can be useful for automatically setting up UI elements, and for outputting data when new data is sent less frequently than it is needed. Finally, we further explored the flexible multislider object, using it for a bar display with peak hold values and full-color display.
|iter||Break a list into individual messages|
|peak||Output larger numbers|
|trough||Output a number if it is less than previous numbers|
|slide||Smooth values logarithmically|