Skip to content

VMC


Here's a problem that sounds simple but isn't: you want to fade out a note over 500 milliseconds. At the 200ms mark, the user releases the key. If nothing else is done, the voice gets released, its children get released, and the fade data vanishes — even though the Kontakt sample is still ringing out. The fade needs somewhere to live that won't disappear the moment the key comes up.

You could keep the voice alive manually — running the fade in a cb NoteOff callback, or copying the voice to pin it. But you still need a place to store the modulation data, and that place needs to work with many simultaneous fades across many voices without global variable collisions.

This is the problem the VMC (Voice Modulation Container) solves. It provides the mechanism for persistent modulation — a reference-counted container that stays alive as long as you keep voices pointing to it.

What a VMC Is


A VMC is a lightweight container that holds modulation data -- fades, volume multipliers, tuning offsets, and other real-time modifications. Every voice has a vmc field that links to its VMC:

declare my_vmc := Voice[self].vmc

The key insight is that a VMC uses reference counting. It stays alive as long as any voice still points to it. The VMC doesn't magically outlive the voice — the developer is responsible for keeping voices alive when modulation needs to persist beyond the natural release point.

Reference Counting


When a voice is created, it adds a reference to its VMC. When the voice is deleted, it removes a reference. When the reference count reaches zero and the VMC has no children, the VMC is cleaned up.

For a fade to continue running after a key is released, the developer must keep a voice reference alive — typically by creating a modulation voice via Voice.copy() or by running the fade logic inside a cb NoteOff callback on the releasing voice. As long as that voice exists and points to the VMC, the ref count stays above zero, the VMC persists, and the fade's modbit values continue to reach the sound.

The VMC provides the mechanism. The developer provides the lifecycle management.

The VMC Tree


VMCs form a tree structure that mirrors the voice tree. When a voice has children, its VMC can have child VMCs. The tree uses four pointers -- parent, child, left, and right -- just like the voice tree.

This tree structure matters because modulation applied to a parent VMC affects all voices linked to any VMC in its subtree. If you apply a volume multiplier to a root VMC, every descendant voice hears the change.

ivls.new_voice vs. ivls.new_formal_voice


This is where the distinction from the previous unit becomes concrete:

ivls.new_voice(self) creates a copy that shares the parent's VMC. Both voices point to the same VMC, so modulation applied to one affects the other.

ivls.new_formal_voice(self) creates a copy with its own child VMC. The new VMC is a child of the parent's VMC in the tree, but modulation applied to it is independent. Modulation on the parent VMC still cascades down, but the child can have its own fades and adjustments without affecting siblings.

Use ivls.new_formal_voice() when voices need independent modulation -- which is most of the time when you're spawning layer voices or building crossfades. This is why Polycore's Spawn.Layers uses ivls.new_formal_voice() for each layer.

How This Connects to Modbits


The actual modulation values are stored in objects called modbits, which live on a VMC. When you create a modbit and attach it to a voice, it's actually being attached to that voice's VMC. The modbit persists as long as the VMC persists.

We'll cover modbits in detail on the next page.

How This Connects to Sound Events


When a voice reaches the PlayEvent and produces an audible sound (a Kontakt event), the VMC registers that sound event. Modbits on the VMC then know which sound events to modify when their values change. Even if the original voice is gone, the sound event persists (Kontakt keeps it alive), and the VMC's modbits can still adjust its volume, pan, and tuning.

The EMCache (Event Modulation Cache) stores the aggregated modulation values for each sound event -- the sum of all additive modbits and the product of all multiplicative modbits. This cache is what actually gets applied to Kontakt's engine parameters. The details of the EMCache are part of the module documentation rather than this guide.


The VMC is the backbone of IVLS modulation. It decouples modulation data from voice lifetime, enabling fades, crossfades, and real-time parameter adjustments that work correctly even as voices are created and destroyed around them. The next page covers modbits -- the atomic units of modulation that live on VMCs.