using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.IO; using NSpeex; namespace SafeMobileLib { public class NspeexAndro { private Mode mode; private int quality; private readonly NSpeex.Decoder decoder; private readonly NSpeex.Encoder encoder; private readonly PreProcessor preProcessor; private JitterBufferWaveProvider waveProvider; public NspeexAndro(Mode m) { mode = m; //quality = Q; //decoder decoder = new NSpeex.Decoder(m); waveProvider = new JitterBufferWaveProvider(m); //encoder encoder = new NSpeex.Encoder(m); encoder.Quality = 5; encoder.VBR = true; preProcessor = new PreProcessor(encoder) { AGC = true, AGCIncrement = 3, Denoise = true, VAD = true }; } public void AddAudio4Decode(byte[] data) { BinaryReader reader = new BinaryReader(new MemoryStream(data)); //while (reader.PeekChar() != -1) while (reader.BaseStream.Length - reader.BaseStream.Position > 4) { int frameLength = reader.ReadInt32(); //Console.WriteLine("frame len" + frameLength); byte[] frame = reader.ReadBytes(frameLength); waveProvider.Write(frame, 0, frameLength); } } public long Length { get { return waveProvider.Length; } } public int GetDecodedAudio(byte[] data, int offset, int size) { if (waveProvider.HasData(size)) return waveProvider.Read(data, offset, size); else return 0; } public byte[] Encode(byte[] data, int offset, int size) { int samplesPerFrame = encoder.FrameSize; byte[] buffer = data; short[] frame = new short[samplesPerFrame]; byte[] encodedFrame = new byte[size]; int encodedBytesSample = 0; byte[] upstreamEncodedSample = new byte[size]; int frameIndex = 0; for (int index = 0; index < size; index += 2, frameIndex = ++frameIndex % samplesPerFrame) { frame[frameIndex] = BitConverter.ToInt16(buffer, index); if (frameIndex != samplesPerFrame - 1) continue; if (preProcessor.Process(frame)) { int encodedBytes = encoder.Encode(frame, encodedFrame); if (encodedBytes != 0) { Array.Copy(BitConverter.GetBytes(encodedBytes), 0, upstreamEncodedSample, encodedBytesSample, sizeof(int)); encodedBytesSample += 4; Array.Copy(encodedFrame, 0, upstreamEncodedSample, encodedBytesSample, encodedBytes); encodedBytesSample += encodedBytes; } } } if (frameIndex != 0) { while (frameIndex < samplesPerFrame) { // fill the last frame with 0s frame[frameIndex++] = 0; } int encodedBytes = encoder.Encode(frame, encodedFrame); if (encodedBytes != 0) { Array.Copy(BitConverter.GetBytes(encodedBytes), 0, upstreamEncodedSample, encodedBytesSample, sizeof(int)); encodedBytesSample += 4; Array.Copy(encodedFrame, 0, upstreamEncodedSample, encodedBytesSample, encodedBytes); encodedBytesSample += encodedBytes; } } if (encodedBytesSample != 0) { var upstreamFrame = new byte[encodedBytesSample]; Array.Copy(upstreamEncodedSample, upstreamFrame, encodedBytesSample); //SM.Debug("Publishing: " + encodedBytesSample + " bytes"); /* if (OnNewDataRecv != null) { OnNewDataRecv(upstreamFrame, encodedBytesSample); } */ return upstreamFrame; } else { return null; //Console.WriteLine("DTX"); } } public TimeSpan TotalTime { get { return waveProvider.TotalTime; } } public delegate void newData4Send(byte[] data, int dataLen); public event newData4Send OnNewDataRecv; } public class AndroEncodedPack { public int frameSize; public byte[] frame; } }