# Stopping an event after fade completion?

**URL:** <https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162>\
**Category:** FMOD Engine\
**Tags:** csharp\
**Created:** [December 31, 2021, 9:51pm UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162 "2021-12-31T21:51:28Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![kgambill](https://avatars.discourse-cdn.com/v4/letter/k/258eb7/32.png) [@kgambill](https://qa.fmod.com/u/kgambill)\
**Post date:** [December 31, 2021, 9:51pm UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/1 "2021-12-31T21:51:28Z")

</div>

I’m currently working on trying to get our game to transition more smoothly between music, rather than abruptly stopping and then starting the next track. I’ve been able to get the current track fading out nicely using fade points, but the issue I’m having is that I’m not sure exactly when to actually call stop & delete the old event and start the next queued one. The event remains in the “playing” playback state even when the volume hits 0, which I would expect, but is there any way of knowing that the fade has completed?

Snippet from fading out the music via the fade points:

```auto
            ulong dspClock;
            ulong parentClock;
            result = eventSet.FMODEvent.getChannelGroup(out group);
            result = group.getDSPClock(out dspClock, out parentClock);

            FMOD.System system;
            FMOD.SPEAKERMODE mode;
            int numSpeakers;
            studioSystem.getLowLevelSystem(out system);
            system.getSoftwareFormat(out _SampleRate, out mode, out numSpeakers);

            const float fadeTime = 1.0f;
            ulong fadedTime = dspClock + Convert.ToUInt64(fadeTime * _SampleRate);

            group.addFadePoint(dspClock, fadeTime);
            group.addFadePoint(fadedTime, 0.0f);

```

---

<div class="post-metadata">

**Author:** ![jeff\_fmod](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/jeff_fmod/32/1766_2.png) [@jeff\_fmod](https://qa.fmod.com/u/jeff_fmod)\
**Post date:** [January 5, 2022, 4:36am UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/2 "2022-01-05T04:36:39Z")

</div>

After an event gets a volume of 0 it will go “virtual”, which should trigger a [`REAL_TO_VIRTUAL`](https://fmod.com/resources/documentation-api?version=2.02&page=studio-api-eventinstance.html#fmod_studio_event_callback_type) callback, and from there you should be able to stop and release the event.  
We have a [C# example](https://fmod.com/resources/documentation-unity?version=2.02&page=examples-programmer-sounds.html) that shows how to set a callback on an event if you are unsure how to go about doing that. You will need to set the `VOL0_BECOMES_VIRTUAL` flag when initializing the Studio system.  
EDIT: On a side note, you shouldn’t need to set fade outs if using FMOD Studio API. Instead you can add an [AHDSR](https://fmod.com/resources/documentation-studio?version=2.02&page=modulator-reference.html#ahdsr-modulator) to the event master track volume, that way when the event is stopped the release time will fade out when the track automatically.

---

<div class="post-metadata">

**Author:** ![kgambill](https://avatars.discourse-cdn.com/v4/letter/k/258eb7/32.png) [@kgambill](https://qa.fmod.com/u/kgambill)\
**Post date:** [January 13, 2022, 10:46pm UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/3 "2022-01-13T22:46:02Z")

</div>

Thanks for the response! I’ll pass the AHDSR information along to our audio guy to take a look there and we can hopefully go that route. Judging from your response and the documentation, the fadeout should happen automatically when calling stop on the event instance as long as STOP\_MODE.IMMEDIATE is not passed, correct?

As far as the REAL\_TO\_VIRTUAL, I don’t seem to be getting that callback. I’m passing the flag as follows during initialization:

```auto
const int maxChannels = 1000;
studioSystem.initialize( maxChannels, FMOD.Studio.INITFLAGS.SYNCHRONOUS_UPDATE, FMOD.INITFLAGS.VOL0_BECOMES_VIRTUAL, IntPtr.Zero );

```

And I’m registering for callbacks when I create an event instance as follows:

```auto
FMOD.Studio.EventInstance gameEvent;

result = _event.createInstance( out gameEvent );
Debug.Assert( result == FMOD.RESULT.OK );

result = gameEvent.setCallback( _EventCallback, EVENT_CALLBACK_TYPE.ALL );

```

I’m getting other EVENT\_CALLBACK\_TYPE just as started, stopped, etc. However, I’m not gettingthe REAL\_TO\_VIRTUAL one. Is there anything else that needs set besides the initialization flag and the callback on the event instance?

---

<div class="post-metadata">

**Author:** ![jeff\_fmod](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/jeff_fmod/32/1766_2.png) [@jeff\_fmod](https://qa.fmod.com/u/jeff_fmod)\
**Post date:** [January 19, 2022, 11:50pm UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/4 "2022-01-19T23:50:28Z")

</div>

> [@kgambill](#):
>
> the fadeout should happen automatically when calling stop on the event instance as long as STOP\_MODE.IMMEDIATE is not passed, correct?

Correct, as long as it has been initialized correctly, which it looks like it has.

> [@kgambill](#):
>
> Is there anything else that needs set besides the initialization flag and the callback on the event instance?

That should be triggering the callback, what version of FMOD are you using?

---

<div class="post-metadata">

**Author:** ![kgambill](https://avatars.discourse-cdn.com/v4/letter/k/258eb7/32.png) [@kgambill](https://qa.fmod.com/u/kgambill)\
**Post date:** [May 27, 2025, 10:08pm UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/5 "2025-05-27T22:08:43Z")

</div>

Apologies for reviving this old thread. We’ve been working with the AHDSR solution since this topic, but are running into this issue once again. Since this topic is the first thing to come back when searching Google or Bing for “fmod not getting REAL\_TO\_VIRTUAL callback” it seems like it’s the best place to keep the information in the hopes of helping someone else as well.

Unfortunately, we are still not getting the REAL\_TO\_VIRTUAL callback. I just recently updated to version 2.01.23 to see if it helps, but we still seem to be getting most other callbacks except for this one. Still using more or less the same code examples shown earlier in the thread for testing.

@jeff_fmod Can you (or someone else on the dev team) confirm you’re getting the REAL\_TO\_VIRTUAL callback when using the C# (non-Unity) API?

EDIT: For additional information, I added this check in my update function:

```auto
bool isVirtual = false;
				result = eventSet.FMODEvent.isVirtual( out isVirtual );
				if ( isVirtual )
				{
					eventSet.FMODEvent.release();
					_AudioEvents[index] = null;
				}

```

I added a break point and isVirtual is never true. I’ve tested this both using the FadePoint code in the original post, as well as just by calling the setVolume directly on the event and setting it to 0.0f. So it seems like the issue may not be with the callback itself, but the fact that the event is not being set virtual

---

<div class="post-metadata">

**Author:** ![jeff\_fmod](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/jeff_fmod/32/1766_2.png) [@jeff\_fmod](https://qa.fmod.com/u/jeff_fmod)\
**Post date:** [June 2, 2025, 4:38am UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/6 "2025-06-02T04:38:18Z")

</div>

Some possibilities I can think of that could prevent the event from being virtualized are:

- The event or a bus above an event is set to the “Highest” [Priority](https://fmod.com/docs/2.02/studio/event-macro-controls-reference.html#priority) setting, meaning it will never be virtualized.
- The event is being stopped by something else, instead of silenced. This would give you a `FMOD_STUDIO_EVENT_CALLBACK_SOUND_STOPPED` callback instead.

The best way to debug this would be to connect the [FMOD Profiler](https://fmod.com/docs/2.02/studio/profiling.html) to your game and send us a profiler capture to go through. For C#, you will need to initialize the `FMOD.Studio.System` with the [`LIVEUPDATE`](https://fmod.com/docs/2.02/api/studio-api-system.html#fmod_studio_init_liveupdate) init flag to connect the profiler.

Can you please collect a profiler capture while reproducing this issue in game, then [package your profiler session](https://fmod.com/docs/2.02/studio/profiling.html) including banks (ticking the “Banks” option when exporting), and upload it to your [FMOD Profile](https://fmod.com/profile#uploads)?

---

<div class="post-metadata">

**Author:** ![kgambill](https://avatars.discourse-cdn.com/v4/letter/k/258eb7/32.png) [@kgambill](https://qa.fmod.com/u/kgambill)\
**Post date:** [June 24, 2025, 5:09am UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/7 "2025-06-24T05:09:00Z")

</div>

Sorry for the delay - I was out of office and just saw your reply upon returning.

I’ve uploaded solari\_audio.fspackage to my profile. Everything was caputed using 2.01.23. Hopefully I captured everything correctly. I booted up the game, started the recording via th eprofiler, played an event, and then called the fade out code posted above.

Please let me know if there are any problems with the capture, or if anything doesn’t make sense about the way I’m trying to play and fade the audio.

---

<div class="post-metadata">

**Author:** ![jeff\_fmod](https://yyz2.discourse-cdn.com/flex036/user_avatar/qa.fmod.com/jeff_fmod/32/1766_2.png) [@jeff\_fmod](https://qa.fmod.com/u/jeff_fmod)\
**Post date:** [July 2, 2025, 2:38am UTC](https://qa.fmod.com/t/stopping-an-event-after-fade-completion/18162/8 "2025-07-02T02:38:17Z")

</div>

Thanks for uploading the profiler capture. Re-reading this years later I realize I made a mistake when I first answered you 3 years ago, and I didn’t catch it when responding last month, so apologies for the misinformation. FMOD actually uses two virtualization systems:

- The Core API virtualization system for optimizing away “voices”, which are the internal sound resources that events use
- The Studio API virtualization system for optimizing away event instances, including voices

While Studio API virtualization system optimizes away voices, the Core API virtualization system does not optimize away events. The situation is described in more detail here: [Interaction with Core API Virtual Voice System](https://fmod.com/docs/2.01/api/white-papers-virtual-voices.html#interaction-with-core-api-virtual-voice-system).  
By using fade points to fade out events, you are virtualizing voices in the Core API virtualization system, which unfortunately won’t trigger any Studio API virtualization changes, so you won’t get the Studio API `REAL_TO_VIRTUAL` callback as I originally stated (sorry again for the misinformation).

If you want to use fade points, the only way I can think of to stop the event after the fadepoint completes would be to poll the channel group’s audibility state with [`ChannelGroup.getAudibility`](https://fmod.com/docs/2.01/api/core-api-channelcontrol.html#channelcontrol_getaudibility), and stop the event if it hits 0. For example:

```cs
//Add a map of channel groups and EventInstances
Dictionary<FMOD.ChannelGroup, FMOD.Studio.EventInstance> stopMap = new Dictionary<FMOD.ChannelGroup, FMOD.Studio.EventInstance>();

...

ulong dspClock;
ulong parentClock;
result = eventSet.FMODEvent.getChannelGroup(out group);
result = group.getDSPClock(out dspClock, out parentClock);

FMOD.System system;
FMOD.SPEAKERMODE mode;
int numSpeakers;
studioSystem.getLowLevelSystem(out system);
system.getSoftwareFormat(out _SampleRate, out mode, out numSpeakers);

const float fadeTime = 1.0f;
ulong fadedTime = dspClock + Convert.ToUInt64(fadeTime * _SampleRate);

group.addFadePoint(dspClock, fadeTime);
group.addFadePoint(fadedTime, 0.0f);

//After adding the fade point, add it to your map
stopMap.add(group, eventSet.FMODEvent);

...

//In your main loop, poll the map and see if the channel is audible. If it is, stop the event.
foreach(KeyValuePair<FMOD.ChannelGroup, FMOD.Studio.EventInstance> entry in stopMap)
{
    entry.Key.getAudibility(out float aud);
    if(aud <= 0.0f)
    {
        entry.Value.stop(FMOD_STUDIO_STOP_IMMEDIATE);
    }
}

```
