using System; namespace Opus.Net { /// Opus codec wrapper. public class OpusEncoder : IDisposable { private readonly IntPtr _encoder; /// Gets the bit rate of the encoder. public const int BitRate = 16; /// Gets the input sampling rate of the encoder. public int InputSamplingRate { get; private set; } /// Gets the number of channels of the encoder. public int InputChannels { get; private set; } /// Gets the milliseconds per frame. public int FrameLength { get; private set; } /// Gets the number of samples per frame. public int SamplesPerFrame { get; private set; } /// Gets the bytes per sample. public int SampleSize { get; private set; } /// Gets the bytes per frame. public int FrameSize { get; private set; } /// Gets the coding mode of the encoder. public Application Application { get; private set; } /// Creates a new Opus encoder. /// Sampling rate of the input signal (Hz). Supported Values: 8000, 12000, 16000, 24000, or 48000. /// Number of channels (1 or 2) in input signal. /// Length, in milliseconds, that each frame takes. Supported Values: 2.5, 5, 10, 20, 40, 60 /// Coding mode. /// A new OpusEncoder public OpusEncoder(int samplingRate, int channels, int frameLength, Application application) { if (samplingRate != 8000 && samplingRate != 12000 && samplingRate != 16000 && samplingRate != 24000 && samplingRate != 48000) throw new ArgumentOutOfRangeException("inputSamplingRate"); if (channels != 1 && channels != 2) throw new ArgumentOutOfRangeException("inputChannels"); InputSamplingRate = samplingRate; InputChannels = channels; Application = application; FrameLength = frameLength; SampleSize = (BitRate / 8) * channels; SamplesPerFrame = samplingRate / 1000 * FrameLength; FrameSize = SamplesPerFrame * SampleSize; Error error; _encoder = API.opus_encoder_create(samplingRate, channels, (int)application, out error); if (error != Error.OK) throw new InvalidOperationException("Error occured while creating encoder: " + error.ToString()); SetForwardErrorCorrection(true); } /// Produces Opus encoded audio from PCM samples. /// PCM samples to encode. /// Length of encoded audio. /// Opus encoded audio buffer. public unsafe int EncodeFrame(byte[] pcmSamples, byte[] outputBuffer) { if (disposed) throw new ObjectDisposedException("OpusEncoder"); IntPtr encodedPtr; int length = 0; fixed (byte* bPtr = outputBuffer) { encodedPtr = new IntPtr((void*)bPtr); length = API.opus_encode(_encoder, pcmSamples, SamplesPerFrame, encodedPtr, outputBuffer.Length); } if (length < 0) throw new Exception("Encoding failed: " + ((Error)length).ToString()); return length; } /// Gets or sets whether Forward Error Correction is enabled. public void SetForwardErrorCorrection(bool value) { 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 - " + ((Error)ret).ToString()); } private bool disposed; public void Dispose() { if (disposed) return; GC.SuppressFinalize(this); if (_encoder != IntPtr.Zero) API.opus_encoder_destroy(_encoder); disposed = true; } ~OpusEncoder() { Dispose(); } } }