C# 如何使用NAudio正确地将淡出写入WAV文件?
我正在使用NAudio转换和修剪一些音频文件,并尝试在每个文件的最后几秒钟添加淡出 我已经检查了,但是所有的答案都是关于播放带有淡入淡出的wav文件,而我实际上需要将淡入淡出写入输出文件 那么,有没有办法用NAudio做到这一点?如果没有,我愿意接受其他建议C# 如何使用NAudio正确地将淡出写入WAV文件?,c#,.net,audio,wav,naudio,C#,.net,Audio,Wav,Naudio,我正在使用NAudio转换和修剪一些音频文件,并尝试在每个文件的最后几秒钟添加淡出 我已经检查了,但是所有的答案都是关于播放带有淡入淡出的wav文件,而我实际上需要将淡入淡出写入输出文件 那么,有没有办法用NAudio做到这一点?如果没有,我愿意接受其他建议 编辑:这是我尝试过的: private void PerformFadeOut(string inputPath, string outputPath) { WaveFileReader waveSource = new Wave
编辑:这是我尝试过的:
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);
但是,输出文件没有应用任何淡入淡出。那么,我在这里遗漏了什么呢?好的,让我们总结一下,以防将来有人遇到同样的问题: 在@yms的大力帮助下,我使用以下方法将淡入淡出写入文件:
WaveFileWriter.CreateWaveFile(outputPath, new SampleToWaveProvider(fadeOut));
但这导致wave编写器只在最后两秒钟编写,这是有意义的,因此我尝试使用该类而不是FadeInOutSampleProvider
。这样我就可以编写整个文件,但最终导致淡入开始的位置错误(保存时更明显。而不是播放时的)
我使用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));
}
}
以下是写入淡出之前和之后的文件:
如上所示,淡出不会从正确的位置开始
在DelayFadeOutSampleProvider
中进行了一些调查之后,我在Read
方法中发现了一个bug,因此我对其进行了如下修改:
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;
}
现在一切正常
如果有人感兴趣,我已经要求作者(@mark heath)用这个补丁更新原始要点。您的原始代码使用原始
波源作为输入,这就是您没有褪色的原因
以下备选方案使用淡出对象fadeOut
:
WaveFileWriter.CreateWaveFile16(outputPath, fadeOut);
CreateWaveFile16
的签名为:
public static void CreateWaveFile16(string filename, ISampleProvider sourceProvider)
这一点可以从中看出
另一种选择是使用该类并将您的fadeOut
对象转换为IWaveProvider
,这允许您使用常规的CreateWaveFile
方法
WaveFileWriter.CreateWaveFile(outputPath, new SampleToWaveProvider(fadeOut))
正如您所知,在所有情况下,您的输出文件将只包含与淡出相对应的最后k秒,如果您希望整个文件具有淡出,则需要另一个类。是否尝试使用WaveFileWriter.CreateWaveFile(输出路径,淡出);相反?@ymsCreateWaveFile
方法需要第二个IWaveProvider
类型的参数。显然,FadeInutsSampleProvider
类没有实现这个接口,因此无法强制转换。然后是WaveFileWriter.CreateWaveFile16(outputPath,fadeOut)或WaveFileWriter.CreateWaveFile(outputPath,new SampleToWaveProvider(fadeOut))。请参见此处:@ymsCreateWaveFile16
也不起作用,因为它需要相同类型的参数。但第二个建议可能确实有效。让我试试看.“它需要相同类型的参数”不,它不。。。至少在源代码中没有指出:publicstaticvoidcreatewavefile16(stringfilename,isampleprovidersourceprovider)非常感谢,您让我走上了正确的道路。我真的很感谢你的帮助。投票表决通过,一旦有可能,将授予赏金。@AhmedAbdelhameed我很高兴它起到了作用