Stottern bei der Audiowiedergabe mit NAudio und Opus nur bei Verbindung über das NetzwerkC#

Ein Treffpunkt für C#-Programmierer
Guest
 Stottern bei der Audiowiedergabe mit NAudio und Opus nur bei Verbindung über das Netzwerk

Post by Guest »

Ich habe ein Problem, bei dem die Audiowiedergabe beim Durchlaufen des Netzwerks (auch bekannt als mein VPS) stottert/jittert, nicht jedoch, wenn dasselbe, sondern lokal ausgeführt wird.
Ich gehe davon aus, dass es etwas mit der Wiedergabe zu tun hat Geschwindigkeit oder Pufferung, aber ich versuche seit ein paar Wochen, das Problem zu beheben, und finde keine Lösung.
Ich habe versucht, mir öffentliche Repositorys anzusehen, die etwas Ähnliches tun, aber ich bin nicht technisch genug, um sie zu verstehen Prozess.
So wird die Wiedergabe initialisiert, wenn die App startet:

Code: Select all

public static void Initialize()
{
waveProvider = new BufferedWaveProvider(new WaveFormat(48000, 1))
{
BufferDuration = TimeSpan.FromSeconds(5),
DiscardOnBufferOverflow = false
};
waveOut = new WaveOutEvent();
waveOut.Init(waveProvider);
}
Ich empfange dann Pakete aus dem Netzwerk und füge sie dieser JitterBuffer-Klasse hinzu:

Code: Select all

public class JitterBuffer(int maxBufferSize)
{
private readonly SortedDictionary buffer = [];
private readonly int maxBufferSize = maxBufferSize;

public void AddFrame(short[] frame, int sequenceNumber)
{
if (buffer.Count >= maxBufferSize)
{
buffer.Remove(buffer.Keys.First()); // Remove the oldest frame if the buffer is full
}
buffer[sequenceNumber] = frame;
}

public short[]? GetFrame()
{
if (buffer.Count > 0)
{
var firstKey = buffer.Keys.First();
var firstValue = buffer[firstKey];
buffer.Remove(firstKey);
return firstValue;
}

// Return null if the buffer is empty
return null;
}

public int BufferSize => buffer.Count;
}
Beachten Sie, dass die Jitter-Puffergröße hier 100 ms beträgt.
Und so erhalte ich Frames von diesem JitterBuffer, um sie einem BufferedWaveProvider hinzuzufügen:

Code: Select all

public static void PlayFromBuffer(object? state)
{
short[]? frame = jitterBuffer.GetFrame();
if (frame != null)
{
byte[] byteBuffer = new byte[frame.Length * sizeof(short)];
Buffer.BlockCopy(frame, 0, byteBuffer, 0, byteBuffer.Length);
waveProvider.AddSamples(byteBuffer, 0, byteBuffer.Length);
}
}
Diese PlayFromBuffer-Methode wird alle 20 ms mithilfe eines Timers aufgerufen, der immer dann gestartet wird, wenn der Benutzer eine Taste drückt, um die Wiedergabe zu starten.
Außerdem Wenn es relevant ist, nehme ich das Audio folgendermaßen auf:

Code: Select all

public static void Initialize()
{
waveIn = new WaveInEvent
{
DeviceNumber = 0, // Use default recording device
WaveFormat = new WaveFormat(48000, 1)
};
waveIn.DataAvailable += OnDataAvailable;
waveIn.RecordingStopped += WaveIn_RecordingStopped;
}

// waveIn.StartRecording is called in a separate method

private static void OnDataAvailable(object? sender, WaveInEventArgs a)
{
// Convert buffer to short PCM samples and accumulate
short[] pcmBuffer = new short[a.BytesRecorded / 2];
Buffer.BlockCopy(a.Buffer, 0, pcmBuffer, 0, a.BytesRecorded);
pcmAccumulationBuffer.AddRange(pcmBuffer);

// This method calls Opus to encode then packages it into a packet and is sent to the server
AudioCodec.Process(pcmAccumulationBuffer);
}
Jede Hilfe ist willkommen.

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post