流式音频播放的延迟

流式音频播放的延迟

本文介绍了流式音频播放的延迟(大约200毫秒)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  1. 文件头信息(采样率,每个样本的位数和通道数)首先发送.
  2. 基于上述参数初始化音频波形输出设备.
  3. 已发送音频(pcm)数据并在上述设备上播放.

数据接收代码是本机代码(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(默认值为正常"),性能会进一步提高,但是正如预期的那样,该过程开始消耗大量资源.

谢谢

维克拉姆

解决方案

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

每秒捕获10次(一次100毫秒).

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

new DirectSoundOut(guid, 50);

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

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

关于声音的平滑度,还有一些工作要做,但是现在我们通常没有等待时间了.

I have an application which plays the streamed audio data (like a chat client). The workflow involves three simple steps:

  1. The file header info (sample rate, bits per sample and num of channels) is sent first.
  2. Audio waveout device is initialized based on the above parameters.
  3. Audio (pcm) data is sent and is played on the above device.

The data receiving code is native (C code). and it reads data on a socket. Then it calls the managed C# code, which uses Naudio library to initialize device and play audio.

Now the problem is that, I am seeing some delay in audio playback. I have already instrumented the rest of my code (specifically: transferring data on socket and passing it back to managed code) and that seems to be okay. The whole transfer process is taking around 600 micro seconds, but after I assign the buffer to Naudio, it seems to start playing it after some time (around 200-250 milliseconds).

Here is my C# class that handles the audio playing part:

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);
    }
}

Anyone has any idea on what might be causing the delay or am I using it (Naudio) in some wrong way.

I tried the same Naudio library to play a wav file and that seems to work perfect, the problem is coming only when I am adding samples after initialing the device myself.

[update] If I change s_WaveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()); to s_WaveOut = new DirectSound();, the performance is much better. If after this, I modify the Naudio source to set playback thread priority to Highest (default is Normal), the performace improves further, but as expected, the process starts consuming high resources.

Thank you,

Vikram

解决方案

I also develop audio streaming application using NAudio. We also have latency issue. It reaches 300 ms.

The capture happens 10 times per second (once a 100 ms).

Using the advice of Vikram.exe to use DirectSoundOut instead of WaveOut helped a bit. The latency decreased by 50 or 100 ms, but only if I set Desired Latency to 50 ms.

new DirectSoundOut(guid, 50);

One more trick has lowered the latency by 100 or 200 ms. We check if there is a sound being played and skip new frames if it is.

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

There is still some work to be done in regards of sound smoothness, but generally we have no latency now.

这篇关于流式音频播放的延迟(大约200毫秒)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-28 00:32