SafeDispatch/SafeMobileLIB_DLL/NspeexAndro.cs

146 lines
4.8 KiB
C#
Raw Normal View History

2024-02-22 16:43:59 +00:00
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;
}
}