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
4 years ago
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|