(maxmsp) mapping midi to msp

Mapping incoming MIDI data to synthesis controls in MSP takes the form of either using conversion objects or creating mathematical scaling algorithms.

mtof and mtof~

Both mtof and mtof~ map incoming MIDI note number messages to floating-point frequency messages suitable for input to an oscillator. These objects are useful not just for pitch control from a MIDI keyboard, but also for adding pitch vibrato and pitch envelopes. Expressing vibrato in terms of MIDI notes allows mtof to scale the appropriate distance given our exponential pitch-to-frequency perception.

midiToFreq.maxpat shows the basic conversion process using the mtof object. midiToFreqVibrato.maxpat adds pitch vibrato to the MIDI note number. Since pitch vibrato is generated by an audio-rate object (cycle~), the input note number and the vibrato signal have to be added with the audio-rate +~ object. The output of +~ goes to mtof~ (audio-rate note number to frequency conversion), and then that output goes to the frequency input of saw~. Notice the number~ object (similar to a float number box). It is acting as a signal monitor that shows numerical values, rather than a meter~ that uses less-precise graphic lights.

dbtoa and dbtoa~

dbtoa (and its audio-rate companion) are technically not MIDI mapping objects. These two objects map linear amplitude changes expressed in dB (decibels) to logarithmic amplitude values that match our linear perception of loudness. Zero decibels (0.0 dB) equals an amplitude of 1.0. Reducing six decibels (-6 dB) cuts the amplitdue approximately in half to around 0.5. To get a decimal amplitude value of 0.0 you need to go down to -126.2 dB, but after about -90 dB it will be extremely difficult to hear the signal. (note: a 16-bit audio system should only need to go down to -96 dB to match the noise floor, and effectively be silent.)

mtofvibratodbtoa.maxpat demonstrates amp conversion as a modification of the previous midiToFreqVibrato patcher. Notice that a slider can be used for input to dbtoa, but that minimum and maximum ranges need to be changed to correspond to dB scale. The gain~ slider scales amplitude on a logarithmic scale, but it does not correspond to dB values.

Sustain Points in Function

You can specify certain points in the function object to be sustain points. A bang message will cause target and time pairs to be sent out up to the sustain point, then a “next” message will send out either the remaining pairs, or the pairs up to another sustain point (you can have more than one sustain point).

Cmd-click on a point to make it a sustain point. The point will have a white ring around the outside. (The help patcher recommends changing the color of the function points so that the ring will show up better than with the default colors.) Cmd-click again to remove the sustain property.

With sustain points your graphic envelope will not look like the typical representation of an ADSR envelope because the horizontal sustain line will not appear. Your envelope will perform like an ADSR, however, and that is the important thing to remember.

Incorporating MIDI note control of synthesis

BasicSynthEnvSusNoteOnOff.maxpat shows how to use map MIDI playback to control frequency and trigger an amplitude envelope (Attack – Decay – Sustain) with the noteon message, and trigger the Release with the noteoff message. Since we don’t know what specific velocity the noteon message will contain, but we do know that noteoff messages have a zero velocity, we can use “select 0” to look for noteoffs while passing the noteon velocity through unchanged.

Notice two important aspects of the function object in this patcher. I’m using the setdomain message to set overall duration of the function. The setdomain message works by setting the x axis and changing the function in proportion to keep its shape. The domain message just changes the x axis display. The other aspect to note is that you do not have to factor sustain times into your function, as sustain points handle that task. The overall x axis will be much shorter.

Velocity Sensitivity

The previous patcher plays back at the same amplitude regardless of key velocity. BasicSynthEnvSusKeyVelocity1.maxpat takes noteon velocity and divides it by 127 (floating-point divide) to get a decimal amplitude. The decimal amplitude is multiplied by the line~ output from the function object to scale the overall amplitude of the function. Scaling amplitude in this manner works, but it is a linear scaling when an exponential scaling is called for.

dbtoa can provide the exponential scaling that we need, but it will not work using the same math operations as used in BasicSynthEnvSusKeyVelocity1.maxpat. In BasicSynthEnvSusKeyVelocity2.maxpat I’ve used a simple math operation to convert incoming velocity to decibels. Subtracting 127 from the noteon velocity neatly converts incoming velocities to dB. A maximum velocity of 127 will produce a dB output of 0. The problem with this math is that a key velocity of 60 won’t play anything. (Check out the decimal amp value after the dbtoa conversion when the input is -67 dB.) BasicSynthEnvSusKeyVelocity3.maxpat demonstrates a better velocity mapping function. Using a scale object that scales incoming values of 0 – 127 onto output values between – 60. and 0. provides a better option. You can still get notes with some amplitude at low key velocities. Notice that the dB amp is still being converted to decimal amp values for multiplication (scaling) of the line~ function.


Leave a Reply