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);
}
}
}