배경 음악이 무한 루프로 재생됩니다. 사용자가 버튼을 눌렀을 때 페이드 아웃하기를 원합니다.페이딩 사운드 입/출력
- DirectSoundOut은 WaveChannel32의 볼륨을 변경하는 WaveStream
- 타이머와 함께 시작됩니다 : 나는 다음 시도했다.
문제점 :
- 소리가 재생되는 동안 볼륨을 변경하면 소음을 생산하고 있습니다.
더 나은 솔루션을 아는 사람이 있습니까?
배경 음악이 무한 루프로 재생됩니다. 사용자가 버튼을 눌렀을 때 페이드 아웃하기를 원합니다.페이딩 사운드 입/출력
문제점 :
더 나은 솔루션을 아는 사람이 있습니까?
부드러운 페이드 인 또는 페이드 아웃을 수행하려면 샘플 레벨에서 수행해야합니다. 그런 다음 각 샘플에 점차적으로 증가하거나 감소하는 수를 곱합니다. 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; }
}
}
또는 당신은이 작업을 수행 할 수 있습니다 페이드 아웃의
while (waveOut.volume > 0.1)
{
waveOut.volume -= 0.1;
System.Threading.Thread.Sleep(10);
}
^예를. 내 자신의 프로그램에서 사용, 잘 작동합니다.