私は無限ループでバックグラウンドサウンドを再生しています。ユーザーがボタンを押したときに消えてしまいたいフェードサウンドのイン/アウト
Iは、次の試み:
- A DirectSoundOutがWaveStream
- Aタイマで開始されるWaveChannel32の容積を変化させます。
問題:
- 音の再生中に音量を変更するには、ノイズを生成します。
もっと良い解決方法を知っている人はいますか?
私は無限ループでバックグラウンドサウンドを再生しています。ユーザーがボタンを押したときに消えてしまいたいフェードサウンドのイン/アウト
Iは、次の試み:
問題:
もっと良い解決方法を知っている人はいますか?
滑らかなフェードインまたはフェードアウトを実行するには、サンプルレベルで行う必要があります。次に、各サンプルに徐々に増減する数を掛けます。 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; }
}
}
それとも、ただ、これを行うことができます:フェードアウトの
while (waveOut.volume > 0.1)
{
waveOut.volume -= 0.1;
System.Threading.Thread.Sleep(10);
}
^例を。私は自分のプログラムで使っていますが、うまく動作します。