How does the audio file playback duration change when the pitch changes in XNA / Monogame?

Using the SoundEffects class in XNA (or alternative implementations of XNA, such as MonoGame or FNA), the sound effect has a specific playback duration equal to the length of the sound file that is stored in:

SoundEffect.Duration

However, when the pitch is changed for playback (between 1 and -1), it also changes the effective duration of the playback (for example, lower pitch = slower playback), changing the value in SoundEffect.Duration is useless.

What is a mathematical expression for calculating the duration depending on the playing height?

What I'm trying to do is smoothly suppress sound effects during, for example, the last second of their playback. But in order to reduce their volume linearly at this last second, I need to know when the reproduction in practice ends, therefore, its (max. Modular, actual) duration.

+4
source share
1 answer

I use the extension method for not 100% , but pretty close:

public static TimeSpan GetEstimatedDuration(this SoundEffect sfx, float pitch)
{
    return TimeSpan.FromMilliseconds(sfx.Duration.TotalMilliseconds * (0.2514 * Math.Pow(pitch, 2) - 0.74 * pitch + 1));
}

Background

I was also not lucky to find “real” mathematicians behind this, so I wrote a small function like this:

private void DurationTest(string sfxAssetName)
    {
        for (float pitch = -1; pitch <= 1; pitch += 0.5f)
        {
            var sfx = this.Content.Load<SoundEffect>(sfxAssetName);
            using (var instance = sfx.CreateInstance())
            {
                instance.Pitch = pitch;
                //var estimatedDuration = sfx.GetEstimatedDuration(pitch);
                instance.Play();
                var sw = System.Diagnostics.Stopwatch.StartNew();
                while (instance.State == SoundState.Playing)
                { }
                sw.Stop();
                var duration = sw.Elapsed;
                System.Diagnostics.Debug.WriteLine("sfx={0} | pitch={1:0.00} | duration={2:0.00}secs", sfxAssetName, pitch, duration.TotalSeconds);
                //System.Diagnostics.Debug.WriteLine("sfx={0} | pitch={1:0.00} | estimated={2:0.00}secs | actual={3:0.00}secs", sfxAssetName, pitch, estimatedDuration.TotalSeconds, duration.TotalSeconds);
            }
        }
    }
// output
sfx=bombfuse | pitch=-1.00 | duration=3.89secs
sfx=bombfuse | pitch=-0.50 | duration=2.75secs
sfx=bombfuse | pitch= 0.00 | duration=1.95secs
sfx=bombfuse | pitch= 0.50 | duration=1.38secs
sfx=bombfuse | pitch= 1.00 | duration=0.98secs

excel, , GetEstimatedDuration. DurationTest ( ) - :

// output bombfuse (short)
sfx=bombfuse | pitch=-1.00 | estimated=3.88secs | actual=3.89secs
sfx=bombfuse | pitch=-0.50 | estimated=2.79secs | actual=2.76secs
sfx=bombfuse | pitch= 0.00 | estimated=1.95secs | actual=1.95secs
sfx=bombfuse | pitch= 0.50 | estimated=1.35secs | actual=1.38secs
sfx=bombfuse | pitch= 1.00 | estimated=1.00secs | actual=0.98secs
// output dreiklang (long)
sfx=dreiklang | pitch=-1.00 | estimated=24.67secs | actual=24.77secs
sfx=dreiklang | pitch=-0.50 | estimated=17.75secs | actual=17.52secs
sfx=dreiklang | pitch= 0.00 | estimated=12.39secs | actual=12.39secs
sfx=dreiklang | pitch= 0.50 | estimated= 8.58secs | actual= 8.76secs
sfx=dreiklang | pitch= 1.00 | estimated= 6.33secs | actual= 6.20secs

, , .

+2

Source: https://habr.com/ru/post/1624587/


All Articles