Search Unity

Fixing sound pops when changing audio mixers volumes at runtime

Discussion in 'Scripting' started by wileyjerkins, Mar 18, 2020.

  1. wileyjerkins

    wileyjerkins

    Joined:
    Oct 13, 2017
    Posts:
    77
    Unity Audio is a bit cryptic, and changing volumes often results in artifacts (pops). The following function attached to an SR_Sound script on my SoundController game object fixes it. You can use the same technique with audio sources too, but those are a bit less cryptic. I will include that as well.

    Code (CSharp):
    1.  
    2. AudioMixer SoundMixer = SoundController.GetComponent<SR_Sound>().Mixer;
    3. StartCoroutine(SR_Sound.MixerSetVolume(SoundMixer, "Thrusters", 30f));
    4.  
    Code (CSharp):
    1.  
    2. //to avoid annoying clicks in audio mixer volume changes
    3.     public static IEnumerator MixerSetVolume(AudioMixer _Mixer, string _WhichExposedParam, float _Vol = 0.001f, float _FadeLength = 0.1f)
    4.     {
    5.         //Debug.Log("Fading out soundfile" + _AudioSource.name);
    6.  
    7.         if(_Vol == 0f) { _Vol = 0.001f; }
    8.  
    9.         float _StartVolume;
    10.         bool __IsMixerParamExposed = _Mixer.GetFloat(_WhichExposedParam, out _StartVolume);
    11.         Extensions.Log(_WhichExposedParam + " mixer = " + _StartVolume);
    12.         float _EndVolume = _Vol;
    13.  
    14.         float _StartTime = Time.time;
    15.  
    16.         if (_StartVolume > _EndVolume)
    17.         {
    18.             while (Time.time < _StartTime + _FadeLength)
    19.             {
    20.                 _Mixer.SetFloat(_WhichExposedParam, _StartVolume - ((_StartVolume - _EndVolume) * ((Time.time - _StartTime) / _FadeLength)));
    21.                 yield return null;
    22.             }
    23.         }
    24.         else
    25.         {
    26.             while (Time.time < _StartTime + _FadeLength)
    27.             {
    28.                 _Mixer.SetFloat(_WhichExposedParam, _StartVolume + ((_EndVolume - _StartVolume) * ((Time.time - _StartTime) / _FadeLength)));
    29.                 yield return null;
    30.             }
    31.         }
    32.  
    33.     }
    34.  
    To tame Audio Sources:
    Code (CSharp):
    1. public static IEnumerator VolumeFadeOut(AudioSource _AudioSource, float _FadeLength = 0.1f)
    2.     {
    3.         //Debug.Log("Fading out soundfile" + _AudioSource.name);
    4.  
    5.         if (MasterVolume == 0f) { yield break; }
    6.  
    7.         float _StartVolume = _AudioSource.volume;
    8.         float _EndVolume = 0f;
    9.         float _StartTime = Time.time;
    10.         while (Time.time < _StartTime + _FadeLength)
    11.         {
    12.             _AudioSource.volume = _StartVolume + ((_EndVolume - _StartVolume) * ((Time.time - _StartTime) / _FadeLength));
    13.             yield return null;
    14.         }
    15.         if (_EndVolume == 0) { _AudioSource.Stop(); }
    16.     }
    17.  
    18.     public static IEnumerator VolumeFadeIn(AudioSource _AudioSource, float _EndVolume, float _FadeLength = 0.1f)
    19.     {
    20.         //Debug.Log("Fading in soundfile"+_AudioSource.name);
    21.  
    22.         if (MasterVolume == 0f) { yield break; }
    23.  
    24.         _AudioSource.volume = 0f;
    25.         _AudioSource.Play();
    26.         float _StartVolume = 0f;
    27.         float _StartTime = Time.time;
    28.         while (Time.time < _StartTime + _FadeLength)
    29.         {
    30.             _AudioSource.volume = _StartVolume + ((_EndVolume - _StartVolume) * ((Time.time - _StartTime) / _FadeLength));
    31.             yield return null;
    32.         }
    33.     }
     
    Last edited: Mar 18, 2020
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,727
    Aren't these coroutines? I think you gotta StartCoroutine them or not much will happen...
     
    wileyjerkins likes this.
  3. wileyjerkins

    wileyjerkins

    Joined:
    Oct 13, 2017
    Posts:
    77
    bah! you are right!
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,727
    If I only had a dollar for every time I inadvertently "called" a coroutine without handing it off to StartCoroutine()... :)
     
    wileyjerkins likes this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,727
    Come to think of it, it really should be a compiler warning. I don't think there can be any side effects from simply creating an IEnumerator and doing nothing with it... it's truly just a no-op and unlikely to be what the engineer intended.