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 and flush 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.
To open the tutorial patch, click on the green Open Tutorial button in the upper right-hand corner of the documentation window.
Controlling note-off with makenote
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 (Also double-click the rightmost notein object and choose an unconnected input. The default of All Devices by Channel may cause the two patches to interfere.) Now use your MIDI keyboard to generate some notes - they will continue to sound until you click the button to flush 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 with flush allows us to be certain that MIDI note-off messages will be generated for any notes that were not specifically turned off.
Controlling note-off with sustain
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/flush 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.
|makenote||Generate a note-on/note-off pair|
|stripnote||Filter out note-off messages|
|flush||Output MIDI note-offs for held notes|
|sustain||Hold note-off messages for release|