Как воспроизвести аудиопоток из пакетов UDP с помощью NAudio? - PullRequest
1 голос
/ 26 мая 2020

Я получаю данные локально от Voicemeeter, который использует протокол VBAN для отправки потока байтов.

Я пытаюсь использовать NAudio для декодирования байтов и воспроизведения звука с помощью WaveOutEvent. Моя реализация почти такая же, как The NetworkChatDemo из NAudioDemo, проверьте эту ссылку , чтобы узнать больше о NAudio, это отличная аудио библиотека, огромное спасибо Марку Хиту.

Моя реализация:

private readonly ILogger<AudioController> _logger;
        private NetworkAudioPlayer player;
        private readonly INetworkChatCodec _codec;


        public AudioController(ILogger<AudioController> logger)
        {
            _logger = logger;
            _codec = new ALawChatCodec();
        }

        [HttpGet]
        [Route("start")]
        public IActionResult Start()
        {

            var receiver = new UdpAudioReceiver(6980);
            player = new NetworkAudioPlayer(_codec, receiver);

            return Ok("Hello");
        }

Сетевой аудиоплеер:

private readonly INetworkChatCodec codec;
    private readonly IAudioReceiver receiver;
    private readonly IWavePlayer waveOut;
    private readonly BufferedWaveProvider waveProvider;

    public NetworkAudioPlayer(INetworkChatCodec codec, IAudioReceiver receiver)
    {
        this.codec = codec;
        this.receiver = receiver;
        receiver.OnReceived(OnDataReceived);

        waveOut = new WaveOutEvent();
        waveProvider = new BufferedWaveProvider(codec.RecordFormat);
        waveProvider.BufferDuration = TimeSpan.FromSeconds(300);
        waveOut.Init(waveProvider);
        waveOut.Play();
    }

    void OnDataReceived(byte[] compressed)
    {
        byte[] decoded = codec.Decode(compressed, 0, compressed.Length);
        waveProvider.AddSamples(decoded, 0, decoded.Length);
    }

    public void Dispose()
    {
        receiver?.Dispose();
        waveOut?.Dispose();
    }

У меня две проблемы в этой реализации:

  • Во-первых, я не могу установить BufferDuration на бесконечное значение, так как это прямой поток.
  • Во-вторых, я ничего не слышу, кроме шума.

Как установить BufferDuration на бесконечность?
Как сделать правильно воспроизводить звук?

Обновление: мне удалось решить первую проблему, установив значение DiscardOnBufferOverflow для bufferPorivider равным true.

Что касается проблемы с шумом, я нашел решение из этого вопроса , Марк Хит упомянул

Кроме того, вы уверены, что нет окружающих метаданные в получаемых сетевых пакетах? Если да, то это нужно удалить, иначе возникнет шум.

Итак, я изменил значение смещения при добавлении образцов в BufferProvider, чтобы оно было равно 28, что вызывает исключение:

  void OnDataReceived(byte[] compressed)
        {
            var l = compressed.Length;
            waveProvider.AddSamples(compressed, 28, compressed.Length);
        }

Трассировка стека:

    > 
> System.ArgumentException
  HResult=0x80070057
  Message=Source array was not long enough. Check the source index, length, and the array's lower bounds. (Parameter 'sourceArray')
  Source=System.Private.CoreLib
  StackTrace:
   at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length, Boolean reliable)
   at System.Array.Copy(Array sourceArray, Int32 sourceIndex, Array destinationArray, Int32 destinationIndex, Int32 length)
   at NAudio.Utils.CircularBuffer.Write(Byte[] data, Int32 offset, Int32 count)
   at NAudio.Wave.BufferedWaveProvider.AddSamples(Byte[] buffer, Int32 offset, Int32 count)
   at POC.AudioStreaming.AudioManagers.NetworkAudioPlayer.OnDataReceived(Byte[] compressed) in C:\dev\POC.AudioStreaming\POC.AudioStreaming\AudioManagers\NetworkAudioPlayer.cs:line 41
   at POC.AudioStreaming.AudioManagers.UdpAudioReceiver.ListenerThread(Object state) in C:\dev\POC.AudioStreaming\POC.AudioStreaming\AudioManagers\UdpAudioReceiver.cs:line 38
   at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
   at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()

Как разрешить это исключение?

1 Ответ

0 голосов
/ 27 мая 2020

Я решил исключение, используя функцию Skip для обрезки первых 28 байтов из полученных пакетов:

 void OnDataReceived(byte[] compressed)
    {
        byte[] buffer = compressed.Skip(28).ToArray();
        waveProvider.AddSamples(buffer, 0, buffer.Length);
    }

Решив исключение, я смог очень хорошо слышать звук. Также я ответил на свой вопрос.

...