Skip to content

Pedals


Most keyboard instruments need to respond to the sustain pedal. When a player holds the sustain pedal and releases a key, the note should continue ringing until the pedal is lifted. IVLS provides a standard library node called Stl.Pedals that handles this for you.

What Stl.Pedals Does


Stl.Pedals manages both sustain (CC 64) and sostenuto (CC 67) pedal behavior across all MIDI channels. Its job is straightforward:

  • When a note is played, it tracks that the key is being held
  • On NoteOff, it checks whether the sustain pedal is currently down
  • If the pedal is down, the node takes ownership of the voice and keeps it alive
  • When the pedal is lifted, it releases all voices it was holding

From the player's perspective, this means notes ring out naturally as long as the pedal is held -- exactly the behavior you'd expect from a piano or any sustain-capable instrument.

Adding It to Your Flow


To add pedal support, register Stl.Pedals in your flow before your PlayEvent:

node MyPlaybackLogic:
    cb Flows:
        define FLOWS += my_flow

        ivls.register_node(my_flow, Stl.Pedals)
        ivls.register_node(my_flow, MyPlayEvent)
end node

That's it. No configuration needed for basic sustain pedal behavior. The node listens for CC 64 and CC 67 automatically, and it handles all the voice lifecycle management internally.

Where It Goes in the Flow


Stl.Pedals should come after any routing or Divert nodes (so the voice has already been sent to the correct flow), but before PlayEvent (so the pedal node can intercept the NoteOff before the sound is stopped).

In a flow with routing:

ivls.register_node(my_sustain_flow, MyModifier)
ivls.register_node(my_sustain_flow, Stl.Pedals)
ivls.register_node(my_sustain_flow, MyPlayEvent)

If you place Stl.Pedals after PlayEvent, it won't be able to intercept the NoteOff in time to keep the note alive.

How It Works (Briefly)


On NoteOn, the pedal node passes the voice through normally (via ivls.pass()). If the sustain pedal happens to be down, it also reparents the voice into a runtime -- a special container that keeps the voice alive independently of the original key press.

On NoteOff, the pedal node checks if it's currently holding the voice. If it is, it simply marks the key as released but does not release the voice. The voice continues playing.

When the sustain pedal is lifted (CC 64 goes below the threshold), the node releases all voices it was holding at once. If a key was pressed again while the pedal was down, that voice gets restored to its normal parent instead of being released.

The internal mechanics of runtimes and voice reparenting are covered in Unit 5 - Voice Mechanics. For now, you don't need to understand them -- Stl.Pedals handles everything behind the scenes.

Sostenuto


Sostenuto (CC 67) works similarly to sustain, but with one key difference: it only holds notes that are already being played at the moment the pedal is pressed. Notes played after the sostenuto pedal goes down are not affected.

Stl.Pedals handles both pedal types in a single node. If both pedals are active simultaneously, the node correctly manages the interaction between them -- sostenuto takes priority over sustain for notes it's holding.


With pedal support in place, your instrument now has a complete basic playback system: keymaps route notes into flows, voices travel through modifier nodes, pedals manage note lifetimes, and PlayEvent triggers the audio. From here, the guide moves on to building the rest of your instrument's features.