Patch C10.monophonic.synth.pd (figure 3.16) also implements a monophonic, note-oriented synthesizer, but in this case oriented toward MIDI controllability. Here the tasks of envelope generation and sequencing pitches is handled using control streams instead of audio signals. Several new control objects are needed for this example.
: MIDI note input. Three outlets present the pitch,
velocity, and channel of incoming MIDI note-on and note-off events
(with note-off events appearing as velocity-zero note-on events.)
The outlets appear in Pd's customary right-to-left
order.
: filter out note-off messages. This passes (pitch,
velocity) pairs through whenever the velocity is nonzero, dropping
the others. Unlike
,
does not input or output
actual MIDI messages.
,
: copy a message to outlets in right to left order, with
type conversion. The creation arguments (``b" and ``f" in this
example) specify two outlets, one giving bang
messages, the other float (i.e., numbers). One outlet
is created for each creation argument. Other types are ``l" for
list, ``s" for symbol, and ``a" to output
anything (i.e., a copy of the input message, whatever it is). The
incoming message is converted (as faithfully as possible) into
whatever format is specified by the creation argument. Although the
outputs appear in Pd's standard right-to-left order, no time
elapses between each of the outputs; they are deterministically
ordered and yet instantaneous.
The patch's control objects feed frequencies to
the
object whenever a note-on
message is received. Controlling the amplitude (via the
object) is more difficult.
When a note-on message is received, the ``sel 0" object outputs the
velocity at right (because the input failed to match 0); this is
divided by the maximum MIDI velocity of 127 and packed into a
message for
with a time of 100
msec.
However, when a note-off is received, it is only appropriate to stop the sound if the note-off pitch actually matches the pitch the instrument is playing. For example, suppose the messages received are ``60 127", ``72 127", ``60 0", and ``72 0". When the note-on at pitch 72 arrives the pitch should change to 72, and then the ``60 0" message should be ignored, with the note playing until the ``72 0" message.
To accomplish this, first we store the velocity
in the upper
object. Second, when the pitch
arrives, it too is stored (the lower
object) and then the velocity
is tested against zero (the bang outlet of ``t b f"
recalls the velocity which is sent to ``sel 0"). If this is zero,
the second step is to recall the pitch and test it (the
object) against the most
recently received note-on pitch. Only if these are equal (so that
bang appears at the left-hand-side outlet of
select) does the message 0 1000 go to the
line~ object.