グローバルなエコー効果を作成するために、つまり現在のオーディオ出力に影響を与えるために、 NAudioとWasapiLoopbackCaptureをWaveOutと組み合わせて使用しています。
しかし、私の実装はかなり貧弱に思えますが、まったくうまくいきません。マシンごとに音が異なり、クラッシュすることもあります。
これが私が思いついたコードです。オーディオ出力を記録し、75 ミリ秒ごとに WaveOut を使用して記録されたストリームを再生します。
ここで何が間違っているのですか、どうすれば改善できますか?
private static void CreateReverb()
{
MemoryStream loopbackWave = new MemoryStream();
DateTime lastEcho = DateTime.Now;
WasapiLoopbackCapture waveIn = new WasapiLoopbackCapture();
waveIn.StartRecording();
waveIn.DataAvailable += delegate(object sender, WaveInEventArgs e)
{
loopbackWave.Write(e.Buffer, 0, e.BytesRecorded);
if ((DateTime.Now - lastEcho).TotalMilliseconds > 75)
{
lastEcho = DateTime.Now;
byte[] loopbackBytes = loopbackWave.ToArray();
loopbackWave.Dispose();
loopbackWave = new MemoryStream();
using (MemoryStream waveStream = new MemoryStream())
{
using (WaveFileWriter waveFileWriter = new WaveFileWriter(waveStream, waveIn.WaveFormat))
{
waveFileWriter.Write(loopbackBytes, 0, loopbackBytes.Length);
}
loopbackBytes = waveStream.ToArray();
}
for (int i = 0; i < 3; i++)
{
ThreadPool.QueueUserWorkItem(delegate
{
try
{
WaveOut waveOut = new WaveOut();
waveOut.Init(new WaveFileReader(new MemoryStream(loopbackBytes)));
waveOut.Volume = ReverbIntensity * .5f;
waveOut.Play();
Thread.Sleep(200);
waveOut.Dispose();
}
catch { }
});
}
}
};
}
編集:2回目の試み:
今回はBufferedWaveProvider
Markさんの提案通り使ってみました。問題は、再生に遅延がないため、エコーではなくフィードバック ループが発生することです。出力は.5f
ボリュームがあり、機能させるためには約 75ms の遅延が必要です。
private static void CreateReverb()
{
DateTime lastEcho = DateTime.Now;
WasapiLoopbackCapture waveIn = new WasapiLoopbackCapture();
BufferedWaveProvider bufferedWaveProvider = new BufferedWaveProvider(waveIn.WaveFormat);
WasapiOut wasapiOut = new WasapiOut(AudioClientShareMode.Shared, 0);
bufferedWaveProvider.DiscardOnBufferOverflow = true;
wasapiOut.Init(bufferedWaveProvider);
wasapiOut.Play();
waveIn.StartRecording();
waveIn.DataAvailable += delegate(object sender, WaveInEventArgs e)
{
bufferedWaveProvider.AddSamples(e.Buffer, 0, e.BytesRecorded);
};
}