Recipe: Making things fit into key with zl objects, vexpr, and lists in Max

About a month ago, I was asked if I could make a really simplified music making patch, where it is impossible for things to not be in key. I’ll probably write further on the event itself at some stage, but for now I wanted to share a small recipe for keeping everything all in key.

What I mean by this is: the user picks a key signature, and all the notes available will be within that key. If you wanted a C major scale, you avoid all the flats/sharps (black notes) on a keyboard. And what if you want a harmony for a whole piece, say a chord pattern of C, G, F, G, C without any “bum notes”?

A quick answer could be to just give the root notes off these chords a number and add to them (CEG is 024, GBD is 468) etc), but then there’s the issue of what to do if these intervals have sharps and flats- in this example, we want to stay in the key of C major, so no sharps and flats.

So what we want is a list of notes we want, and them to have some kind of way to be called up. The easiest way to do this is to simply make a list in Max of the note numbers/gaps we want starting at zero.

Going back to C major, what notes do we need? C, D, E, F, G, A, and B- all natural. Looking at a keyboard helps here, and the Kslider in Max might help as a visual reference point:

Kslider with annotated numbers for each note. C is 1, C# is 2 and so on.

This gives us a clear picture on the notes we want for the key, as we can ignore the black notes(2, 4, 7, 9, and 11). Something to bear in mind though is that we actually want to start at 0, as Max starts on 0’s for most things, and it saves headaches when working with note numbers. With everything taken down one, and the black notes removed, you can write this into a message box:

A Max message with "0 2 4 5 7 9 11" inside.This is your note list. You can choose any intervals of course, that’s down to you. That said for ease of use, I’d urge you to start at 0, as I have a way to shift this list to your desired root note using a vexpr object later on.

That’s great, so what was the point in doing this? Well, now you can pick from this pruned list and every melody or note chosen will be in key. But to make this useful we are going to take this a step further and make it so that you can pick any one of these notes and form chords off it, and have melodies that will fit that chord.

The first thing to bear in mind is that you will likely want more than these 7 notes, in fact… what happens if you want a triad chord starting on note 11? There will just be 11, as that’s where this list ends. This probably isn’t ideal unless you’re looking at using clever inversion chords. This is more like it, even if it’s a bit overkill:

An extended version of the message, with the intervals starting again for the next octave (12 being the starting number of the next batch).

This means that your triad chord on 11 would now have 14, and 17 for company. Incidentally that would be a B diminished.

Now from here you could just grab the 7th, 9th and 11th list items to get that chord, but for me, I found it too prone to human error and to be honest, extra work. Instead I opted to use a zl.rot object to just make the list do what I wanted:

Zl.rot in action. The list is fed into it, along with the number's place in the list (again starting at 0).


So what’s happening here? The number in the box at the top right is how many positions you want the list shifted. The “* -1” object is there to make the list shift items to the left by making the number negative.

Another quirk with the zl objects is they sometimes have a right inlet for a setting, but the output doesn’t happen until the left inlet receives a bang. To get round this I’ve used a t object (shorthand for trigger, which also works) to send a bang to the left inlet. Max reads right to left, so when the t object gets the -6, it first sends out from the i outlet into the right of the zl.rot, and then a bang from the b outlet to get it to output.

This should let you change the number in the top box and the list rotate automatically now we have some progress!

For real practical usage, that top number is your choice in chord. I had the kids click into an itable (that’s another post for another day!), and then sent that to be that top number…  voilà, chord choice without any scary music theory!

An optional step is to further chop this down to size using a zl.sort, with a max size setting to make the list only have the first 8 numbers:

The zlmaxsize is what’s chucking away the numbers after the 8th entry. I personally found this useful for things like random notes without crazy jumping intervals.

Loadbang is an amazing thing, and it basically just sends a bang when the patch loads, to force parameters into it. Speaking of which, you will need one above the first list, as otherwise it won’t reach zl.rot. They are great… until you forget to put one in and have to hunt for the missing link!

We’re pretty much there, but there’s one last thing you will need, and that’s a way to choose a key- C will get boring, even with the nice chord setup we now have.

The first time I tried this with the theremin, I had a huge collection of lists for each possible key, each identical, but one starting on 0, one starting on 1, another on 2, and so on. That was a lot of work, and totally unnecessary with the next object.

The sorted list is fed into a vexpr object like this "Vexpr $i1 + $i2 + 72 @scalarmode 1"Okay, there’s a few things happening here. Vexpr is a nice quick way to do expressions, kind of like the =sum feature in Excel Spreadsheets. What is nice is that it handles lists, so we can give it a number to add all the note numbers by.

So let’s break this down:

$i1 and $i2 are both a way to get input into the box, the i stands for integer, and the number on the end just is a way of saying which one is which. So from this it’s “$i1 +$i2”, so “input 1 + input 2”.

the + 72 works on the same idea, except it’s just a flat number that vexpr keeps. From here it’s “$i1 + $i2 + 72”, which just takes the list and adds 72 to each number. I picked that number, as I wanted to shove everything up a few octaves for midi use.

Anything or nothing is fine as you need, just bear in mind that you’ll want to just change the octave you’re using, but NOT the note at this point- otherwise everything will be wrong with what you think is A being C or something like that- this is what input 2 is for. As long as you stick to multiples of 12 you should be fine though.

Last but not least, “@scalarmode 1” just forces vexpr to be handling the input as a list. In the screenshot above it would just show 93 on its own otherwise.

Note the trusty “t b i”  there to force an output.

The finished patch! It's got zl.nth as a way to get eh 1st, 3rd and 5th notes from the list.

And here we are! Zl.nth is a way to get certain numbers off the list (starting on 1), other than that, just plumb in your key signature number, and chord choice and you’re good to go!

I hope this can be of use to someone. 🙂 Click page 2 for a copy/paste version of this recipe.

Leave a Reply