流式音频播放延迟(约200 ms)

时间:2011-12-28 11:27:39

标签: c# optimization instrumentation naudio

我有一个播放流式音频数据的应用程序(如聊天客户端)。工作流程包括三个简单的步骤:

  1. 首先发送文件头信息(采样率,每个样本的比特数和通道数)。
  2. 根据以上参数初始化音频波形设备。
  3. 发送音频(pcm)数据并在上述设备上播放。
  4. 数据接收代码是本机(C代码)。它读取套接字上的数据。然后它调用托管C#代码,该代码使用Naudio库初始化设备并播放音频。

    现在的问题是,我看到音频播放有些延迟。我已经检测了我的其余代码(特别是:在套接字上传输数据并将其传递回托管代码),这似乎没问题。整个传输过程大约需要600微秒,但在我将缓冲区分配给Naudio之后,它似乎在一段时间后(大约200-250毫秒)开始播放。

    这是我的C#类处理音频播放部分:

    class foo
    {
        static  IWavePlayer     s_WaveOut;
        static  WaveFormat      s_WaveOutFormat;
        static  BufferedWaveProvider    s_WaveProvider;
        static  byte[]          s_Samples       = new byte[10000];
    
        // called from native code to init deivce with specified sample rate and num of channels
        private static void DeviceInit(int rate, int bits, int channels)
        {
            s_WaveOut   = new WaveOut(WaveCallbackInfo.FunctionCallback());
            s_WaveOutFormat = new WaveFormat(rate, bits, channels);
            s_WaveProvider  = new BufferedWaveProvider(s_WaveOutFormat);
    
            s_WaveProvider.DiscardOnBufferOverflow      = true;
            s_WaveProvider.BufferLength         = 5 * 1024 * 1024;
    
            s_WaveOut.Init(s_WaveProvider);
            s_WaveOut.Play();
        }
    
        // called from native 'C' code upon receiving audio packates
        private unsafe static void PlayDataCallback(
            IntPtr buff,
            Int32 size) 
        {
            Marshal.Copy(buff, s_Samples, 0, size);
            s_WaveProvider.AddSamples(s_Samples, 0, size);
        }
    }
    

    任何人都知道可能导致延迟的原因或我是否以错误的方式使用它(Naudio)。

    我尝试使用相同的Naudio库来播放wav文件,这似乎工作得很完美,只有在我自己初始化设备后添加样本时才会出现问题。

    [更新] 如果我将s_WaveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());更改为s_WaveOut = new DirectSound();,效果会更好。如果在此之后,我修改Naudio源以将回放线程优先级设置为Highest(默认为正常),性能进一步提高,但正如预期的那样,该过程开始消耗大量资源。

    谢谢,

    维克拉姆

2 个答案:

答案 0 :(得分:2)

音频播放总会引入延迟。对于WaveOut,您可以指定缓冲区的数量和总体所需的延迟。您也可以为其他驱动程序模型指定缓冲区大小。对于大多数播放场景,两个100ms的缓冲区都是理想的,因为它具有合理的响应速度,除极端负载外不会断断续续。但是,如果需要,可以降低,但要冒着无法及时填充下一个缓冲区的风险。不要期望与Nudio一样的低延迟(例如5ms),它没有那么高度优化,并且由于垃圾收集器,.NET框架无论如何都不是特别适合这种应用程序。

以下是设置WaveOut的输出延迟的示例:

var waveOut = new WaveOut();
waveout.DesiredLatency = 50; // 50ms latency

答案 1 :(得分:2)

我还使用NAudio开发音频流应用程序。我们也有延迟问题。它达到300毫秒。

捕获每秒发生10次(一次100毫秒)。

使用Vikram.exe的建议来使用DirectSoundOut代替WaveOut有所帮助。延迟减少了50或100毫秒,但前提是我将Desired Latency设置为50毫秒。

new DirectSoundOut(guid, 50);

另一个技巧是将延迟降低了100或200毫秒。我们检查是否有正在播放的声音并跳过新帧。

if (s_WaveProvider.BufferedDuration <= 100)
    s_WaveProvider.AddSamples(s_Samples, 0, size);

在声音平滑性方面还有一些工作要做,但一般来说我们现在没有延迟。