2012-02-27 5 views
5

배경 음악이 무한 루프로 재생됩니다. 사용자가 버튼을 눌렀을 때 페이드 아웃하기를 원합니다.페이딩 사운드 입/출력

  • DirectSoundOut은 WaveChannel32의 볼륨을 변경하는 WaveStream
  • 타이머와 함께 시작됩니다 :

    나는 다음 시도했다.

문제점 :

  • 소리가 재생되는 동안 볼륨을 변경하면 소음을 생산하고 있습니다.

더 나은 솔루션을 아는 사람이 있습니까?

답변

6

부드러운 페이드 인 또는 페이드 아웃을 수행하려면 샘플 레벨에서 수행해야합니다. 그런 다음 각 샘플에 점차적으로 증가하거나 감소하는 수를 곱합니다. WaveChannel32를 사용 중이므로 오디오가 이미 32 비트 부동 소수점으로 변환되었습니다. 그런 다음 페이드 인 (fade in) 및 페이드 아웃 (fade out)을 담당하는 또 다른 IWaveProvider 구현자를 만들 것입니다. 일반적으로 샘플은 변경되지 않지만 Read 메서드에서는 페이드 인하거나 페이드 아웃하는 경우 각 샘플 (또는 스테레오 인 경우 쌍)을 곱합니다.

NAudio 1.5의 ISampleProvider 인터페이스는 byte []를 float로 변환해야하는 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); 
} 

^예를. 내 자신의 프로그램에서 사용, 잘 작동합니다.