2016-01-16 12 views
4

Использование класса SoundEffects в XNA (или альтернативные реализации XNA как MonoGame или ФНК), звуковой эффект имеет определенную продолжительность воспроизведения, равную длине звукового файла, который хранится в:Как изменяется продолжительность воспроизведения звуковых файлов при изменении высоты тона в XNA/Monogame?

SoundEffect.Duration 

Однако, когда шаг изменяется для воспроизведения (между 1 и -1), это также изменяет эффективную продолжительность воспроизведения (например, более низкий шаг = более медленное воспроизведение), изменяя значение в SoundEffect.Duration бесполезно.

Что такое математическое выражение для вычисления продолжительности в зависимости от высоты воспроизведения?

То, что я пытаюсь сделать, это плавно исчезать звуковые эффекты во время, например, последнюю секунду их воспроизведения. Но для того, чтобы уменьшить их объем линейно в эту последнюю секунду, мне нужно знать, когда воспроизведение на практике заканчивается, следовательно, его (смоляная, фактическая) продолжительность.

ответ

2

Я Worte метод расширения для этого, который не 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 для Comparision (строки комментария выше) - который выводит это:

// 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 

Я надеюсь, что это несколько полезно для вас, не стесняйтесь использовать методы для собственных нужд и сравнений.

+0

Ничего себе, я не ожидал, что это будет тот комплекс. Я предположил несколько простое уравнение, но не полиномиальное соответствие ;-) Я проверю это как можно скорее! –

+0

Ну, это только решение, которое я пробормотал :) - может, кто-то еще может просветить нас – Bashn