Max Tutorial #8: A Keyboard-Controlled Synth

In this tutorial, we will apply what we’ve covered so far to build a piano keyboard-controlled synthesizer. We’ll start off with a standard synthesis chain as in the previous tutorials, this time using a sawtooth oscillator as our sound source. The frequency of the oscillator will be determined by an object called [kslider], short for “keyboard slider,” which generates a piano keyboard-like interface inside of the patch. Clicking on notes on the keyboard (with the patch locked) causes the corresponding MIDI note number to be passed out the left outlet. We can use a [t b i] object to send a bang to the [function] object, triggering the envelope, and the MIDI note number to [saw~] via the [mtof] conversion object.

If you have a MIDI controller available, you can use that instead of clicking on the on-screen keyboard. To add this functionality, we’ll need two new objects: [notein] and [gate]. The [notein] object detects incoming MIDI notes and passes them along. The [gate] object is used to limit what information passes from the right inlet to the outlet. The left inlet opens and closes the gate: a zero closes it and a non-zero value opens it. In this case, the [gate] ensures that only the start of notes are passed through, and not the ends of notes, which are automatically determined by the envelope we draw in the [function] object.

To explain exactly what’s happening with these two objects requires a brief technical tangent—feel free to skip ahead to the next paragraph if you prefer (especially if you don’t have a MIDI controller). Every MIDI note consists of two parts: a “note on” and a “note off.” The “on” and “off” messages for a single note will have the same MIDI note number; they are only distinguished by what is called their “velocity” value, which corresponds to the volume of the note. Any non-zero value is interpreted as the volume of a “note on,” and a value of zero is interpreted as a “note off.” By passing the velocity values from the middle outlet of [notein] to the left (control) inlet of the [gate] object, only the start of notes, corresponding to non-zero velocity values, will pass through, and velocity values of zero, “note offs,” will close the [gate]. If the “note offs” were passed through directly, we would hear a double attack for each note, since the software would have no way of determining which was a “note on” and which was a “note off.”

Once we have a basic synthesizer setup, we can expand it to include the [lores~] filter object. Instead of using an LFO to modulate the filter as in the previous tutorial, here we’ll use a second [function] object to generate an envelope to modulate the filter. As in the previous modulation-based tutorials, we use the [scale~] object to set a range of values—in this case, a range of frequencies for the filter cutoff from 500 to 1500 Hz. Then we connect the outlet of [scale~] to the cutoff frequency input of [lores~], connect the “b” outlet of the [t b i] object to trigger the second [function] object, and finally, lock the patch and draw an envelope shape for the filter frequency. When we play notes, we can hear the effect of the modulated filter as a change in timbre. Changing the direction and steepness of the envelope changes the way the filter affects the timbre.

Our final step will allow us to customize the range over which the filter sweeps. Choosing a fixed range of frequencies might make sense intuitively, but it results in an inconsistent sound because it means that the filter is indifferent to the specific pitches we play. This means that pitches in different registers will have a dramatically different timbre. To resolve this, we can set the frequency range as a multiple of the frequency played. We do this by using two [* ] multiplication objects (note that we are using the “regular” multiplication object and not the audio rate version [*~]). We pass the frequency from [mtof] into the left inlet of each, and use a floating-point number box on the right to determine the multiples. By trying different multipliers—along with different envelope shapes—it’s possible to get a wide range of sounds from this simple setup.