Timbre, Pitch Bend, and Control Changes

This chapter explains how to make various changes to sounds using MIDI features. Note that not all synthesizers support these features.

Timbre

In MIDI, switching to a different instrument's sound is called a program change. Within Pytakt MML, you can use the $prog(value) command to implement this function. value is an integer from 1 to 128 called the program number. While you can specify it by the number, it is more intuitive to use the instrument name as shown below (however, if you are not using a GM-compliant synthesizer, the sound may not match the instrument name).

$prog(gm.Flute) C D E F $prog(gm.Piano1) G F E D

For a list of instrument names, please see here.

It is important to remember that program changes are specified per MIDI channel. Therefore, to play two or more voices simultaneously with different timbres, you need to assign a separate channel to each voice. For example, when writing a two-part piece and attempting to play each part with a different sound,

[{$prog(gm.Violin) C~ D~} {$prog(gm.Piano1) E F~ G}]

will still play with the same sound for all parts. The correct way is to specify channels for each voice part as shown below (please specify channel assignments before $prog).

[{ch=1 $prog(gm.Violin) C~ D~} {ch=2 $prog(gm.Piano1) E F~ G}]

For a more efficient description method when assigning channels to each part for multi-part music, see Chapter 8.

Pitch bend

Pitch bend is a feature that allows you to raise or lower the pitch of a note in smaller steps than semitones. In Pytakt MML, this control is possible with $bend(value). The value should be specified within the range -8192 to 8191, where 0 represents the center (the original pitch). The default pitch bend range in most synthesizers is +-2 semitones. This means that 4096 corresponds to one semitone, and one cent is approximately 41. In the example below, the pitch of the second D# note is raised by an amount equivalent to 1/2 of a semitone (i.e., a quarter tone).

C D D# $bend(2048) D# $bend(0) E

Since pitch bend is not a context attribute, writing “{$bend(2048) D#} E” will not automatically reset the pitch bend value. As shown above, you need to do it explicitly using $bend(0).

Similar to program changes, pitch bend is also specified per MIDI channel. Therefore, if you want to assign different pitch bend values to notes sounding simultaneously, you must use separate channels. For example, if you want to slightly lower the pitch of just one note within a chord, channel specification is required as below.

[C E(ch=2 $bend(-1024)) G]

Note that “E(ch=2 $bend(-1024))” in the above example is equivalent to “{ch=2 $bend(-1024) E}”.

Control changes, etc.

In addition to the program changes and pitch bends mentioned above, Pytakt provides various commands for modifying sounds defined by MIDI (see table below). These are all specified on a per-channel basis. For details on each controller, please refer to the Pytakt API Documents or general guides on MIDI.

Command Meaning
$cpr(value) Channel pressure (after-touch)
$kpr(MIDI-note-number, value) Key pressure (after-touch)
$bank(value) Bank select (Control change #0, #32)
$mod(value) Modulation depth (Control change #1, #33)
$breath(value) Breath control (Control change #2, #34)
$foot(value) Foot controller (Control change #4, #36)
$porta(value) Portamento time (Control change #5, #37)
$vol(value) Volume (Control change #7, #39)
$pan(value) Pan (Control change #10, #42)
$expr(value) Expression (Control change #11, #43)
$reverb(value) Reverb depth (Control change #91)
$ped([value]) Damper pedal (Control change #64). Default value: 127
$pedoff() Damper pedal off (Equivalent to $ped(0))
$ped2([value]) Soft pedal (Control change #67). Default value: 127
$ped2off() Soft pedal off (Equivalent to $ped2(0))
$ped3([value]) Sostenuto pedal (Control change #66). Default value: 127
$ped3off() Sostenuto pedal off (Equivalent to $ped3(0))
$portaon([value]) Portamento on (Control change #65). Default value: 127
$portaoff() Portamento off (Equivalent to $portaon(0))
$ctrl(controller-number, value) Arbitrary control change
$all_sound_off() All sound off (Control change #120)
$reset_all_ctrls() Reset all controllers (Control change #121)
$all_notes_off() All notes off (Control change #123)

The value argument above typically takes a value ranging from 0 to 127. When you want to specify both the MSB (most significant 7 bits) and LSB (least significant 7 bits), such as in the Bank Select control, write it as $bank((MSB,LSB)).

Time shifts are also effective for control changes. For example, you can use $ped()> or $ped()(dt=10) to press the pedal with a slight delay.



Last update: Feb 17 2026 12:09 JST     Copyright (C) 2026 Satoshi Nishimura Top Page