Я получаю данные локально от 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()
Как разрешить это исключение?