0

グローバルなエコー効果を作成するために、つまり現在のオーディオ出力に影響を与えるために、 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回目の試み:

今回はBufferedWaveProviderMarkさんの提案通り使ってみました。問題は、再生に遅延がないため、エコーではなくフィードバック ループが発生することです。出力は.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);
    };
}
4

1 に答える 1

1

の何百ものインスタンスを開き続けないでくださいWaveOut。のインスタンスを 1 つだけ持つ必要がありますWaveOut。これは、録音されたオーディオで始まるカスタム ストリームから再生され (aBufferedWaveProviderが適切な出発点になります)、それをエフェクトに渡します。これを行う最善の方法はISampleProvider、そのReadメソッドでソース プロバイダーから読み取り、効果を実行する実装を作成することです。

最後に、ループバック オーディオを使用してサウンドをキャプチャし、それを同じデバイスから再生しているため、それ自体が厄介なフィードバック ループを作成している可能性があります。

于 2015-03-12T21:12:29.593 に答える