网上演练贵港万达广场(人员密集)
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.

448 lines
19 KiB

4 years ago
using System;
using System.Runtime.InteropServices;
namespace AX.AudioSystem
{
/// <summary>
/// Opus C API Bindings。具体请参考 http://www.opus-codec.org/docs/。
/// </summary>
internal static class OpusNative
{
#region Opus Encoder
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_encoder_get_size(int channels);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr opus_encoder_create(int Fs, int channels, int application, out int error);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_encoder_init(IntPtr st, int Fs, int channels, int application);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_encode(IntPtr st, short* pcm, int frame_size, byte* data, int max_data_bytes);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_encode_float(IntPtr st, float* pcm, int frame_size, byte* data, int max_data_bytes);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern void opus_encoder_destroy(IntPtr st);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_encoder_ctl(IntPtr st, int request);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_encoder_get_ctl(IntPtr st, int request, out int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_encoder_set_ctl(IntPtr st, int request, int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_encoder_reset(IntPtr st);
public static IntPtr OpusEncoderCreate(SamplingRate Fs, Channel channels, OpusApplication application)
{
var size = opus_encoder_get_size((int)channels);
var intptr = Marshal.AllocHGlobal(size);
var error = opus_encoder_init(intptr, (int)Fs, (int)channels, (int)application);
if (error != (int)OpusErrorCode.OK && intptr != IntPtr.Zero)
{
OpusEncoderDestroy(intptr);
ThrowOpusException(error);
}
return intptr;
}
public static void OpusEncoderDestroy(IntPtr st)
{
Marshal.FreeHGlobal(st);
}
public static int OpusEncode(IntPtr st, short[] pcm, int frame_size, byte[] data)
{
return OpusEncode(st, pcm, 0, frame_size, data);
}
public static unsafe int OpusEncode(IntPtr st, short[] pcm, int pcmOffset, int frame_size, byte[] data)
{
fixed (short* pcmPtr = &pcm[pcmOffset])
fixed (byte* dataPtr = &data[0])
{
var result = opus_encode(st, pcmPtr, frame_size, dataPtr, data.Length);
if (result < 0)
ThrowOpusException(result);
return result;
}
}
public static int OpusEncode(IntPtr st, float[] pcm, int frame_size, byte[] data)
{
return OpusEncode(st, pcm, 0, frame_size, data);
}
public static unsafe int OpusEncode(IntPtr st, float[] pcm, int pcmOffset, int frame_size, byte[] data)
{
fixed (float* pcmPtr = &pcm[pcmOffset])
fixed (byte* dataPtr = &data[0])
{
var result = opus_encode_float(st, pcmPtr, frame_size, dataPtr, data.Length);
if (result < 0)
ThrowOpusException(result);
return result;
}
}
public static int OpusEncoderGetCtl(IntPtr st, OpusEncoderGetRequest request)
{
int result = 0;
var error = opus_encoder_get_ctl(st, (int)request, out result);
if (error != (int)OpusErrorCode.OK)
ThrowOpusException(error);
return result;
}
public static void OpusEncoderSetCtl(IntPtr st, OpusEncoderSetRequest request, int value)
{
var error = opus_encoder_set_ctl(st, (int)request, value);
if (error != (int)OpusErrorCode.OK)
ThrowOpusException(error);
}
public static void OpusEncoderReset(IntPtr st)
{
var error = opus_encoder_reset(st);
if (error != (int)OpusErrorCode.OK)
ThrowOpusException(error);
}
#endregion
#region Opus Decoder
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_get_size(int channels);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr opus_decoder_create(int Fs, int channels, out int error);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_init(IntPtr st, int Fs, int channels);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_decode(IntPtr st, byte* data, int len, short* pcm, int frame_size, int decode_fec);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_decode_float(IntPtr st, byte* data, int len, float* pcm, int frame_size, int decode_fec);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_ctl(IntPtr st, int request);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_get_ctl(IntPtr st, int request, out int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_set_ctl(IntPtr st, int request, int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_reset(IntPtr st);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern void opus_decoder_destroy(IntPtr st);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_packet_parse(byte* data, int len, byte* out_toc, [MarshalAs(UnmanagedType.LPArray, SizeConst = 48)]byte[] frames, [MarshalAs(UnmanagedType.LPArray, SizeConst = 48 * 2)]short[] size, int* payload_offset);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_packet_get_bandwidth(byte[] data);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_packet_get_samples_per_frame(byte[] data, int Fs);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_packet_get_nb_channels(byte[] data);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_packet_get_nb_frames(byte[] packet, int len);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_packet_get_nb_samples(byte[] packet, int len, int Fs);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_decoder_get_nb_samples(IntPtr dec, byte[] packet, int len);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe void opus_pcm_soft_clip(float* pcm, int frame_size, int channels, float* softclip_mem);
public static IntPtr OpusDecoderCreate(SamplingRate Fs, Channel channels)
{
var size = opus_decoder_get_size((int)channels);
var intptr = Marshal.AllocHGlobal(size);
var error = opus_decoder_init(intptr, (int)Fs, (int)channels);
if (error != (int)OpusErrorCode.OK && intptr != IntPtr.Zero)
{
OpusDecoderDestroy(intptr);
ThrowOpusException(error);
}
return intptr;
}
public static void OpusDecoderDestroy(IntPtr st)
{
Marshal.FreeHGlobal(st);
}
public static unsafe int OpusDecode(IntPtr st, byte[] data, short[] pcm, int channels, int decode_fec)
{
if (st == IntPtr.Zero)
throw new ObjectDisposedException("OpusDecoder");
int samplesDecoded = 0;
fixed (short* pcmPtr = &pcm[0])
{
if (data != null)
{
fixed (byte* dataPtr = &data[0])
{
samplesDecoded = opus_decode(st, dataPtr, data.Length, pcmPtr, pcm.Length / channels, decode_fec);
}
}
else
samplesDecoded = opus_decode(st, null, 0, pcmPtr, pcm.Length / channels, decode_fec);
}
if (samplesDecoded == (int)OpusErrorCode.InvalidPacket)
return 0;
if (samplesDecoded <= (int)OpusErrorCode.OK)
ThrowOpusException(samplesDecoded);
return samplesDecoded;
}
public static unsafe int OpusDecode(IntPtr st, byte[] data, float[] pcm, int channels, int decode_fec)
{
if (st == IntPtr.Zero)
throw new ObjectDisposedException("OpusDecoder");
int samplesDecoded = 0;
fixed (float* pcmPtr = &pcm[0])
{
if (data != null)
{
fixed (byte* dataPtr = &data[0])
{
samplesDecoded = opus_decode_float(st, dataPtr, data.Length, pcmPtr, pcm.Length / channels, decode_fec);
}
}
else
samplesDecoded = opus_decode_float(st, null, 0, pcmPtr, pcm.Length / channels, decode_fec);
}
if (samplesDecoded == (int)OpusErrorCode.InvalidPacket)
return 0;
if (samplesDecoded <= (int)OpusErrorCode.OK)
ThrowOpusException(samplesDecoded);
return samplesDecoded;
}
public static int OpusDecoderGetCtl(IntPtr st, OpusDecoderGetRequest request)
{
int result = 0;
var error = opus_decoder_get_ctl(st, (int)request, out result);
if (error != (int)OpusErrorCode.OK)
ThrowOpusException(error);
return result;
}
public static void OpusDecoderSetCtl(IntPtr st, OpusDecoderSetRequest request, int value)
{
var error = opus_decoder_set_ctl(st, (int)request, value);
if (error != (int)OpusErrorCode.OK)
ThrowOpusException(error);
}
public static void OpusDecoderReset(IntPtr st)
{
var error = opus_decoder_reset(st);
if (error != (int)OpusErrorCode.OK)
ThrowOpusException(error);
}
#endregion
#region Repacketizer
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_repacketizer_get_size();
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr opus_repacketizer_init(IntPtr rp);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr opus_repacketizer_create();
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern void opus_repacketizer_destroy(IntPtr rp);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_repacketizer_cat(IntPtr rp, byte* data, int len);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_repacketizer_out_range(IntPtr rp, int begin, int end, byte* data, int maxlen);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_repacketizer_get_nb_frames(IntPtr rp);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_repacketizer_out(IntPtr rp, byte* data, int maxlen);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_packet_pad(byte* data, int len, int new_len);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_packet_unpad(byte* data, int len);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_packet_pad(byte* data, int len, int new_len, int nb_streams);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_packet_unpad(byte* data, int len, int nb_streams);
#endregion
#region Opus Multistream API
#region Multistream encoder functions
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_encoder_get_size(int streams, int coupled_streams);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_surround_encoder_get_size(int channels, int mapping_family);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe IntPtr opus_multistream_encoder_create(int Fs, int channels, int streams, int coupled_streams, byte* mapping, int application, out int error);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe IntPtr opus_multistream_surround_encoder_create(int Fs, int channels, int mapping_family, int* streams, int* coupled_streams, byte* mapping, int application, out int error);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_encoder_init(IntPtr st, int Fs, int channels, int streams, int coupled_streams, byte* mapping, int application);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_surround_encoder_init(IntPtr st, int Fs, int channels, int mapping_family, int* streams, int* coupled_streams, byte* mapping, int application);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_encode(IntPtr st, short* pcm, int frame_size, byte* data, int max_data_bytes);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_encode_float(IntPtr st, float* pcm, int frame_size, byte* data, int max_data_bytes);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern void opus_multistream_encoder_destroy(IntPtr st);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_encoder_ctl(IntPtr st, int request);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_encoder_get_ctl(IntPtr st, int request, out int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_encoder_set_ctl(IntPtr st, int request, int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_encoder_reset(IntPtr st);
#endregion
#region Multistream decoder functions
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_decoder_get_size(int streams, int coupled_streams);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe IntPtr opus_multistream_decoder_create(int Fs, int channels, int streams, int coupled_streams, byte* mapping, out int error);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_decoder_init(IntPtr st, int Fs, int channels, int streams, int coupled_streams, byte* mapping);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_decode(IntPtr st, byte* data, int len, short* pcm, int frame_size, int decode_fec);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern unsafe int opus_multistream_decode_float(IntPtr st, byte* data, int len, float* pcm, int frame_size, int decode_fec);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_decoder_ctl(IntPtr st, int request);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_decoder_get_ctl(IntPtr st, int request, out int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_decoder_set_ctl(IntPtr st, int request, int value);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern int opus_multistream_decoder_reset(IntPtr st);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern void opus_multistream_decoder_destroy(IntPtr st);
#endregion
#endregion
#region Opus library information functions
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr opus_strerror(int error);
[DllImport("opus", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr opus_get_version_string();
public static string OpusStringError(OpusErrorCode errorCode)
{
return Marshal.PtrToStringAnsi(opus_strerror((int)errorCode));
}
public static string OpusGetVersionString()
{
return Marshal.PtrToStringAnsi(opus_get_version_string());
}
#endregion
#region Opus Custom
#endregion
#region Others
public static void ThrowOpusException(int error)
{
throw new OpusException((OpusErrorCode)error, OpusStringError((OpusErrorCode)error));
}
#endregion
}
}