首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >当在XNA/Monogame中改变音高时,声音文件的回放持续时间是如何变化的?

当在XNA/Monogame中改变音高时,声音文件的回放持续时间是如何变化的?
EN

Stack Overflow用户
提问于 2016-01-16 14:19:35
回答 1查看 350关注 0票数 4

使用XNA中的SoundEffects类(或XNA的替代实现,如MonoGame或FNA),声音效果的回放时间等于存储在以下文件中的声音文件的长度:

代码语言:javascript
运行
复制
SoundEffect.Duration

然而,当音高被更改为回放(1到-1之间)时,这也改变了回放的有效持续时间(例如,较低的音调=较慢的回放),从而使SoundEffect.Duration中的值无效。

根据播放音高计算持续时间的数学表达式是什么?

我想要做的是在他们的回放的最后一秒平稳地淡出声音效果。但是,为了在这最后一秒线性地减少它们的音量,我需要知道回放何时结束,因此它的(调音,实际)持续时间。

EN

回答 1

Stack Overflow用户

发布于 2016-01-17 19:03:52

我想出了一种扩展方法,即不是100%精确的,而是非常接近:

代码语言:javascript
运行
复制
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));
}

背景

我也不走运地找到了背后的“真实”数学,所以我写了这样一个小函数:

代码语言:javascript
运行
复制
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 --它输出如下:

代码语言:javascript
运行
复制
// 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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34827986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档