Skip to content

Fades


Fades are the most common use of the modulation system. Fade out a note when a legato transition begins. Fade in a new note for a smooth crossfade. Fade out a release noise over its natural decay. Nearly every production instrument uses fades somewhere, and IVLS provides a clean API for them built on top of modbits and VMCs.

Basic Fade-Out


fades.out() fades a voice's volume to zero:

fades.out(target_vo, 500, YES)

The arguments are:

  • target_vo -- the voice to fade out
  • time_ms -- the fade duration in milliseconds
  • kill_on_end -- YES to release the voice when the fade finishes, NO to leave it alive at zero volume

Most of the time you'll use YES -- there's no reason to keep a silent voice around. But if you're implementing a mute/unmute toggle, NO lets you fade to silence and then fade back in later.

Basic Fade-In


fades.in() fades a voice's volume from zero to full:

fades.in(target_vo, 300)

Fade-in always starts from silence and ramps to 100%. It doesn't take a kill_on_end argument -- there's no reason to kill a voice at full volume.

Curved Fades


By default, fades are linear -- the volume changes at a constant rate. For more musical fading, use the curved variants:

fades.curve_out() applies an exponential curve to the fade-out:

fades.curve_out(target_vo, 500, -50, YES)

fades.curve_in() applies an exponential curve to the fade-in:

fades.curve_in(target_vo, 300, 30)

The curve parameter ranges from -100 to 100:

  • Negative values produce a logarithmic curve -- the fade happens quickly at first, then slows down toward the end
  • Positive values produce an exponential curve -- the fade starts slowly, then accelerates
  • Zero is a linear fade (identical to fades.out() / fades.in())

Logarithmic fade-outs (negative curve) tend to sound more natural to the ear, because our perception of volume is logarithmic. A curve of -50 is a good starting point for natural-sounding fade-outs.

The Modulation Voice


Each fade function returns a modulation voice -- a special voice that drives the fade asynchronously:

declare mod_vo := fades.out(target_vo, 500, YES)

This modulation voice runs in its own flow. It contains a loop that updates a modbit on the target voice's VMC every few milliseconds, ramping the volume smoothly over the specified duration. You don't need to do anything with the returned voice in most cases -- it manages itself.

The modulation voice is what makes fades work asynchronously. Your code doesn't block waiting for the fade to finish. You call fades.out(), it starts the fade, and your code continues. The modulation voice runs in parallel, updating the modbit until the fade completes.

The Legato Crossfade Pattern


The most common use of fades is the legato crossfade: fading out the old note while simultaneously fading in the new one.

{ Fade out the source note }
fades.out(source_vo, 200, YES)

{ Fade in the destination note }
fades.in(dest_vo, 200)

Because each fade creates its own modbit on its own VMC, the two fades run independently. The source voice fades to silence and is released. The destination voice fades from silence to full. The listener hears a smooth transition.

This pattern only works correctly because ivls.new_formal_voice() was used to create the destination voice with its own VMC. If both voices shared a VMC, the fade-out would also affect the fade-in. Independent VMCs are essential for crossfades.

When to Use fades vs. fade_out


Kontakt provides a built-in fade_out() command that fades a sound event natively. It's cheaper than the IVLS fade system -- no modulation voice, no modbit, no VMC overhead. So when should you use which?

Use Kontakt's fade_out() when: - You're doing a simple, standalone fade-out with no other modulation - Performance is critical and you're fading many voices simultaneously - You don't need the fade to coordinate with other modbits

Use fades.out() when: - The voice has other modulation (modbits) that need to stay in sync - You need curved fading - You need the fade to participate in the VMC system (for crossfades, layered modulation) - You want the modbit-based approach for consistency with the rest of your modulation stack

In practice, production instruments tend to use fades.out() for musically important transitions (legato crossfades, expression changes) and Kontakt's native fade_out() for simple cleanup (releasing old voices quickly).

Custom Modulation with ivls.fire_modulation


Under the hood, fades.out() and fades.in() are built on ivls.fire_modulation() -- a lower-level function that creates a modulation voice with custom parameters:

declare mod_vo := ivls.fire_modulation(vo, time_ms, kill, curve, mod_flow)

This is how you'd build custom modulation effects -- pitch sweeps, pan automation, or any time-based parameter change. The modulation voice runs in the specified flow, where a custom modulation node processes it. The details of building custom modulation nodes are covered in the module documentation.


Fades are where the modulation system becomes tangible. VMCs provide the persistence, modbits provide the atomic values, and fades provide the musical behavior. Together, they let you build smooth transitions that work correctly no matter what happens to the voices underneath.