zl.group stuck on previous values

Carlos Butler's icon

Hi there, I'm trying to code a MIDI transformation tool for chords and I've run into an issue that I think it's related to the zl.group object not being able to update properly after changes in the MIDI notes.

The tool is supposed to perform one type of transposition on major chords and another type of transposition on minor chords. It works for the most part, but the problem is when I change the chord from major to minor or from minor to major, the tool performs one transposition as if the chord hadn't changed, and after that one wrong transformation, it works as expected, as if it needed to do an extra transformation based on the previous values.

I've tried sending clear and reset messages to zl.group to no avail, so I don't know what else to do. Any assistance would be appreciated, thanks.

Source Audio's icon

zlclear is the right messsge to reset

zl objects

P.S.

check zl.group output and also

output of if object.

Timing of midi input and chord type detector is

definitely wrong

Carlos Butler's icon

I've tried zlclear already at the beginning and at the end of the chain and it didn't fix it.

Source Audio's icon

Timing … as added to my first reply

Carlos Butler's icon

I've checked all the outputs and they're fine, yet it keeps doing that extra pass with previous values. Can you be a bit more specific?

Andy Maskell's icon

I would suggest that you use the Debugger with a breakpoint to check which cords your data is running down and in which order. Max generally processes things from right to left and bottom to top. My guess is that because the input for your [gate] is further right than the output of your [live.miditool.in] (it effectively crosses over the [gate] selector message) that the order of events is following the longer left hand cord down to the [gate] before the process runs through the right hand path to select which side of the [gate] to use. It's a problem that I have come across many times with [gate] where the normal process rules appear to be at odds with reality. A simple way to check this would be to simply move the position of the [gate] to the left such that the right input is well to the left of the long cord coming down from the top of the patch. The other method would be to place a [trigger l l] under the [live.miditool.in] with the left output going down to the [gate] input and the right hand output going to the [dict.unpack]. That will force the right hand gate selector path to be processed before the notes are sent down to the [gate].

As a demonstration, try out these three simple examples:

Max Patch
Copy patch and select New From Clipboard in Max.

They essentially all do the same thing but the results are different. The lefthand exmple is lined up like your patch and clicking on the 1 or 2 at top constantly sends the message through the wrong side of the gate first but clicking it again appears to get it right. The middle example is exactly the same code but with the [gate] positioned to the left. Now the message always goes to the correct output every time. The third example, which is lined up exactly the same as the first but now has a [trigger l l] to force the order in which the messages are processed, the messages again always go in the correct direction.

Incidentally, there are a lot of people who have suggested that the [gate] object be redesigned such that the data goes into the left input and the selector message into the right. If this was done, it would eliminate this unexpected behaviour. However, the clever people have justified the design because of how the underlying code works in the object. I know of some people that have created their own subpatcher snippets that deliberately swap the inputs over but it means that you have to create different snippets for every size of [gate] that you need to use.

Roman Thilenius's icon

as it is, this patch is checking if a list of 3 numbers is -4 or not.

Source Audio's icon

Output from that dict & if is getting out later than direct midi input to gate.

So you are switching gate too late.

I don't know what direct output of that miditool looks like

but I doubt that dict.unpack to zl.group 3 can keep

both streams synchonised ?

Carlos Butler's icon

Thanks for the help guys, I just moved the top objects to the right and that fixed it.

Andy Maskell's icon

It's daft that such a simple thing can make such a big difference! I notice it a lot as I'm very OTT about how neat and tidy my patches look but [gate] is the one object that repeatedly causes me problems as a result. [trigger] is my friend!

Carlos Butler's icon

Yes, I find it a bit irritating that objects perfectly left aligned with each other should still be evaluated from the bottom up, it's very counterintuitive. However, I followed your advice and learned how to debug with break watchpoints and also learned about the [trigger] object, so I've gained a lot of insight with this patcher, thanks!

Andy Maskell's icon

It's a common feature of object orientated languages. The logic is that those objects that refer to another object have to have that second object declared earlier in the code.

I can recall my first exposure to Pascal back in the early 1980's where it was necessary to build a program in a specific way. The main routine of the code had to come last such that all subroutines and parameters that it referenced had always been declared beforehand. Likewise, any subroutine referenced by another subroutine had to be declared before it. It was also true of variables and other parameters that always had to be declared before they were used. This meant that global parameters available to the whole program had to be declared right at the beginning, even if their appearance in the code might only occur pages down the printout. It often looked like the program had been written backwards! Debugging of large applications could be a nightmare, constantly having to look backwards towards the top of the printout rather than working forwards.