如何使用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
实例。我很惊讶这竟然有效。就用带InitRecordAndPlayback
的那个。
对于直通监视的绝对最小延迟,在AudioAvailableEvent
中,直接复制到OutputBuffers
,并设置WrittenToOutputBuffers = true
。这意味着你不需要BufferedWaveProvider
。
还要记住,任何故障都只是由于您没有足够快地处理AudioAvailable事件。当您使用ASIO时,您可以在非常低的延迟(例如低于10ms),并且可以处理大量数据(例如96kHz采样率,8通道输入和输出)。所以你需要在短时间内进行大量的数据移动。对于。net,您必须考虑到一个不幸的事实,即垃圾收集器可能随时启动,并导致您不时错过缓冲区。