How do we make a normalized Cross fade with snapshots?

TransitionToSnapshots will always make a crossfade that has a total volume % <100 in the middle of the transition.
Meaning, with crossfade between snapshot INGAME-0 and snapshot INGAME-1 configured as shown below
then
if transition is 1 second
at 0.5 seconds the total volume will be < 0db instead of being normalized at 0db
so
the result is the sound tracks are muted for a fraction of a second.

How can this be fixed whilst still using convenient gizmos such as snapshot and the sound mixer?

Hi laurentlavigne,

I believe what you want is an equal-power cross fade. Simply crossfading two audio signals in a linear manner will result in a perceived volume dip in the middle as you describe.

An equal-power cross fade can be achieved by using the squares of the two crossfade gains. You can do this with Unity’s AudioMixers by clicking on your INGAME-0/INGAME-1 sliders and in the inspector right-click on the volume parameter under Attenuation and select the ā€œSquared Snapshot Transitionā€ setting.

3167601--241211--Screen Shot 2017-08-01 at 14.18.49.png

Hope that helps!
Andy

That is very well hidden.
Thanks for the tip but the volume still dips.
I call the transition with this bit of code, so maybe the TransitionToSapshots command does something funky to the values?:

    [Task]
    void EvaluateMusic()
    {
        int threat = EvaluateThreat ();
        var choice = new MusicToThreat {threat = 0 };
        foreach (var m in snapshots)
        {
            if (threat > choice.threat && threat > m.threat)
                 choice = m;
        }
        AudioMixerSnapshot[] thisSnap = new AudioMixerSnapshot [snapshots.Length];
        float[] thisWeights = new float[snapshots.Length];
        for (int i=0;i<snapshots.Length;i++)
        {
            thisSnap [i] = snapshots[i].snapshot;
            thisWeights[i] = snapshots[i] == choice ? 1 : 0;
        }
        mixer.TransitionToSnapshots (thisSnap, thisWeights, 1.0f);
        Task.current.Succeed();
    }

Indeed it is well hidden isn’t it.

Hmm, I just had a look at the transition curves in this video (4m 58s):

The SquareRoot transition curve looks more like the curve I was aiming for (and what Pro Tools does for equal power crossfades). Did you try the SquareRoot transition curve?

I’d be surprised if TransitionToSnapshots doesn’t respect the transition curve (and would report it as a bug if that is the case).

The silence is less pronounced but still exists.
I thought it could be due to half phase offset so I verified the tracks in audition by overlaying them and they don’t cancel each other out (or I’m doing it wrong).

I look at the slider in the audio mixer and TransitionToSnapshots does apply the curve but in a weird way: instead of mapping the curve to the volume, it maps the curve to the transition. This means that no curve can ever provide an approximation of equal power volume cross fade.

It seems to be a known problem…

Damn. Thanks for the info.

Perhaps we should make a feature request for an equal power transition curve. Doing this manually loses all the convenience of AudioMixerSnapshots.

1 Like

Solution: bypass the new audio mixer and do it by hand, as usual
(and enjoy NaN volumes because it’s 3am and I can’t be bothered fixing the arithmetic :p)
{EDIT: 3am ain’t no 'scuse, boy!}
<EDIT: is fixed>

    IEnumerator CrossFadeTo(AudioSource destination, float duration)
    {
        var timer = Time.time + duration;
        while (Time.time < timer)
        {
            var t = (timer - Time.time)/duration ;
            foreach(var s in sources)
            {
                if (s == destination)
                    s.volume = Mathf.Sqrt (1-t);
                else
                    s.volume *= Mathf.Sqrt (t);
            }
            yield return null;
        }
        foreach(var s in sources)
        {
            if (s == destination)
                s.source.volume = 1;
            else
                s.source.volume = 0;
        }
    }
2 Likes

The request was made in 2015, ignored by the staff, maybe the new dev that took over will be more receptive.

Still no proper crossfade?

you tried the beta?

Any proper crossfade yet?

Bump?

Saw this article and it seems like a hacky workaround, but still well-thought out.:

(check out point 10)

Bump

It’s a huge limitation of snapshots that you can’t transition between them without an audible volume dip.

3 Likes

BTW it is not a bug; it’s a feature :smile:

I just discovered the audio mixer yesterday and it works like a charm but this ā€˜dip’ problem is really annoying.

The interpolation between snaps goes perfectly linearly.
Just try to setup a manual slider sending from 0 to 1 on snapshotA and 1 to 0 on snapshotB; you’ll notice the snapshots’ cursors match perfectly the manual slider.

The problem comes with U3D devs wanting to do perfect audio things and use log volume sliders ( like any you can find on a real life mixing table ).
The pain comes when we game devs just don’t care log !
we want ( and need ) linear cursor scales !

I guess this is a matter of 15 minutes for devs to change from log to lin cursors scales and say 2h to make it choosable globally ( as we definitely don’t need log at all ) in project config.

Unfortunately this ā€˜bad joke’ lasts now for ages and i doubt it will be one day changed/solved.
I think the dirty workaround ( we’re used with this in unity :stuck_out_tongue: ) would be to send to the snapshots interpolator the result of an exp curve between 0 and 1…

It would have been so simple that user don’t have to care with this… but i seems U3D dev like when their user have brainstorms :smile:

Happy unitying ! :slight_smile:

EDIT:
For those curious of how to do this ( and for me when i forget the ā€˜how-to’ :smile: )
here’s the way to setup main volume and mixing values for snapshots:
add this func to your c#:

   float linearize_shitty_U3D_audio(float v) // v:[0:1] ---> out:[0:-80] in log10
   {
   float tmp = Mathf.Log10(v)*20f;
 
      return((tmp <-80f)?-80f:tmp); // -80 = min value on audio scale
   }

now you set, say… your AudioMixer master_volume ( that you have previously made visible ):
M.SetFloat(ā€œVolume_Generalā€,linearize_shitty_U3D_audio(zero_to_one));

Proper values are in:
100% is 0dB
50% is -6dB
25% is -12dB
etc…
up to -80dB when the log reaches -Infinity…

Hope you like the cheat :wink:

Happy unitying !

In short, professional and clean version:

private static float ToLogVolume(float value)
{
  return Mathf.Clamp(Mathf.Log10(value) * 20f, -80f, 20f);
}

private static float FromLogVolume(float value)
{
  return Mathf.Clamp01(Mathf.Exp(value / 20f));
}
2 Likes

Bump? Still looking for a good way to cross fade between snapshots that works properly :frowning:

@TimHeijden2 Hello to you and also to the rest, I’ve managed to get it working by exposing the volume param to script and then selecting ā€œattenuation Snapshot Transitionā€, from the context menu appearing on right click. Hope that helps!

Here’s a screenshot of what I’m selecting:

1 Like