如何使用AsioOut录制和播放NAudio

本文关键字:播放 NAudio 何使用 AsioOut | 更新日期: 2023-09-27 17:50:47

我正在尝试获得声音输入直接发送输出与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();

有谁知道怎么修理它吗?谢谢大家。

如何使用AsioOut录制和播放NAudio

您不应该在同一设备上使用两个AsioOut实例。我很惊讶这竟然有效。就用带InitRecordAndPlayback的那个。

对于直通监视的绝对最小延迟,在AudioAvailableEvent中,直接复制到OutputBuffers,并设置WrittenToOutputBuffers = true。这意味着你不需要BufferedWaveProvider

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