Max Debugging Max Debugging
Synthesis Techniques — Dr. Louis Goldford (2024)
These slides will discuss:
These slides will discuss:
You guessed it...

Debugging

bug!
These slides will discuss:
...More specifically...
What is Debugging?
Message Order in MaxMSP
Hot + Cold Inlets
Monitoring Control and Signal Output
Event Probe and Signal Probe
Watchpoints

What Is Debugging?

Debugging is...

“the process of finding and resolving bugs (defects or problems that prevent correct operation) within computer programs, software, or systems.”

Wikipedia

What Is Debugging?

But it can also be thought of as...

a process of identifying

  • what variables
  • hold what values
  • at what point in time.

—Rebecca Hill,
Debugging Specialist
JavaScript Developer
WeTransfer.com

What Is Debugging?

In MaxMSP, this can also be extended to...

a process of identifying

which object boxes and patch cables

boxes + cables

What Is Debugging?

In MaxMSP, this can also be extended to...

a process of identifying

which object boxes and patch cables

are carrying specific signal and message values

boxes + cables

What Is Debugging?

In MaxMSP, this can also be extended to...

a process of identifying

which object boxes and patch cables

are carrying specific signal and message values

at any point in time.

Message Order — Part I

To understand this process better,

Let's first discuss the order of messages in Max.

Message Order — Part I

By now, you probably realize that data flows top-to-bottom in your patch:

boxes + cables

Message Order — Part I

But for object boxes that have more than one inlet or outlet,

data also flows right-to-left.

boxes + cables

Message Order — Part I

When we design our own patches,

most mistakes (“bugs”) happen

because we forget the message order!

bug!

Hot + Cold Inlets

To help us remember messaging order,

look closely at the colors of an object’s inlets...

cold inlet

Hover your mouse over the right inlet.

Notice it is blue.

Hot + Cold Inlets

cold inlet

The blue inlet indicates

that this is a cold inlet

because it is on the right.

Hot + Cold Inlets

cold inlet

Cold inlets do not trigger output from an object box.

Instead, they replace the argument(s) of the function typed inside the box.

Hot + Cold Inlets

cold inlet

For example, if we type a new number in the integer box, it will replace the number 4,

which is the argument to the + function.

...But, curiously, it will not trigger output from the + function...

Hot + Cold Inlets

random.cold

If we set up the patch above,

the metro object will generate a new random number between 0-100 every 200 miliseconds.

Hot + Cold Inlets

random.cold

But no matter how many numbers we generate,

we will never get output from the + function...

because the numbers are only feeding its cold inlet.

Hot + Cold Inlets

hot inlet

Next, hover your mouse over the left inlet.

Notice it is red.

Hot + Cold Inlets

hot inlet

The red inlet indicates

that this is a hot inlet

because it is on the left.

Hot + Cold Inlets

hot inlet

In this case, the hot inlet sets the left operand to the + function,

and most importantly, it triggers output from the object box.

In MaxMSP, the left inlet always triggers output.

In other words, output is triggered any time an input is delivered to a left inlet.

Hot + Cold Inlets

hot triggers

If we set up the patch above, with a new random number process feeding the hot inlet,

the metro on the left will generate a random number every 50 miliseconds.

That’s much faster than the cold inlet, which only receives a new number every 200 miliseconds.

Hot + Cold Inlets

hot triggers

The numbers received in the hot inlet will always trigger output,

in other words, every 50 miliseconds,

While the numbers on the right update much more slowly.

Hot + Cold Inlets

hot triggers

This snapshot of the patch above represents a discrete moment in time.

At this moment, the cold cable is carrying a value of 23,

while the hot cable is carrying a value of 77.

At this very moment, this produces an output of 100.

Hot + Cold Inlets

hot triggers

Because these streams of numbers move at different speeds,

we know that each number feeding the hot inlet

will be added to the same number (in the cold inlet) many times over,

before a new number replaces the argument in the cold inlet.

Monitoring Output

We can prove this by using the Max console to monitor our stream of numbers.

The Max console allows us to view many successive snapshots,

that is, many individual moments...

in order to monitor what changes over time.

Monitoring Output

hot triggers

First, if you don't see it, open your Max console by choosing Window > Max Console.

Monitoring Output

hot triggers

In our patch, we can use a print object to monitor the values

flowing through our patch cables

each time a hot value triggers output.

Monitoring Output

hot triggers

Notice that the pack object also has hot and cold inlets.

We created 2 arguments for the pack function by typing f f

which resulted in 2 inlets.

Each f represents a floating-point value to be received in an inlet.

Monitoring Output

hot triggers

Now, take a look at your Max console.

We see that the values on the left are indeed changing faster than the values on the right.

Monitoring Output

hot triggers

Using the Max console with print statements, like this,

allows us to see things we cannot easily see if we are only looking at our patch.

Monitoring Output

hot triggers

For example, remember this simple algorithm we created?

Here, we can only see the first number, at the top, and the last number, at the bottom.

Monitoring Output

hot triggers

But, what can’t we see in this view?

Answer: We cannot see the inputs and outputs for the objects in the middle...

that is, the [* 5.] object, and the [- 8] object.

Monitoring Output

hot triggers

But what if we needed to monitor each of these steps?

Let’s create some example data to test this algorithm...

Monitoring Output

hot triggers

Here, we enter the number 13 in the topmost flonum object and press enter.

If we check using a calculator, we can be sure 57 is the expected result.

Monitoring Output

hot triggers

Now, let’s test a decimal input value. If we run 13.01 at the top...

We would expect a floating-point result...

And yet, we still get a 57!

Monitoring Output

hot triggers

If we use our calculator, we know to expect 57.05 instead.

What’s wrong?!

This is pure chaos...

What is this world we’re living in??

I feel sick...

Monitoring Output

hot triggers

Answer: We found a bug in our code.

So... Let’s fix it...

Are you ready to debug this bug?

Monitoring Output

bug problem

Our procedure is really simple, in fact...

Just set up 2 print statements

and label them 1st: and 2nd:

so we can easily see what is happening at each step...

Monitoring Output

bug problem

Now, look at your Max console...

Here, we can see the problem is clearly at the 2nd step:

At the 2nd step, our value changes from a floating-point to an integer.

But again, we expect these to be floating-point values.

Monitoring Output

bug problem

So, what is going at our 2nd stage?

Upon closer inspection of the [- 8] object...

Monitoring Output

hot triggers

We have localized our bug!

Monitoring Output

bug problem

Answer: We forgot a dot (.) after the argument.

Without this dot (.), the [- 8] function will only return integer values instead of floats.

So, we just need to change [- 8] ... to [- 8.].

Monitoring Output

bug problem

And when we update our patch,

and rerun the input value of 13.01, voilà!

We have the correct and expected result: an output of 57.05!

Monitoring Output

bug problem

Using multiple print statements in combination with our Max console

teaches us to be systematic and logical about our coding practice

in order to obtain the results we need...

and in order to remain in control of our programs.

Message Order — Part II

bug problem

We can further use print statements

to verify MaxMSP’s sophisticated messaging order structure:

Data flows right-to-left,

But also from top-to-bottom...

Message Order — Part II

bug problem

Notice how it works in columns first, followed by rows...

First, print statements 2nd, 3rd, and 4th are triggered in one column on the far right.

Then, statements 5th, 6th, and 7th are triggered in the middle.

Finally, statements 8th, 9th, and 10th are triggered on the left.

Message Order — Part II

bug problem

So, the messaging order is:

Starting on the right, move top-to-bottom, then one move to the left,

then top-to-bottom again, followed by another move to the left,

and finally, top-to-bottom one last time.

Message Order — Part II

bug problem

Keeping track of this messaging order may seem redundant, basic, or even boring,

and to be sure, you do not need to do this all the time!

But, knowing how to do it will save you many hours...

Message Order — Part II

bug

...searching for bugs!

Message Order — Part II

This messaging order is not true for signals.

Message Order — Part II

bug problem

Signal cables carry extremely fast streams of values.

And each MSP object can be imagined as its own “island” of C code.

Message Order — Part II

bug problem

Think of signal cables like a garden hose

carrying a continuous flow, or stream of values.

Message Order — Part II

bug problem

Unlike Max’s controle rate message cables,

which may only occasionally carry values,

MSP’s signal cables always have signal values moving quickly through them.

Message Order — Part II

bug problem

Like the garden hose, these cables are either on or off;

When they are off, nothing is happening,

but when they are on, sample values are moving in a quick flow.

Message Order — Part II

How are signal cables and MSP objects synchronized?

Message Order — Part II

bug problem

The short answer is:

You don’t have to think about the messaging order of signal cables.

Message Order — Part II

bug problem

Message order is related to the slower control rate:

the “Max” side of MaxMSP.

This means: only the values traveling through the gray control rate cables.

Message Order — Part II

bug problem

What holds the signal cables and MSP objects together in synchronization is different...

This is controlled by the Max scheduler and a number of parameters set in the Audio Status menu.

We will look at these items together another time.

More Debugging Tools

MaxMSP also includes more sophisticated tools to monitor message and signal values...

Event Probe and Signal Probe

probing

For example, find the Debug menu,

select Event Probe

and Signal Probe

so that a check mark appears to the left of each.

Event Probe and Signal Probe

event probe

Now, when you hover your cursor above a gray patch cable,

you can monitor rapdily-changing values traveling at message rate.

Event Probe and Signal Probe

event probe

Move your cursor above other patch cables to observe different parts of your process.

This way, you can be sure each step is doing what you think it is...

Event Probe and Signal Probe

event signal

You can do the same thing with signal cables!

Watchpoints

Even more sophisticated is the concept of Watchpoints.

Watchpoints allow you to monitor many cables at the same time...

They also allow you to create breakpoints in the messaging flow.

This allows you to stop time and monitor each step at any instant.

Watchpoints

watchpoints

To create a Watchpoint, first select a patch cable.

Then select Debug > Add Watchpoint — Print.

Watchpoints

watchpoints

Your watchoint has a blue number and each value prints to the Max Console.

Watchpoints

watchpoints

That's a fairly basic use of Watchpoints, though...

If, instead, we choose Debug > Add Watchpoint — Monitor,

Watchpoints

watchpoints

And choose Debug > Enable Debugging...

Watchpoints

watchpoints

we can create easily-identifiable Watchpoints

for many cables at the same time,

allowing us to monitor the flow of data from one object box to the next.

Watchpoints

watchpoints

Here, we have created Watchpoints on each of the 2 patch cables.

Now, select Debug > Watchpoints...

Watchpoints

watchpoints

The Watchpoints window pops up,

displaying the monitoring status of each of our numbered watchpoints, 1 and 2.

Watchpoints

watchpoints

Now, suppose we want to stop the flow of time and monitor

a single transaction of values from one object box to the next.

Choose one of the cables, and select break or break/watch from the list (red arrow above)...

Watchpoints

watchpoints

Now, we see both the Debug Window and the Watchpoints window.

And we can monitor the current value being passed along this patch cable.

We can even see the values current being held in the other cables as well.

Watchpoints

watchpoints

If everything looks good,

Press the Continue button,

which advances to the next value, and see if the problem is there...

Watchpoints

watchpoints

If something is not working in your patch,

use this method to see if the bug exists between your patch cables.

Watchpoints

bug!

This will help you isolate your bug!

Summary

By understanding how data flows in MaxMSP, we can more rapidly debug our work.

Today, we reviewed:

  • Message order in Max:
  • data moves right-to-left,
  • but also top-to-bottom.
  • Message order can also be controlled with the trigger object.
  • Message order applies to control rate, but not signal rate.

Summary

MaxMSP includes tools to help us debug our work:

  • print statements,
  • event probes,
  • signal probes, and
  • watchpoints

Summary

These tools help us answer some essential questions:

They help us identify...

  • which object boxes and patch cables
  • are carrying specific signal and message values
  • at any particular point in time.

Summary

In other words, they help us identify...

  • what variables
  • hold what values
  • at what point in time.

Summary

bug!

And this is the core of debugging.

Happy debugging!