You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
8.7 KiB
235 lines
8.7 KiB
using System; |
|
|
|
namespace AX.AudioSystem |
|
{ |
|
public class OpusEncoder : IDisposable |
|
{ |
|
public const int BitrateMax = -1; |
|
|
|
private IntPtr handle = IntPtr.Zero; |
|
private int frameSize; |
|
|
|
/// <summary> |
|
/// 建议最大编码包的大小。 |
|
/// </summary> |
|
public const int PacketMaxSize = 4000; |
|
|
|
/// <summary> |
|
/// 获得每通道的帧大小。 |
|
/// </summary> |
|
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); |
|
} |
|
} |
|
} |