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);
这使您可以快速重新排序链中的效果,因为每个效果都将效果链的头部作为输入。如果你不添加任何效果,它只是作为一个传递。如果你愿意的话,你可以很容易地扩展这个类来拥有更多的方法来管理包含的效果,但是就目前而言,它工作得非常干净。