📄 codecs.cs
字号:
using System.Collections;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System;
namespace RtpAudio
{
#region//编解码动态库引用
public static class Codec
{
/// <summary>
/// 语音编码初始化操作
/// </summary>
/// <param name="quality"></param>
[DllImport("speexCodec.dll", EntryPoint = "encoder_init")]
public extern static void encoder_init(int quality);
/// <summary>
///语音编码的释放
/// </summary>
[DllImport("speexCodec.dll", EntryPoint = "encoder_dispose")]
public extern static void encoder_dispose();
/// <summary>
///语音编码的执行过程
/// </summary>
/// <param name="data">要进行编码的数据</param>
/// <param name="output">编码之后的数据</param>
/// <returns></returns>
[DllImport("speexCodec.dll", EntryPoint = "encoder_encode")]
public extern static int encoder_encode(short[] data, byte[] output);
/// <summary>
///解码初始化
/// </summary>
[DllImport("speexCodec.dll", EntryPoint = "decoder_init")]
public extern static void decoder_init();
/// <summary>
///语音解码释放
/// </summary>
[DllImport("speexCodec.dll", EntryPoint = "decoder_dispose")]
public extern static void decoder_dispose();
/// <summary>
///语音解码
/// </summary>
/// <param name="nbBytes">解码的字节数</param>
/// <param name="data">要进行解码的语音数据</param>
/// <param name="output">解码后输出的语音数据</param>
[DllImport("speexCodec.dll", EntryPoint = "decoder_decode")]
public extern static void decoder_decode(int nbBytes, byte[] data, short[] output);
}
#endregion
#region// 编码
public class SpeexEncoder : IDisposable
{
const int FrameSize = 160;
private bool _init = false;
public void Dispose()
{
Codec.encoder_dispose();
_init = false;
}
/// <summary>
/// 初始化结构保存数据,quality的值可以取 8表示 15kbps
/// </summary>
/// <param name="quality"></param>
public void SetQuality(int quality)
{
if (_init)
Codec.encoder_dispose();
Codec.encoder_init(quality);
_init = true;
}
//在开始捕获后,每隔 1 秒(缓冲区设置为可以保存最长 10 秒的音频,超过的话最早的内容会被覆盖)读出当前的音频流,
//然后送给 SpeexEncoder 编码
/// <summary>
///数据编码
/// </summary>
/// <param name="data">要进行编码的数据</param>
/// <returns></returns>
public byte[] Encode(byte[] data)
{
if (!_init)
throw new NotSupportedException("尚未设置编码器比特率。");
//data的长度必须为 160 *2 的整数倍
if (data.Length % (FrameSize * 2) != 0) //将要进行 语音编码的数据 切分为多个 320字节的单元
throw new ArgumentException("数据无效。", "data");
int nbBytes;
short[] input = new short[FrameSize]; //一会要进行语音编码数据
byte[] buffer = new byte[200];
byte[] output = new byte[0];
for (int i = 0; i < data.Length / (FrameSize * 2); i++) //将 data数组 划分为 多个 320 单元
{
for (int j = 0; j < input.Length; j++)
input[j] = (short)(data[i * FrameSize * 2 + j * 2] + data[i * FrameSize * 2 + j * 2 + 1] * 0x100);
nbBytes = Codec.encoder_encode(input, buffer); //针对 每 320 字节即编码, 编码之后的数据长度
Array.Resize<byte>(ref output, output.Length + nbBytes + sizeof(int));
Array.Copy(buffer, 0, output, output.Length - nbBytes, nbBytes);
for (int j = 0; j < sizeof(int); j++)
{
output[output.Length - nbBytes - sizeof(int) + j] = (byte)(nbBytes % 0x100);
nbBytes /= 0x100;
}
}
return output;
}
}
#endregion
#region//解码
public class SpeexDecoder : IDisposable
{
public const int FrameSize = 160;
private bool _init = false;
/// <summary>
///解码释放
/// </summary>
public void Dispose()
{
if (_init)
Codec.decoder_dispose();
}
/// <summary>
///解码语音数据
/// </summary>
/// <param name="data">要解码的语音数据</param>
/// <returns>解码之后的语音数组</returns>
public byte[] Decode(byte[] data)
{
if (!_init)
Codec.decoder_init(); //解码初始化
int nbBytes, index = 0;
byte[] input; // input数组为一暂存数组
short[] buffer = new short[FrameSize];
byte[] output = new byte[0];
while (index < data.Length)
{
nbBytes = 0;
//每段的前四字节存储的是 该段数据的长度值
index += sizeof(int);
for (int i = 1; i <= sizeof(int); i++)
nbBytes = nbBytes * 0x100 + data[index - i];
input = new byte[nbBytes]; //读出对应的解码段的长度
Array.Copy(data, index, input, 0, input.Length);// 将接收的编码语音数据拷贝到 input数组中去
index += input.Length;
//解码之后的数据在 buffer中
Codec.decoder_decode(nbBytes, input, buffer); //对数据进行解码,解码后语音数据即还原了
Array.Resize<byte>(ref output, output.Length + FrameSize * 2);
for (int i = 0; i < FrameSize; i++)
{
output[output.Length - FrameSize * 2 + i * 2] = (byte)(buffer[i] % 0x100);
output[output.Length - FrameSize * 2 + i * 2 + 1] = (byte)(buffer[i] / 0x100);
}
}
return output;
}
}
#endregion
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -