2012-02-27 12 views
5

私は無限ループでバックグラウンドサウンドを再生しています。ユーザーがボタンを押したときに消えてしまいたいフェードサウンドのイン/アウト

Iは、次の試み:

  • A DirectSoundOutがWaveStream
  • Aタイマで開始されるWaveChannel32の容積を変化させます。

問題:

  • 音の再生中に音量を変更するには、ノイズを生成します。

もっと良い解決方法を知っている人はいますか?

答えて

6

滑らかなフェードインまたはフェードアウトを実行するには、サンプルレベルで行う必要があります。次に、各サンプルに徐々に増減する数を掛けます。 WaveChannel32を使用しているので、オーディオはすでに32ビットのフロートに変換されています。次に、フェードインとフェードアウトを担当する別のIWaveProvider実装者を作成します。通常はサンプルをそのまま通過しますが、Readメソッドでは、フェードインまたはフェードアウトしている場合は、各サンプル(またはステレオの場合はペア)が掛けられます。

NAudio 1.5のISampleProviderインターフェイスは、バイト型[]から浮動型に変換する必要があるIWaveProviderを実装するのではなく、サンプルを既に32ビットの浮動小数点数として扱うことができるため、 []。ここでは、フェードインとフェードアウトのためのSampleProviderを作成しました。これを次のNAudioに組み込み、すぐにそれについてのブログを作成します。適切なフェード持続時間を持つBeginFadeInまたはBeginFadeOutに電話するだけです。

public class FadeInOutSampleProvider : ISampleProvider 
{ 
    enum FadeState 
    { 
     Silence, 
     FadingIn, 
     FullVolume, 
     FadingOut, 
    } 

    private readonly object lockObject = new object(); 
    private readonly ISampleProvider source; 
    private int fadeSamplePosition; 
    private int fadeSampleCount; 
    private FadeState fadeState; 

    public FadeInOutSampleProvider(ISampleProvider source) 
    { 
     this.source = source; 
     this.fadeState = FadeState.FullVolume; 
    } 

    public void BeginFadeIn(double fadeDurationInMilliseconds) 
    { 
     lock (lockObject) 
     { 
      fadeSamplePosition = 0; 
      fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate)/1000); 
      fadeState = FadeState.FadingIn; 
     } 
    } 

    public void BeginFadeOut(double fadeDurationInMilliseconds) 
    { 
     lock (lockObject) 
     { 
      fadeSamplePosition = 0; 
      fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate)/1000); 
      fadeState = FadeState.FadingOut; 
     } 
    } 

    public int Read(float[] buffer, int offset, int count) 
    { 
     int sourceSamplesRead = source.Read(buffer, offset, count); 
     lock (lockObject) 
     { 
      if (fadeState == FadeState.FadingIn) 
      { 
       FadeIn(buffer, offset, sourceSamplesRead); 
      } 
      else if (fadeState == FadeState.FadingOut) 
      { 
       FadeOut(buffer, offset, sourceSamplesRead); 
      } 
      else if (fadeState == FadeState.Silence) 
      { 
       ClearBuffer(buffer, offset, count); 
      } 
     } 
     return sourceSamplesRead; 
    } 

    private static void ClearBuffer(float[] buffer, int offset, int count) 
    { 
     for (int n = 0; n < count; n++) 
     { 
      buffer[n + offset] = 0; 
     } 
    } 

    private void FadeOut(float[] buffer, int offset, int sourceSamplesRead) 
    { 
     int sample = 0; 
     while (sample < sourceSamplesRead) 
     { 
      float multiplier = 1.0f - (fadeSamplePosition/(float)fadeSampleCount); 
      for (int ch = 0; ch < source.WaveFormat.Channels; ch++) 
      { 
       buffer[offset + sample++] *= multiplier; 
      } 
      fadeSamplePosition++; 
      if (fadeSamplePosition > fadeSampleCount) 
      { 
       fadeState = FadeState.Silence; 
       // clear out the end 
       ClearBuffer(buffer, sample + offset, sourceSamplesRead - sample); 
       break; 
      } 
     } 
    } 

    private void FadeIn(float[] buffer, int offset, int sourceSamplesRead) 
    { 
     int sample = 0; 
     while (sample < sourceSamplesRead) 
     { 
      float multiplier = (fadeSamplePosition/(float)fadeSampleCount); 
      for (int ch = 0; ch < source.WaveFormat.Channels; ch++) 
      { 
       buffer[offset + sample++] *= multiplier; 
      } 
      fadeSamplePosition++; 
      if (fadeSamplePosition > fadeSampleCount) 
      { 
       fadeState = FadeState.FullVolume; 
       // no need to multiply any more 
       break; 
      } 
     } 
    } 

    public WaveFormat WaveFormat 
    { 
     get { return source.WaveFormat; } 
    } 
} 
-1

それとも、ただ、これを行うことができます:フェードアウトの

while (waveOut.volume > 0.1) 
{ 
    waveOut.volume -= 0.1; 
    System.Threading.Thread.Sleep(10); 
} 

^例を。私は自分のプログラムで使っていますが、うまく動作します。

関連する問題