using System; namespace AX.AudioSystem { public class OpusEncoder : IDisposable { public const int BitrateMax = -1; private IntPtr handle = IntPtr.Zero; private int frameSize; /// /// 建议最大编码包的大小。 /// public const int PacketMaxSize = 4000; /// /// 获得每通道的帧大小。 /// public int FrameSize { get { return frameSize; } } public SamplingRate SamplingRate { get { return (SamplingRate)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.SampleRate); } } public OpusComplexity Complexity { get { return (OpusComplexity)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.Complexity); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.Complexity, (int)value); } } public int Bitrate { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.Bitrate); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.Bitrate, value); } } public bool VBR { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.VBR) == 1; } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.VBR, value ? 1 : 0); } } public bool VBRConstraint { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.VBRConstraint) == 1; } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.VBRConstraint, value ? 1 : 0); } } public ForceChannels ForceChannels { get { return (ForceChannels)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.ForceChannels); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.ForceChannels, (int)value); } } public OpusBandwidth MaxBandwidth { get { return (OpusBandwidth)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.MaxBandwidth); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.MaxBandwidth, (int)value); } } public OpusBandwidth Bandwidth { get { return (OpusBandwidth)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.Bandwidth); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.Bandwidth, (int)value); } } public OpusSignal Signal { get { return (OpusSignal)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.Signal); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.Signal, (int)value); } } public OpusApplication Application { get { return (OpusApplication)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.Application); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.Application, (int)value); } } public int FinalRange { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.FinalRange); } } public int LookAhead { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.LookAhead); } } public bool InbandFec { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.InbandFec) == 1; } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.InbandFec, value ? 1 : 0); } } public int PacketLossPercentage { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.PacketLossPercentage); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.PacketLossPercentage, value); } } public bool Dtx { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.Dtx) == 1; } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.Dtx, value ? 1 : 0); } } public int LsbDepth { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.LsbDepth); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.LsbDepth, value); } } public OpusFrameSize ExpertFrameDuration { get { return (OpusFrameSize)OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.ExpertFrameDuration); } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.LsbDepth, (int)value); } } public bool PredictionDisabled { get { return OpusNative.OpusEncoderGetCtl(handle, OpusEncoderGetRequest.PredictionDisabled) == 1; } set { OpusNative.OpusEncoderSetCtl(handle, OpusEncoderSetRequest.PredictionDisabled, value ? 1 : 0); } } public OpusEncoder(SamplingRate samplingRate, Channel channels) : this(samplingRate, channels, 30000, OpusApplication.Voip, Delay.Delay20ms) { } public OpusEncoder(SamplingRate samplingRate, Channel channels, int bitrate) : this(samplingRate, channels, bitrate, OpusApplication.Voip, Delay.Delay20ms) { } public OpusEncoder(SamplingRate samplingRate, Channel channels, int bitrate, OpusApplication application) : this(samplingRate, channels, bitrate, application, Delay.Delay20ms) { } public OpusEncoder(SamplingRate samplingRate, Channel channels, int bitrate, OpusApplication application, Delay delay) { if (samplingRate != SamplingRate.Sampling08000 && samplingRate != SamplingRate.Sampling12000 && samplingRate != SamplingRate.Sampling16000 && samplingRate != SamplingRate.Sampling24000 && samplingRate != SamplingRate.Sampling48000) throw new ArgumentOutOfRangeException("samplingRate"); if (channels != Channel.Mono && channels != Channel.Stereo) throw new ArgumentOutOfRangeException("channels"); if (application != OpusApplication.Audio && application != OpusApplication.Voip && application != OpusApplication.RestrictedLowDelay) throw new ArgumentOutOfRangeException("application"); if (delay != Delay.Delay2_5ms && delay != Delay.Delay5ms && delay != Delay.Delay10ms && delay != Delay.Delay20ms && delay != Delay.Delay40ms && delay != Delay.Delay60ms && delay != Delay.Delay80ms && delay != Delay.Delay100ms && delay != Delay.Delay120ms) throw new ArgumentOutOfRangeException("delay"); handle = OpusNative.OpusEncoderCreate(samplingRate, channels, application); Bitrate = bitrate; var sampling = (int)samplingRate; switch (delay) { case Delay.Delay2_5ms: frameSize = sampling / 400; break; case Delay.Delay5ms: frameSize = sampling / 200; break; case Delay.Delay10ms: frameSize = sampling / 100; break; case Delay.Delay20ms: frameSize = sampling / 50; break; case Delay.Delay40ms: frameSize = sampling / 25; break; case Delay.Delay60ms: frameSize = 3 * sampling / 50; break; case Delay.Delay80ms: frameSize = 4 * sampling / 50; break; case Delay.Delay100ms: frameSize = 5 * sampling / 50; break; case Delay.Delay120ms: frameSize = 6 * sampling / 50; break; default: break; } } public void Dispose() { if (handle != IntPtr.Zero) { OpusNative.OpusEncoderDestroy(handle); handle = IntPtr.Zero; } } public void Reset() { OpusNative.OpusEncoderReset(handle); } public int Encode(short[] pcmSamples, byte[] data) { return OpusNative.OpusEncode(handle, pcmSamples, frameSize, data); } public int Encode(float[] pcmSamples, byte[] data) { return OpusNative.OpusEncode(handle, pcmSamples, frameSize, data); } } }