2016-01-16 38 views
4

使用在XNA的SoundEffects類(或類似MonoGame或FNA XNA的替代實施方式),聲音效果有一定的再現持續時間等於所述聲音文件的長度被存儲在:在更改XNA/Monogame中的音高時,聲音文件的播放時間如何變化?

SoundEffect.Duration 

然而,當音調改變以進行播放時(在1和-1之間),這也會改變播放的有效持續時間(例如,較低的音調=較慢的播放),使SoundEffect.Duration中的值無效。

根據播放音高計算持續時間的數學表達式是什麼?

我想要做的是平穩淡入淡出聲音效果。他們播放的最後一秒。但爲了在最後一秒內線性減小它們的音量,我需要知道播放何時結束,因此它的(音調調製,實際)持續時間。

回答

2

我又寫道擴展方法這是不是100%準確但八九不離十:

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)); 
} 

背景

我也倒黴,找到 '真實'數學背後,所以我寫了這樣一個小函數:

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 

我希望這是對你有所幫助,隨意使用的方法爲自己的需要和comparisions。

+0

哇,我沒想到這會是那麼複雜。我假設了一個簡單的方程,但不是一個多項式擬合;-)我會盡快檢查! –

+0

嗯,那只是我擺弄出來的解決方案:) - 也許別人可以啓發我們 – Bashn