C#
[SerializeField] AudioClip jumpClip;
[SerializeField] float jumpVolume = 1f;
[SerializeField] float minPitch = 0.9f;
[SerializeField] float maxPitch = 1.1f;
[SerializeField] float fadeInDuration = 0.5f;
[SerializeField] float fadeOutDuration = 0.3f;

AudioSource jumpSource;
Coroutine activeFadeCoroutine;
bool isFadingOut;

void Awake()
{
    jumpSource = GetComponent<AudioSource>();

    if (jumpSource == null)
        jumpSource = gameObject.AddComponent<AudioSource>();

    jumpSource.playOnAwake = false;
    jumpSource.loop = false;
    jumpSource.spatialBlend = 0f;
    jumpSource.volume = jumpVolume;
}

void OnDisable()
{
    CancelActiveFade();
}

void OnJump()
{
    PlayJumpSoundWithRandomPitchAndFadeIn();
}

void OnLand()
{
    FadeOutJumpSound();
}

void PlayJumpSoundWithRandomPitchAndFadeIn()
{
    if (jumpClip == null)
        return;

    if (jumpSource == null)
        return;

    CancelActiveFade();
    isFadingOut = false;

    jumpSource.Stop();
    jumpSource.clip = jumpClip;
    jumpSource.pitch = Random.Range(minPitch, maxPitch);
    jumpSource.volume = 0f;
    jumpSource.Play();

    if (fadeInDuration <= 0f)
    {
        jumpSource.volume = jumpVolume;
        return;
    }

    activeFadeCoroutine = StartCoroutine(FadeJumpVolumeIn());
}

void FadeOutJumpSound()
{
    if (jumpSource == null)
        return;

    if (jumpClip == null)
        return;

    if (!jumpSource.isPlaying && !isFadingOut)
        return;

    CancelActiveFade();
    isFadingOut = true;

    if (fadeOutDuration <= 0f)
    {
        jumpSource.Stop();
        jumpSource.volume = jumpVolume;
        jumpSource.pitch = 1f;
        isFadingOut = false;
        return;
    }

    activeFadeCoroutine = StartCoroutine(FadeJumpVolumeOut());
}

void StopJumpSound()
{
    CancelActiveFade();
    isFadingOut = false;

    if (jumpSource == null)
        return;

    jumpSource.Stop();
    jumpSource.volume = jumpVolume;
    jumpSource.pitch = 1f;
}

void CancelActiveFade()
{
    if (activeFadeCoroutine == null)
        return;

    StopCoroutine(activeFadeCoroutine);
    activeFadeCoroutine = null;
}

IEnumerator FadeJumpVolumeIn()
{
    float elapsed = 0f;
    float startVolume = jumpSource.volume;
    float targetVolume = jumpVolume;

    while (elapsed < fadeInDuration)
    {
        if (jumpSource == null)
            yield break;

        if (isFadingOut)
            yield break;

        elapsed += Time.deltaTime;
        jumpSource.volume = Mathf.Lerp(
            startVolume,
            targetVolume,
            elapsed / fadeInDuration
        );
        yield return null;
    }

    if (jumpSource == null)
        yield break;

    jumpSource.volume = targetVolume;
    activeFadeCoroutine = null;
}

IEnumerator FadeJumpVolumeOut()
{
    float elapsed = 0f;
    float startVolume = jumpSource.volume;

    while (elapsed < fadeOutDuration)
    {
        if (jumpSource == null)
            yield break;

        elapsed += Time.deltaTime;
        jumpSource.volume = Mathf.Lerp(
            startVolume,
            0f,
            elapsed / fadeOutDuration
        );
        yield return null;
    }

    if (jumpSource == null)
        yield break;

    jumpSource.Stop();
    jumpSource.volume = jumpVolume;
    jumpSource.pitch = 1f;
    isFadingOut = false;
    activeFadeCoroutine = null;
}