In this tutorial, we will look at several ways to deal with one of the more difficult issues in MIDI note generation and manipulation: dealing with pairs of note-on and note-off messages. We will use makenote
to generate properly formed pairs of a specific duration, use stripnote
to control incoming pairings, and use the sustain
object to handle situations where a sustain pedal
-like action is required.
When working with MIDI synthesizers and samplers, one of the most distracting situations is when a note-on message is sent to a device, but no note-off message is sent. This results in “stuck notes”, where the note is sounded but never turned off. This is never a good result, and may be seen as a “bug” by anyone that uses your patch.
In this tutorial, we will look at different ways of maintaining an appropriate pairing of note-on and note-off messages. By using some of the Max objects that can help manage this situation, we can prevent the types of mistakes that come from unpaired note messages.
One of the most popular uses of Max is to create generative music using a variety of Max objects. Obviously, this would include the creation of note messages that are played by connected samplers or synthesizers. If you are creating a lot of note messages, maintaining the proper pairing of note-on and note-off messages can require a lot of extra programming.
One of the objects included with Max is the makenote
object, which will create a / combination of your choosing, then will generate a matching note-off message after a you set. The leftmost patch shows the makenote
object in action – you can select a , and using the supplied slider
objects; the object will generate a note-on message, followed automatically by a note-off (actually, a note-on with velocity of ) after the selected duration. The two arguments for makenote
are the default and values, but these are changed when new values are received in the inlets. As with most Max objects, only the left
inlet of makenote is hot
; dragging the leftmost slider
will cause a ripple of MIDI events, wherease the middle and right slider
objects only set up the parameters.
Double-click on the noteout
object in the lower-right, and select a valid MIDI output destination. Then adjust the , , and values. You should hear notes being generated, then turned off, based on the selected . We've also sent the note events to a print
object; if you look in the Max
window, you can see how each note-on is followed by corresponding note-off messages, and that the object will correctly queue this messages even with multiple notes sounding at the same time. Using the makenote
object is the simplest way to generate note playback within Max without having to program the tracking and generation of note-off messages.
The second patch in our tutorial deals with eliminating the note-off messages received from a MIDI device and then controlling them explicitly from a patcher. In many cases, we may want to prevent a keyboard (or other MIDI input device) from turning off a note, preferring to generate the note-off programmatically. In the second patch, we route received MIDI notes from the notein
object through the stripnote
object, which will eliminate all note-off messages that are coming from our MIDI device. As a result, the remainder of the patch will only see note-on messages, and we will be responsible for turning the notes off when necessary.
One of the most useful tools for maintaining note-on tracking is the flush
object. It will create an internal table of note-on messages that have not yet received a corresponding note-off; it can then generate note-off messages for all sustained notes whenever a is received in its left inlet. In this case, we are stripping all of the note-off messages, so this table will contain all of the notes that we play on our MIDI device. When we want to turn these notes off, we can hit the button
object, which will send a message to the flush
object. This will generate note-off messages for all of the played notes, then clear the internal table of notes in preparation for the next set of events. Double-click the notein
object to select a valid MIDI input device; using your MIDI keyboard source, generate some notes - they will continue to sound until you click the button
them. We've also routed the notes to the Max
window (using the print
object) so we can see what's going on.
Using the stripnote
object to control the use of MIDI notes is useful when our playback engine needs to be sensitive to controllers other than the keyboard. Combining stripnote
allows us to be certain that MIDI note-off messages will be generated for any notes that were not specifically turned off.
The third patch features a similar function – sustained notes are held until specifically released. However, this patch will only perform this function when a toggle
is turned on; in all other instances, the functionality is “normal”, and note-off messages pass without change.
This functionality is very similar to a sustain pedal
on a piano: whenever the sustain pedal is “on”, the notes will ring even if we remove our fingers from the keys. When the pedal is released, the notes stop ringing, thereby giving us a secondary level of control. The sustain
object simulates this process: when it receives a non-zero value in its right
inlet, it holds
all note-off messages until it receives a message in that same inlet. In this way, you can simulate the action of a sustain pedal without having to programmatically maintain the note-on/note-off pairings. It is often useful to combine the use of the sustain object with MIDI controller (the sustain pedal controller), so that pedal control messages from a keyboard will react appropriately within your patch.
As with the previous example, set the notein
on the right to your MIDI input device (if necessary, disengage your input device from the middle notein
). Play some notes normally, then check the toggle
box - notes should no longer turn off. When you uncheck the toggle
, all your sounding notes should stop.
Most MIDI synthesizers and samplers demand note-on and note-off messages in pairs; failure to do so will result in “stuck” notes. There are several Max objects that help maintain the note-on/note-off pairings, and allow you to control the generation and playback of MIDI notes programmatically. The makenote
object is perfect for generating MIDI notes when you know the planned duration of the note. The stripnote
combination is better when you want to specifically control note-off generation, but want a “backup” in maintaining notes that have not been sent a note-off. Finally, the sustain
object allows you to simulate the use of a sustain pedal on a standard keyboard, saving you from having to program functionality for this specific MIDI control situation.
Generate a note-off message following each note-on
Filter out note-off messages, pass only note-on messages
Provide note-offs for held notes
Hold note-off messages, output them on command