如何将多个 NAudio ISampleProvider 效果链接在一起
Posted
技术标签:
【中文标题】如何将多个 NAudio ISampleProvider 效果链接在一起【英文标题】:How to chain together multiple NAudio ISampleProvider Effects 【发布时间】:2017-09-26 18:51:33 【问题描述】:我在 ISampleProvider 模型中编码了一些 DSP 效果。为了应用一种效果,我这样做了,效果很好。
string filename = "C:\myaudio.mp3";
MediaFoundationReader mediaFileReader = new MediaFoundationReader(filename);
ISampleProvider sampProvider = mediaFileReader.ToSampleProvider();
ReverbSampleProvider reverbSamplr = new ReverbSampleProvider(sampProvider);
IWavePlayer waveOutDevice.Init(reverbSamplr);
waveOutDevice.Play();
如何同时对同一个输入文件应用多种效果? 例如,如果我有一个混响效果器和失真效果器提供器,我如何将它们链接在一起以将它们同时应用于一个输入文件?
【问题讨论】:
【参考方案1】:效果可以通过将一个作为“源”传递给下一个来链接在一起。所以如果你想让你的音频先经过混响,然后失真,你可以做这样的事情,将原始音频传递给混响效果,混响的输出进入失真效果,然后将失真发送到 waveOut设备。
var reverb = new ReverbSampleProvider(sampProvider);
var distortion = new DistortionSampleProvider(reverb);
waveOutDevice.Init(distortion);
(n.b. NAudio 没有内置混响/失真效果 - 您必须自己制作或从其他地方获取)
【讨论】:
哈,太容易了。它工作完美。谢谢 Mark,ISampleProvider 框架是天才。【参考方案2】:Mark 的回答是正确的,但是如果您以不同的顺序复制和粘贴内容,这种方法会很痛苦,因为您必须更改您正在传递的变量。
例如,如果您以:
var lpf = new LowPassEffectStream(input);
var reverb = new ReverbEffectStream(lpf);
var stereo = new StereoEffectStream(reverb);
var vol = new VolumeSampleProvider(stereo);
waveOutDevice.Init(vol);
如果您想交换混响和立体声,快速复制粘贴会将输入变量向后移动:
var lpf = new LowPassEffectStream(input);
var stereo = new StereoEffectStream(reverb); // <--
var reverb = new ReverbEffectStream(lpf); // <--
var vol = new VolumeSampleProvider(stereo);
waveOutDevice.Init(vol);
它还可以很容易地修复一个参数但忘记修复另一个参数,例如修复stereo
效果以将lpf
作为其输入,但忘记修复reverb
效果。这通常会导致效果链中的跳过效果,从而在效果似乎不起作用时导致调试受挫。
当我将效果堆叠在一起并重新排序时,为了让事情变得更容易和更不容易出错,我创建了以下帮助器类:
class EffectChain : ISampleProvider
public EffectChain(ISampleProvider source)
this._sourceStream = source;
private readonly ISampleProvider _sourceStream;
private readonly List<ISampleProvider> _chain = new List<ISampleProvider>();
public ISampleProvider Head
get
return _chain.LastOrDefault() ?? _sourceStream;
public WaveFormat WaveFormat
get
return Head.WaveFormat;
public void AddEffect(ISampleProvider effect)
_chain.Add(effect);
public int Read(float[] buffer, int offset, int count)
return Head.Read(buffer, offset, count);
你可以这样使用它:
var effectChain = new EffectChain(input);
var lpf = new LowPassEffectStream(effectChain.Head);
effectChain.AddEffect(lpf);
var stereo = new StereoEffectStream(effectChain.Head);
effectChain.AddEffect(stereo);
var reverb = new ReverbEffectStream(effectChain.Head);
effectChain.AddEffect(reverb);
var vol = new VolumeSampleProvider(effectChain.Head);
effectChain.AddEffect(vol);
waveOutDevice.Init(effectChain);
这使您可以快速重新排序链中的效果,因为每个效果都将效果链的头部作为输入。如果你不添加任何效果,它只是作为一个传递。如果你愿意的话,你可以很容易地扩展这个类来拥有更多的方法来管理包含的效果,但是就目前而言,它工作得非常干净。
【讨论】:
以上是关于如何将多个 NAudio ISampleProvider 效果链接在一起的主要内容,如果未能解决你的问题,请参考以下文章