146 lines
4.8 KiB
C#
146 lines
4.8 KiB
C#
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;
|
|
}
|
|
|
|
}
|