听起来你的工作方向是正确的。正如您所说,请求的音频量可以通过将请求的样本数除以采样率来计算。但您还必须考虑渠道。在立体声文件中,每秒的样本数是采样率的两倍。
我已经将延迟淡出的非常基本的代码示例放在GitHub 要点在这里。可以进行一些改进,例如允许在从调用返回的音频中途开始淡出Read
但希望这能让您大致了解如何通过对 FadeInOutSampleProvider 进行一些小修改来实现它。
主要变化是 BeginFadeOut 的一个额外参数,它设置两个新变量(fadeOutDelaySamples、fadeOutDelayPosition):
/// <summary>
/// Requests that a fade-out begins (will start on the next call to Read)
/// </summary>
/// <param name="fadeDurationInMilliseconds">Duration of fade in milliseconds</param>
public void BeginFadeOut(double fadeAfterMilliseconds, double fadeDurationInMilliseconds)
{
lock (lockObject)
{
fadeSamplePosition = 0;
fadeSampleCount = (int)((fadeDurationInMilliseconds * source.WaveFormat.SampleRate) / 1000);
fadeOutDelaySamples = (int)((fadeAfterMilliseconds * source.WaveFormat.SampleRate) / 1000);
fadeOutDelayPosition = 0;
//fadeState = FadeState.FadingOut;
}
}
然后在Read
方法我们可以跟踪延迟的程度,如果是这样,我们可以开始淡出
public int Read(float[] buffer, int offset, int count)
{
int sourceSamplesRead = source.Read(buffer, offset, count);
lock (lockObject)
{
if (fadeOutDelaySamples > 0)
{
fadeOutDelayPosition += sourceSamplesRead / WaveFormat.Channels;
if (fadeOutDelayPosition >= fadeOutDelaySamples)
{
fadeOutDelaySamples = 0;
fadeState = FadeState.FadingOut;
}
}
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;
}