Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Very simple jitter buffer #54

Merged
merged 6 commits into from
Mar 27, 2020
Merged
79 changes: 56 additions & 23 deletions MumbleSharp/Audio/AudioDecodingBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,55 @@ public AudioDecodingBuffer(int sampleRate = Constants.DEFAULT_AUDIO_SAMPLE_RATE,
}

private long _nextSequenceToDecode;
private readonly List<BufferPacket> _encodedBuffer = new List<BufferPacket>();

private readonly List<BufferPacket> _encodedBuffer = new List<BufferPacket>();
private IVoiceCodec _codec;

public int Read(byte[] buffer, int offset, int count)
{
int readCount = 0;
while (readCount < count)
{
readCount += ReadFromBuffer(buffer, offset + readCount, count - readCount);

//Try to decode some more data into the buffer
if (!FillBuffer())
break;
}
/// <summary>
/// The time, in milliseconds, for the jitter buffer to delay when network data is exhausted. Only updates internally when jitter is detected.
/// </summary>
public TimeSpan JitterDelay { get; set; } = TimeSpan.FromMilliseconds(350f);

if (readCount == 0)
{
//Return silence
Array.Clear(buffer, 0, buffer.Length);
return count;
}
private bool isJitterDetected;
private bool isJitterTimerRunning;
private DateTime jitterTimer = DateTime.UtcNow;
private double jitterMillis = 350f;

return readCount;
public int Read(byte[] buffer, int offset, int count)
{
int readCount = 0;

if (isJitterTimerRunning && ((DateTime.UtcNow - jitterTimer).TotalMilliseconds > jitterMillis))
{
isJitterDetected = false;
isJitterTimerRunning = false;
}

if (!isJitterDetected)
{
while (readCount < count)
{
readCount += ReadFromBuffer(buffer, offset + readCount, count - readCount);

if (readCount == 0)
{
isJitterDetected = true;
}

//Try to decode some more data into the buffer
if (!FillBuffer())
break;
}
}

if (readCount == 0)
{
//Return silence
Array.Clear(buffer, 0, count);
return count;
}

return readCount;
}

/// <summary>
Expand All @@ -68,8 +93,15 @@ public int Read(byte[] buffer, int offset, int count)
/// <param name="data">The encoded audio packet</param>
/// <param name="codec">The codec to use to decode this packet</param>
public void AddEncodedPacket(long sequence, byte[] data, IVoiceCodec codec)
{
if(sequence == 0)
{
if (isJitterDetected && !isJitterTimerRunning)
{
jitterTimer = DateTime.UtcNow;
jitterMillis = JitterDelay.TotalMilliseconds;
isJitterTimerRunning = true;
}

if (sequence == 0)
_nextSequenceToDecode = 0;

if (_codec == null)
Expand All @@ -81,7 +113,8 @@ public void AddEncodedPacket(long sequence, byte[] data, IVoiceCodec codec)
if (_nextSequenceToDecode > sequence)
return;

_encodedBuffer.Add(new BufferPacket {
_encodedBuffer.Add(new BufferPacket
{
Data = data,
Sequence = sequence
});
Expand Down