Skip to content

Audio jitter/choppy echo when returning RTP audio via Channels in echo mode #1474

@tlierdotfr

Description

@tlierdotfr

Hi,

I'm experimenting with a simple SIP server using SIPSorcery 8.0, and I'm currently testing an echo mode to validate the audio path before implementing further audio processing.

The idea is straightforward:

I receive RTP packets from the SIP session (OnRtpPacketReceived handler).

Each packet’s payload (PCMU, 8 kHz, 160 bytes per frame) is written into a Channel<byte[]> for async handling.

A consumer task reads from that channel and sends the same payload back through _rtpSession.SendAudio().

When I inspect the recorded inbound/outbound audio (saved as raw µ-law files), playback in Audacity sounds perfect — so the chunks themselves are correct.

However, during a live SIP call (tested against a 3CX server), the return audio sounds choppy, with jitter and short dropouts.
There’s no transformation of the chunks (no transcoding, no conversion).
Each frame is sent as 160 bytes every ~20 ms, and timing is managed by the consumer task.

I’ve tried variants with and without Task.Delay(20), but adding a delay causes increasing latency, while removing it keeps the audio immediate but still glitchy.

So it looks like the RTP send timing might not be properly synchronized, or that the internal packet scheduling expects a different approach when streaming from custom queues.

Here’s a simplified overview of my pipeline (without any scheduling):

_rtpSession.OnRtpPacketReceived += OnAudioPacketReceived;

private async void OnAudioPacketReceived(IPEndPoint remoteEndPoint, SDPMediaTypesEnum mediaType, RTPPacket packet)
{
    if (mediaType == SDPMediaTypesEnum.audio && packet.Payload?.Length > 0)
        await _incomingFromSipQueue.Writer.WriteAsync(packet.Payload);
}

private async Task ConsumeIncomingFromSipAudio(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        var buffer = await _incomingFromSipQueue.Reader.ReadAsync(token);
        await _outgoingToSipQueue.Writer.WriteAsync(buffer);
    }
}

private async Task ConsumeOutgoingToSipAudio(CancellationToken token)
{
    while (!token.IsCancellationRequested)
    {
        var buffer = await _outgoingToSipQueue.Reader.ReadAsync(token);
        _rtpSession.SendAudio(160, buffer);
    }
}

Has anyone encountered this issue with SendAudio timing or echo loops using Channels?
Is there a recommended way to ensure smoother RTP scheduling when manually pushing audio frames like this?

Thanks in advance for any insights!

Thomas

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions