我使用NAudio转换&修剪一些音频文件,我试图在每个文件的最后几秒添加淡出。
我已经检查了this,this和{{3}},但所有的答案都在讨论用淡入淡出来播放wav文件,而我需要将淡入淡出实际写入输出文件。
那么,有没有办法用NAudio做到这一点?如果没有,我可以接受其他建议。
修改:这是我尝试过的:
private void PerformFadeOut(string inputPath, string outputPath)
{
WaveFileReader waveSource = new WaveFileReader(inputPath);
ISampleProvider sampleSource = waveSource.ToSampleProvider();
OffsetSampleProvider fadeOutSource = new OffsetSampleProvider(sampleSource);
// Assume the length of the audio file is 122 seconds.
fadeOutSource.SkipOver = TimeSpan.FromSeconds(120); // Hard-coded values for brevity
// Two seconds fade
var fadeOut = new FadeInOutSampleProvider(fadeOutSource);
fadeOut.BeginFadeOut(2000);
Player = new WaveOut();
Player.Init(fadeOut);
Player.Play();
}
当我使用Player.Play()
- 应用淡入淡出后播放音频时,如上面的方法 - ,它可以正常工作,我可以听到淡入淡出。现在,我想将此结果导出到输出WAV文件。
我尝试添加以下行:
WaveFileWriter.CreateWaveFile(outputPath, waveSource);
但是,输出文件没有应用任何淡入淡出。那么,我在这里错过了什么?
答案 0 :(得分:1)
好的,让我们把所有事情都包起来以防将来有人遇到同样的问题:
在@yms的帮助下,我设法使用以下方法将淡入淡出写入文件:
WaveFileWriter.CreateWaveFile(outputPath, new SampleToWaveProvider(fadeOut));
但是这导致wave writer只写了最后两秒,这是有意义的,所以我尝试使用DelayFadeOutSampleProvider
类而不是FadeInOutSampleProvider
。有了这个,我就能写出整个文件,但最终导致褪色开始处于错误的位置(在保存时更明显。不播放时< / em>的)。
我用Audacity生成了一个10秒的wav文件,并使用以下方法进行测试:
private static void PerformFadeOut(string inputPath, string outputPath, bool playNoSave = false)
{
WaveFileReader waveSource = new WaveFileReader(inputPath);
ISampleProvider sampleSource = waveSource.ToSampleProvider();
// Two seconds fade
var fadeOut = new DelayFadeOutSampleProvider(sampleSource);
fadeOut.BeginFadeOut(8000, 2000);
if(playNoSave)
{
// Here the fade is played exactly where expected (@00:08)
var player = new WaveOut();
player.Init(fadeOut);
player.Play();
}
else
{
// But when saving, the fade is applied @00:04!
WaveFileWriter.CreateWaveFile(outputPath, new SampleToWaveProvider(fadeOut));
}
}
这里是文件,之前&amp;写完淡出后:
如上所示,淡出不会从正确的位置开始。
在DelayFadeOutSampleProvider
进行一些调查后,我在Read
方法中发现了一个错误,因此我对其进行了修改:
public int Read(float[] buffer, int offset, int count)
{
int sourceSamplesRead = source.Read(buffer, offset, count);
lock (lockObject)
{
if (fadeOutDelaySamples > 0)
{
int oldFadeOutDelayPos = fadeOutDelayPosition;
fadeOutDelayPosition += sourceSamplesRead / WaveFormat.Channels;
if (fadeOutDelayPosition > fadeOutDelaySamples)
{
int normalSamples = (fadeOutDelaySamples - oldFadeOutDelayPos) * WaveFormat.Channels;
int fadeOutSamples = (fadeOutDelayPosition - fadeOutDelaySamples) * WaveFormat.Channels;
// apply the fade-out only to the samples after fadeOutDelayPosition
FadeOut(buffer, offset + normalSamples, fadeOutSamples);
fadeOutDelaySamples = 0;
fadeState = FadeState.FadingOut;
return sourceSamplesRead;
}
}
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;
}
现在一切正常。
全班的{p> Here's my fork,如果有人感兴趣,我已经要求作者(@ mark-heath)用这个修补程序更新原始要点。答案 1 :(得分:1)
原始代码使用原始waveSource
作为输入,这就是您没有淡入淡出的原因。
以下替代方法使用fadeOut
对象:
WaveFileWriter.CreateWaveFile16(outputPath, fadeOut);
CreateWaveFile16
的签名是:
public static void CreateWaveFile16(string filename, ISampleProvider sourceProvider)
这可以在source code of the class WaveFileWriter。
中看到另一种方法是使用类SampleToWaveProvider并将fadeOut
对象转换为IWaveProvider
,这样您就可以使用常规的CreateWaveFile
方法。
WaveFileWriter.CreateWaveFile(outputPath, new SampleToWaveProvider(fadeOut))
如您所知,在所有情况下,您的输出文件将仅包含与淡出对应的最后k秒,如果您希望整个文件 为淡出,则需要不同的类。