gpt4 book ai didi

c# - 淡入/淡出声音

转载 作者:太空狗 更新时间:2023-10-29 21:40:55 25 4
gpt4 key购买 nike

我有一个无限循环播放的背景音。我希望它在用户按下按钮时淡出。

我尝试了以下方法:

  • 使用 WaveStream 启动 DirectSoundOut
  • 定时器改变 WaveChannel32 的音量。

问题:

  • 在播放声音时改变音量会产生噪音。

有人知道更好的解决方案吗?

最佳答案

要执行平滑的淡入或淡出,您需要在样本级别执行此操作。然后将每个样本乘以逐渐增加或减少的数字。您正在使用 WaveChannel32,因此您的音频已经转换为 32 位 float 。然后,我将创建另一个 IWaveProvider 实现程序,负责执行淡入和淡出。通常它会通过样本不变,但在 Read 方法中,如果您处于淡入或淡出状态,它会乘以每个样本(如果是立体声,则成对)。

NAudio 1.5 中的 ISampleProvider 接口(interface)旨在使此类事情变得更加容易,因为它允许您将样本作为 32 位 float 进行处理,而不是实现 IWaveProvider,后者需要您将 byte[] 转换为 float[ ].这是我刚刚制作的用于淡入和淡出的 SampleProvider,我将把它包含在下一个 NAudio 中,并希望尽快在博客中介绍它。只需使用适当的淡入淡出持续时间调用 BeginFadeInBeginFadeOut

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; }
}
}

关于c# - 淡入/淡出声音,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9468083/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com