using System;
|
using System.Collections;
|
using System.Collections.Generic;
|
using System.Runtime.InteropServices;
|
using UnityOpus;
|
|
public static class OpusNative
|
{
|
#if UNITY_ANDROID || UNITY_EDITOR || UNITY_STANDALONE
|
const int frameSize = 160;
|
static readonly byte[] encodeBuffer = new byte[frameSize * 4];
|
static readonly List<short> sampleList = new List<short>();
|
static readonly List<byte> encodedByteList = new List<byte>();
|
|
static readonly short[] decodedBuffer = new short[Decoder.maximumPacketDuration];
|
static readonly List<byte> bytesToDecode = new List<byte>();
|
static readonly List<short> decodeFloatList = new List<short>();
|
#endif
|
|
public static byte[] opus_encode_native(float[] pcm)
|
{
|
#if UNITY_ANDROID || UNITY_EDITOR || UNITY_STANDALONE
|
var encoder = new Encoder(
|
SamplingFrequency.Frequency_16000,
|
NumChannels.Mono,
|
OpusApplication.VoIP
|
)
|
{
|
Bitrate = 20000,
|
Complexity = 10,
|
Signal = OpusSignal.Music
|
};
|
var shorts = VoiceConvert.SamplesToShorts(pcm);
|
sampleList.Clear();
|
sampleList.AddRange(shorts);
|
|
encodedByteList.Clear();
|
int totalsize = 0;
|
|
while (sampleList.Count > frameSize)
|
{
|
var encodedLength = encoder.Encode(sampleList.GetRange(0, frameSize).ToArray(), encodeBuffer);
|
sampleList.RemoveRange(0, frameSize);
|
encodedByteList.Add((byte)encodedLength);
|
var bytes = new byte[encodedLength];
|
Array.Copy(encodeBuffer, bytes, encodedLength);
|
encodedByteList.AddRange(bytes);
|
totalsize += (encodedLength + 1);
|
}
|
UnityEngine.Debug.Log(totalsize);
|
encoder.Dispose();
|
return encodedByteList.ToArray();
|
|
#elif UNITY_IOS
|
var shorts = VoiceConvert.SamplesToShorts(pcm);
|
byte[] opus = new byte[VoiceSettings.frequency * VoiceSettings.length];
|
int length = native_opus_encode(shorts, shorts.Length, opus);
|
System.IO.MemoryStream stream=new System.IO.MemoryStream();
|
stream.Write(opus, 0, length );
|
stream.Close();
|
|
return stream.ToArray();
|
//return opus;
|
#endif
|
}
|
|
public static float[] opus_decode_native(byte[] opus)
|
{
|
#if UNITY_ANDROID || UNITY_EDITOR || UNITY_STANDALONE
|
var decoder = new Decoder(
|
SamplingFrequency.Frequency_16000,
|
NumChannels.Mono
|
);
|
|
decodeFloatList.Clear();
|
bytesToDecode.Clear();
|
bytesToDecode.AddRange(opus);
|
|
short[] audioClipData = null;
|
while (bytesToDecode.Count > 0)
|
{
|
var bytesLength = bytesToDecode[0];
|
bytesToDecode.RemoveAt(0);
|
var sampleLength = decoder.Decode(bytesToDecode.GetRange(0, bytesLength).ToArray(), bytesLength, decodedBuffer);
|
|
if (audioClipData == null || audioClipData.Length != sampleLength)
|
{
|
audioClipData = new short[sampleLength];
|
}
|
|
Array.Copy(decodedBuffer, audioClipData, sampleLength);
|
decodeFloatList.AddRange(audioClipData);
|
bytesToDecode.RemoveRange(0, bytesLength);
|
}
|
decoder.Dispose();
|
//return decodeFloatList.ToArray();
|
var floats = VoiceConvert.ShortsToSamples(decodeFloatList.ToArray());
|
return floats;
|
|
#elif UNITY_IOS
|
short[] pcm = new short[VoiceSettings.frequency * VoiceSettings.length];
|
native_opus_decode(opus, opus.Length, pcm);
|
var floats = VoiceConvert.ShortsToSamples(pcm);
|
return floats;
|
#endif
|
}
|
|
#if UNITY_IOS
|
[DllImport("__Internal")]
|
public static extern int native_opus_encode(short[] pcm, int len, byte[] opus);
|
|
[DllImport("__Internal")]
|
public static extern int native_opus_decode(byte[] opus, int len, short[] pcm);
|
|
#endif
|
|
|
}
|