using NSpeex; using SevenZip; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using UnityEngine; public static class VoiceCodec { public static bool IsBusy { get; private set; } public static void Encode(float[] samples, Action callback) { if (IsBusy) { return; } IsBusy = true; short[] s = VoiceConvert.SamplesToShorts(samples); byte[] opus = new byte[VoiceSettings.frequency * VoiceSettings.length]; var length = OpusNative.native_opus_encode(s, s.Length, opus); byte[] results = new byte[length]; Buffer.BlockCopy(opus, 0, results, 0, length); byte[] compress = VoiceCompress.SevenZipCompress(results); IsBusy = false; Debug.Log(compress.Length); if (callback != null) { callback(compress); } } public static void Decode(byte[] _bytes, Action callback) { var decompress = VoiceCompress.SevenZipDecompress(_bytes); short[] pcm = new short[VoiceSettings.frequency * VoiceSettings.length]; OpusNative.native_opus_decode(decompress, decompress.Length, pcm); float[] samples = VoiceConvert.ShortsToSamples(pcm); if (callback != null) { callback(samples); } } } public static class VoiceConvert { static short[] s_pcm = new short[VoiceSettings.frequency * VoiceSettings.length]; public static short[] SamplesToShorts(float[] samples) { for (int i = 0; i < samples.Length; i++) { float s = samples[i]; if (Mathf.Abs(s) > 1.0f) { s = s > 0 ? 1.0f : -1.0f; } float c = s * 3267.0f; s_pcm[i] = (short)c; } return s_pcm; } public static float[] ShortsToSamples(short[] data) { float[] samples = new float[data.Length]; for (int i = 0; i < samples.Length; i++) { int c = (int)data[i]; samples[i] = ((float)c / 3267.0f) * 4f; } return samples; } } public static class VoiceCompress { public static byte[] SevenZipCompress(byte[] _input) { CoderPropID[] ids = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (int)(23), (int)(2), (int)(3), (int)(2), (int)(1), (int)(128), (string)("bt4"), (bool)(true) }; var encoder = new SevenZip.Compression.LZMA.Encoder(); encoder.SetCoderProperties(ids, properties); MemoryStream msIn = new MemoryStream(_input); using (MemoryStream msOut = new MemoryStream()) { encoder.WriteCoderProperties(msOut); encoder.Code(msIn, msOut, -1, -1, null); msIn.Dispose(); msIn.Close(); return msOut.ToArray(); } } public static byte[] SevenZipDecompress(byte[] _input) { CoderPropID[] ids = { CoderPropID.DictionarySize, CoderPropID.PosStateBits, CoderPropID.LitContextBits, CoderPropID.LitPosBits, CoderPropID.Algorithm, CoderPropID.NumFastBytes, CoderPropID.MatchFinder, CoderPropID.EndMarker }; object[] properties = { (int)(23), (int)(2), (int)(3), (int)(2), (int)(1), (int)(128), (string)("bt4"), (int)(0) }; var dec = new SevenZip.Compression.LZMA.Decoder(); byte[] prop = new byte[5]; Array.Copy(_input, prop, 5); dec.SetDecoderProperties(prop); MemoryStream msInp = new MemoryStream(_input); msInp.Seek(5, SeekOrigin.Current); MemoryStream msOut = new MemoryStream(); dec.Code(msInp, msOut, -1, -1, null); return msOut.ToArray(); } }