Added Opus.Net, fixed public IP method, starting to add outgoing voice support.

This commit is contained in:
Brandon Smith
2015-08-24 02:44:42 -03:00
parent a80355699a
commit 32565efa5c
11 changed files with 685 additions and 60 deletions

198
src/Opus.Net/OpusEncoder.cs Normal file
View File

@@ -0,0 +1,198 @@
using System;
namespace Opus.Net
{
/// <summary>
/// Opus codec wrapper.
/// </summary>
public class OpusEncoder : IDisposable
{
/// <summary>
/// Creates a new Opus encoder.
/// </summary>
/// <param name="inputSamplingRate">Sampling rate of the input signal (Hz). This must be one of 8000, 12000, 16000, 24000, or 48000.</param>
/// <param name="inputChannels">Number of channels (1 or 2) in input signal.</param>
/// <param name="application">Coding mode.</param>
/// <returns>A new <c>OpusEncoder</c></returns>
public static OpusEncoder Create(int inputSamplingRate, int inputChannels, Application application)
{
if (inputSamplingRate != 8000 &&
inputSamplingRate != 12000 &&
inputSamplingRate != 16000 &&
inputSamplingRate != 24000 &&
inputSamplingRate != 48000)
throw new ArgumentOutOfRangeException("inputSamplingRate");
if (inputChannels != 1 && inputChannels != 2)
throw new ArgumentOutOfRangeException("inputChannels");
IntPtr error;
IntPtr encoder = API.opus_encoder_create(inputSamplingRate, inputChannels, (int)application, out error);
if ((Errors)error != Errors.OK)
{
throw new Exception("Exception occured while creating encoder");
}
return new OpusEncoder(encoder, inputSamplingRate, inputChannels, application);
}
private IntPtr _encoder;
private OpusEncoder(IntPtr encoder, int inputSamplingRate, int inputChannels, Application application)
{
_encoder = encoder;
InputSamplingRate = inputSamplingRate;
InputChannels = inputChannels;
Application = application;
MaxDataBytes = 4000;
}
/// <summary>
/// Produces Opus encoded audio from PCM samples.
/// </summary>
/// <param name="inputPcmSamples">PCM samples to encode.</param>
/// <param name="sampleLength">How many bytes to encode.</param>
/// <param name="encodedLength">Set to length of encoded audio.</param>
/// <returns>Opus encoded audio buffer.</returns>
public unsafe byte[] Encode(byte[] inputPcmSamples, int sampleLength, out int encodedLength)
{
if (disposed)
throw new ObjectDisposedException("OpusEncoder");
int frames = FrameCount(inputPcmSamples);
IntPtr encodedPtr;
byte[] encoded = new byte[MaxDataBytes];
int length = 0;
fixed (byte* benc = encoded)
{
encodedPtr = new IntPtr((void*)benc);
length = API.opus_encode(_encoder, inputPcmSamples, frames, encodedPtr, sampleLength);
}
encodedLength = length;
if (length < 0)
throw new Exception("Encoding failed - " + ((Errors)length).ToString());
return encoded;
}
/// <summary>
/// Determines the number of frames in the PCM samples.
/// </summary>
/// <param name="pcmSamples"></param>
/// <returns></returns>
public int FrameCount(byte[] pcmSamples)
{
// seems like bitrate should be required
int bitrate = 16;
int bytesPerSample = (bitrate / 8) * InputChannels;
return pcmSamples.Length / bytesPerSample;
}
/// <summary>
/// Helper method to determine how many bytes are required for encoding to work.
/// </summary>
/// <param name="frameCount">Target frame size.</param>
/// <returns></returns>
public int FrameByteCount(int frameCount)
{
int bitrate = 16;
int bytesPerSample = (bitrate / 8) * InputChannels;
return frameCount * bytesPerSample;
}
/// <summary>
/// Gets the input sampling rate of the encoder.
/// </summary>
public int InputSamplingRate { get; private set; }
/// <summary>
/// Gets the number of channels of the encoder.
/// </summary>
public int InputChannels { get; private set; }
/// <summary>
/// Gets the coding mode of the encoder.
/// </summary>
public Application Application { get; private set; }
/// <summary>
/// Gets or sets the size of memory allocated for reading encoded data.
/// 4000 is recommended.
/// </summary>
public int MaxDataBytes { get; set; }
/// <summary>
/// Gets or sets the bitrate setting of the encoding.
/// </summary>
public int Bitrate
{
get
{
if (disposed)
throw new ObjectDisposedException("OpusEncoder");
int bitrate;
var ret = API.opus_encoder_ctl(_encoder, Ctl.GetBitrateRequest, out bitrate);
if (ret < 0)
throw new Exception("Encoder error - " + ((Errors)ret).ToString());
return bitrate;
}
set
{
if (disposed)
throw new ObjectDisposedException("OpusEncoder");
var ret = API.opus_encoder_ctl(_encoder, Ctl.SetBitrateRequest, value);
if (ret < 0)
throw new Exception("Encoder error - " + ((Errors)ret).ToString());
}
}
/// <summary>
/// Gets or sets whether Forward Error Correction is enabled.
/// </summary>
public bool ForwardErrorCorrection
{
get
{
if (_encoder == IntPtr.Zero)
throw new ObjectDisposedException("OpusEncoder");
int fec;
int ret = API.opus_encoder_ctl(_encoder, Ctl.GetInbandFECRequest, out fec);
if (ret < 0)
throw new Exception("Encoder error - " + ((Errors)ret).ToString());
return fec > 0;
}
set
{
if (_encoder == IntPtr.Zero)
throw new ObjectDisposedException("OpusEncoder");
var ret = API.opus_encoder_ctl(_encoder, Ctl.SetInbandFECRequest, value ? 1 : 0);
if (ret < 0)
throw new Exception("Encoder error - " + ((Errors)ret).ToString());
}
}
~OpusEncoder()
{
Dispose();
}
private bool disposed;
public void Dispose()
{
if (disposed)
return;
GC.SuppressFinalize(this);
if (_encoder != IntPtr.Zero)
{
API.opus_encoder_destroy(_encoder);
_encoder = IntPtr.Zero;
}
disposed = true;
}
}
}