Задержка (около 200 мс) при воспроизведении потокового аудио - PullRequest
4 голосов
/ 28 декабря 2011

У меня есть приложение, которое воспроизводит потоковые аудиоданные (например, чат-клиент). Рабочий процесс состоит из трех простых шагов:

  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 для воспроизведения файла wav, и это, кажется, работает идеально, проблема возникает только тогда, когда я добавляю сэмплы после инициализации устройства самостоятельно.

[обновление] Если я изменю s_WaveOut = new WaveOut(WaveCallbackInfo.FunctionCallback()); на s_WaveOut = new DirectSound();, производительность будет намного лучше. Если после этого я изменю источник Naudio для установки приоритета потока воспроизведения на Highest (по умолчанию - Normal), производительность улучшится еще больше, но, как и ожидалось, процесс начнет потреблять большие ресурсы.

Спасибо,

Викрам

Ответы [ 2 ]

2 голосов
/ 21 сентября 2012

Я также разрабатываю приложение для потоковой передачи аудио с использованием 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);

Еще предстоит проделать определенную работу в отношении плавности звука, но обычно у нас нет задержки.

2 голосов
/ 30 декабря 2011

При воспроизведении аудио всегда присутствует задержка. Для WaveOut вы можете указать количество буферов и общую желаемую задержку. Вы также можете указать размеры буфера для других моделей драйверов. Для большинства сценариев воспроизведения идеально подходит два буфера по 100 мс каждый, так как он достаточно чувствителен и не заикается, кроме как при экстремальной нагрузке. Тем не менее, вы можете пойти ниже, если вам нужно, но рискуете быть не в состоянии заполнить следующий буфер вовремя. Не ожидайте таких низких задержек, как вы могли бы получить в DAW (например, 5 мс) с NAudio, он не настолько оптимизирован, и платформа .NET в любом случае не особенно подходит для такого типа приложений из-за сборщика мусора.

Вот пример установки задержки вывода для WaveOut:

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