Stopping an event after fade completion?

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:

            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 an event gets a volume of 0 it will go “virtual”, which should trigger a REAL_TO_VIRTUAL callback, and from there you should be able to stop and release the event.
We have a C# example 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 to the event master track volume, that way when the event is stopped the release time will fade out when the track automatically.

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:

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:

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?

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

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

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:

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

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 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 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 init flag to connect the profiler.

Can you please collect a profiler capture while reproducing this issue in game, then package your profiler session including banks (ticking the “Banks” option when exporting), and upload it to your FMOD Profile?