Skip to content

Commit

Permalink
Pass encoder to VoIPMediaSession audio extras (#1015)
Browse files Browse the repository at this point in the history
Currently audio extras in VoIPMediaSession use AudioEncoder for encoding
audio extras. It leads to problems if we are using custom encoder:
AudioEncoder.EncodeAudio method throws an exception because of unsupported
audio format. So we need a way to inject a custom encoder for
VoIPMediaSession audio extras.

Co-authored-by: name <[email protected]>
  • Loading branch information
ynborokh and name authored Dec 10, 2023
1 parent 73d24e1 commit d87b256
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 32 deletions.
30 changes: 2 additions & 28 deletions src/app/Media/Codecs/AudioEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,36 +176,10 @@ public short[] DecodeAudio(byte[] encodedSample, AudioFormat format)
}
}

[Obsolete("No longer used. Use SIPSorcery.Media.PcmResampler.Resample instead.")]
public short[] Resample(short[] pcm, int inRate, int outRate)
{
if (inRate == outRate)
{
return pcm;
}
else if (inRate == 8000 && outRate == 16000)
{
// Crude up-sample to 16Khz by doubling each sample.
return pcm.SelectMany(x => new short[] { x, x }).ToArray();
}
else if (inRate == 8000 && outRate == 48000)
{
// Crude up-sample to 48Khz by 6x each sample. This sounds bad, use for testing only.
return pcm.SelectMany(x => new short[] { x, x, x, x, x, x }).ToArray();
}
else if (inRate == 16000 && outRate == 8000)
{
// Crude down-sample to 8Khz by skipping every second sample.
return pcm.Where((x, i) => i % 2 == 0).ToArray();
}
else if (inRate == 16000 && outRate == 48000)
{
// Crude up-sample to 48Khz by 3x each sample. This sounds bad, use for testing only.
return pcm.SelectMany(x => new short[] { x, x, x }).ToArray();
}
else
{
throw new ApplicationException($"Sorry don't know how to re-sample PCM from {inRate} to {outRate}. Pull requests welcome!");
}
return PcmResampler.Resample(pcm, inRate, outRate);
}
}
}
40 changes: 40 additions & 0 deletions src/app/Media/Codecs/PcmResampler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;
using System.Linq;

namespace SIPSorcery.Media
{
internal static class PcmResampler
{
public static short[] Resample(short[] pcm, int inRate, int outRate)
{
if (inRate == outRate)
{
return pcm;
}
else if (inRate == 8000 && outRate == 16000)
{
// Crude up-sample to 16Khz by doubling each sample.
return pcm.SelectMany(x => new short[] { x, x }).ToArray();
}
else if (inRate == 8000 && outRate == 48000)
{
// Crude up-sample to 48Khz by 6x each sample. This sounds bad, use for testing only.
return pcm.SelectMany(x => new short[] { x, x, x, x, x, x }).ToArray();
}
else if (inRate == 16000 && outRate == 8000)
{
// Crude down-sample to 8Khz by skipping every second sample.
return pcm.Where((x, i) => i % 2 == 0).ToArray();
}
else if (inRate == 16000 && outRate == 48000)
{
// Crude up-sample to 48Khz by 3x each sample. This sounds bad, use for testing only.
return pcm.SelectMany(x => new short[] { x, x, x }).ToArray();
}
else
{
throw new ApplicationException($"Sorry don't know how to re-sample PCM from {inRate} to {outRate}. Pull requests welcome!");
}
}
}
}
6 changes: 3 additions & 3 deletions src/app/Media/Sources/AudioExtrasSource.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public class AudioExtrasSource : IAudioSource
private bool _isStarted;
private bool _isPaused;
private bool _isClosed;
private AudioEncoder _audioEncoder;
private IAudioEncoder _audioEncoder;

// Fields for interrupting the main audio source with a different stream. For example playing
// an announcement over music etc.
Expand Down Expand Up @@ -173,7 +173,7 @@ public int AudioSamplePeriodMilliseconds
/// <param name="audioOptions">Optional. The options that determine the type of audio to stream to the remote party.
/// Example type of audio sources are music, silence, white noise etc.</param>
public AudioExtrasSource(
AudioEncoder audioEncoder,
IAudioEncoder audioEncoder,
AudioSourceOptions audioOptions = null)
{
_audioEncoder = audioEncoder;
Expand Down Expand Up @@ -546,7 +546,7 @@ private void EncodeAndSend(short[] pcm, int pcmSampleRate)
{
if (pcmSampleRate != _audioFormatManager.SelectedFormat.ClockRate)
{
pcm = _audioEncoder.Resample(pcm, pcmSampleRate, _audioFormatManager.SelectedFormat.ClockRate);
pcm = PcmResampler.Resample(pcm, pcmSampleRate, _audioFormatManager.SelectedFormat.ClockRate);
}

byte[] encodedSample = _audioEncoder.EncodeAudio(pcm, _audioFormatManager.SelectedFormat);
Expand Down
2 changes: 1 addition & 1 deletion src/app/Media/VoIPMediaSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public VoIPMediaSession(VoIPMediaSessionConfig config)
Media = config.MediaEndPoint;

// The audio extras source is used for on-hold music.
_audioExtrasSource = new AudioExtrasSource();
_audioExtrasSource = new AudioExtrasSource(config.AudioExtrasEncoder);
_audioExtrasSource.OnAudioSourceEncodedSample += SendAudio;

// Wire up the audio and video sample event handlers.
Expand Down
2 changes: 2 additions & 0 deletions src/app/Media/VoIPMediaSessionConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,7 @@ public sealed class VoIPMediaSessionConfig
public VideoTestPatternSource TestPatternSource { get; set; }

public PortRange RtpPortRange { get; set; }

public IAudioEncoder AudioExtrasEncoder { get; set; } = new AudioEncoder();
}
}

0 comments on commit d87b256

Please sign in to comment.