如何使用AsioOut通过NAudio进行录音和播放

问题描述 投票:0回答:2

我正在尝试 获取声音输入直接发送输出,使用 C# 可以减少延迟。

我正在使用支持 ASIO 的库 NAudio 以获得更好的延迟。

特别是,我使用 AsioOut 对象进行录制,另一个用于使用 BufferedWaveProvider 初始化的播放,该对象填充了一个回调函数:OnAudioAvailable,它允许我使用 ASIO 缓冲区。

问题是我听到的声音带有各种故障并且有一点延迟。我认为问题出在 OnAudioAvailable 函数中,其中缓冲区充满了从声卡输入的数据。

声明:

NAudio.Wave.AsioOut playAsio;
NAudio.Wave.AsioOut recAsio;
NAudio.Wave.BufferedWaveProvider buffer;

播放流程:

if (sourceList.SelectedItems.Count == 0) return;

int deviceNumber = sourceList.SelectedItems[0].Index;

recAsio = new NAudio.Wave.AsioOut(deviceNumber);
recAsio.InitRecordAndPlayback(null, 2, 44100); //rec channel = 1

NAudio.Wave.WaveFormat formato = new NAudio.Wave.WaveFormat();
buffer = new NAudio.Wave.BufferedWaveProvider(formato);

recAsio.AudioAvailable += new EventHandler<NAudio.Wave.AsioAudioAvailableEventArgs>(OnAudioAvailable);

//Collego l'output col buffer
playAsio = new NAudio.Wave.AsioOut(deviceNumber);
playAsio.Init(buffer);

//Registro
recAsio.Play();
//Playback
playAsio.Play();

OnAudioAvailable():

//Callback
private unsafe void OnAudioAvailable(object sender, NAudio.Wave.AsioAudioAvailableEventArgs e)
{
    //Copio tutti gli elementi di InputBuffers in buf e li aggiungo in coda al buffer
    byte[] buf = new byte[e.SamplesPerBuffer];
    for (int i = 0; i < e.InputBuffers.Length; i++)
    {
        Marshal.Copy(e.InputBuffers[i], buf, 0, e.SamplesPerBuffer);
        //Aggiungo in coda al buffer
        buffer.AddSamples(buf, 0, buf.Length);
    }
}

AsioAudioAvailableEventArgs 定义:

public AsioAudioAvailableEventArgs(IntPtr[] inputBuffers, int samplesPerBuffer, AsioSampleType asioSampleType);
public float[] GetAsInterleavedSamples();

有人知道如何解决吗? 谢谢大家。

c# audio-recording playback naudio asio
2个回答
3
投票

您不应在同一设备上使用两个

AsioOut
实例。我很惊讶这竟然有效。只需使用带有
InitRecordAndPlayback
的那个即可。

为了实现直通监控的绝对最小延迟,请在

AudioAvailableEvent
中,直接复制到
OutputBuffers
,然后设置
WrittenToOutputBuffers = true
。这意味着您不需要
BufferedWaveProvider

还请记住,任何故障都只是由于您未能足够快地处理 AudioAvailable 事件造成的。当您使用 ASIO 时,您可以处于非常低的延迟(例如低于 10 毫秒),并且可以处理大量数据(例如 96kHz 采样率、8 个输入和输出通道)。因此,您需要在短时间内进行大量数据移动。使用 .NET,您必须考虑到一个不幸的事实,即垃圾收集器可能随时启动并导致您不时错过缓冲区。


0
投票

有人解决了吗?我也在做同样的事情,但我在音频输出处听不到任何声音。

我尝试使用 Marshal.Copy

 Marshal.Copy(e.InputBuffers[0], e.OutputBuffers, 0, e.InputBuffers.Length);

但是,不起作用

© www.soinside.com 2019 - 2024. All rights reserved.