Skip to content

Max Delta

My Favourite

One of my favourite tricks in Max is a very simple one: calculate the delta of two numbers. It is often very useful to know the delta values of a stream of numbers. Delta is the difference between successive values and if there is a sudden big change it could indicate that something, somewhere might not be going right…

How NOT To…

It is super simple to do a delta calculation in max. Doing more complex ones, like comparing your current value to one further back in time, or to a mean value is also not that hard. First let’s look at how NOT to do it. These are some examples I have seen in code of students and more seasoned practitioners alike.

Overly complicated way of calculating delta values…

(see below for the contents of [randomWalkWithSpikes] and the unnamed subpatch)

There is nothing overly wrong with these two approaches. They work! If I had to choose one it would be the [cycle 2] variant.
There are many ways of doing things in Max, but trying to understand the underlying problem/system can help us create code that is as simple as possible in order to minimize bugs and issues once the patch/project starts to grow.

How To…

And here is how I have been doing it for years:

Very easy and simple way to calculate delta values…

Simple, to the point and there isn’t much that can go wrong (fingers crossed). So what is happening exactly? We need to understand two Max concepts in order to understand what’s going on here:

  1. Hot and cold inlets
  2. Order of operation (here: right to left ordering)

The cold, blue, right inlet of the subtraction object stores the number from which we subtract. The hot, red, left inlet does the calculation, subtracting the incoming number from the stored number (stored from the right, cold inlet). This means we can update the right inlet as often as we like and will never get an output.

Hot inlet triggers action while the cold inlet stores a value to be used when triggered

Next, we fix the order of operations using the [trigger i i] object. The trigger allows us to be 100% certain which message will come out of it first, and in which order. It is always from RIGHT to LEFT.

When we combine these two pieces of information and look at our simple patch again, we see that the each incoming number is used twice:

  1. Do the calculation right away by triggering the left inlet
  2. Store it in the right inlet so it can be subtracted from the following number

Let’s add a breakpoint and follow the flow of two numbers:

Stepping through the an example to understand the order of operations…

Although this was quite a bit of text, the patch itself is very simple. Make sure you understand the order of operations as well as hot and cold inlets in Max and you are good to go.

Adding Complexity

What if you want to compare your current value to a value further back in time? Here is a time based example, delaying each calculation by 1000 ms as well as a sample based example, delaying each calculation by a certain amount of samples:

What if we want the mean value of the last n samples? Well, simply add:

How could we use this in a real scenario?
One very common and simple thing to do would be to detect high delta values (peaks) and filter them out by repeating the last “good” value:

Detect and remove spikes from data…
filterPeakRepeatPrev subpatch content

This can grow in complexity according to the individual situation. But always keep in mind: what is the problem I am trying to solve. Is there a built in way to solve it or do I need to find a custom solution? If I need to go custom, what are the underlying components and how can I create those in a Max specific way.

Happy patching!

And for completeness sake here is the content of the [randomWalkWithSpikes] subpatch as well as the unnamed patcher shown throughout:

randomWalkWithSpikes subpatch

MRprobGate is a probability gate that has a 5% chance of creating a spike.

Unnamed subpatch content

Get the finished patch here!

Become a Patron!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.