?? codecs.cs
字號:
using System.Collections;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System;
namespace RtpAudio
{
#region//編解碼動態(tài)庫引用
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>
///語音編碼的執(zhí)行過程
/// </summary>
/// <param name="data">要進行編碼的數(shù)據(jù)</param>
/// <param name="output">編碼之后的數(shù)據(jù)</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">解碼的字節(jié)數(shù)</param>
/// <param name="data">要進行解碼的語音數(shù)據(jù)</param>
/// <param name="output">解碼后輸出的語音數(shù)據(jù)</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>
/// 初始化結構保存數(shù)據(jù),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 秒(緩沖區(qū)設置為可以保存最長 10 秒的音頻,超過的話最早的內容會被覆蓋)讀出當前的音頻流,
//然后送給 SpeexEncoder 編碼
/// <summary>
///數(shù)據(jù)編碼
/// </summary>
/// <param name="data">要進行編碼的數(shù)據(jù)</param>
/// <returns></returns>
public byte[] Encode(byte[] data)
{
if (!_init)
throw new NotSupportedException("尚未設置編碼器比特率。");
//data的長度必須為 160 *2 的整數(shù)倍
if (data.Length % (FrameSize * 2) != 0) //將要進行 語音編碼的數(shù)據(jù) 切分為多個 320字節(jié)的單元
throw new ArgumentException("數(shù)據(jù)無效。", "data");
int nbBytes;
short[] input = new short[FrameSize]; //一會要進行語音編碼數(shù)據(jù)
byte[] buffer = new byte[200];
byte[] output = new byte[0];
for (int i = 0; i < data.Length / (FrameSize * 2); i++) //將 data數(shù)組 劃分為 多個 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 字節(jié)即編碼, 編碼之后的數(shù)據(jù)長度
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>
///解碼語音數(shù)據(jù)
/// </summary>
/// <param name="data">要解碼的語音數(shù)據(jù)</param>
/// <returns>解碼之后的語音數(shù)組</returns>
public byte[] Decode(byte[] data)
{
if (!_init)
Codec.decoder_init(); //解碼初始化
int nbBytes, index = 0;
byte[] input; // input數(shù)組為一暫存數(shù)組
short[] buffer = new short[FrameSize];
byte[] output = new byte[0];
while (index < data.Length)
{
nbBytes = 0;
//每段的前四字節(jié)存儲的是 該段數(shù)據(jù)的長度值
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);// 將接收的編碼語音數(shù)據(jù)拷貝到 input數(shù)組中去
index += input.Length;
//解碼之后的數(shù)據(jù)在 buffer中
Codec.decoder_decode(nbBytes, input, buffer); //對數(shù)據(jù)進行解碼,解碼后語音數(shù)據(jù)即還原了
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 + -