C#中利用Socket實現網路語音通訊[初級版本]
阿新 • • 發佈:2019-02-10
///<summary>/// 設定音訊格式,如取樣率等
///</summary>///<returns>設定完成後的格式</returns> private WaveFormat SetWaveFormat()
{
WaveFormat format = new WaveFormat();
format.FormatTag = WaveFormatTag.Pcm;//設定音訊型別 format.SamplesPerSecond = 11025;//
return
//按照以上取樣規格,可知取樣1秒鐘的位元組數為22050*2=44100B 約為 43K }
///<summary>/// 建立捕捉裝置物件
///</summary>///<returns>如果建立成功返回true</returns> private bool CreateCaputerDevice()
{
//首先要玫舉可用的捕捉裝置 CaptureDevicesCollection capturedev = new CaptureDevicesCollection();
Guid devguid;
if
{
devguid = capturedev[0].DriverGuid;
}
else
{
System.Windows.Forms.MessageBox.Show("當前沒有可用於音訊捕捉的裝置", "系統提示");
return false;
}
//利用裝置GUID來建立一個捕捉裝置物件 capture = new Capture(devguid);
return true;
}
///<summary>/// 建立捕捉緩衝區物件
///</summary> private void CreateCaptureBuffer()
{
//想要建立一個捕捉緩衝區必須要兩個引數:緩衝區資訊(描述這個緩衝區中的格式等),緩衝裝置。 WaveFormat mWavFormat = SetWaveFormat();
CaptureBufferDescription bufferdescription = new CaptureBufferDescription();
bufferdescription.Format = mWavFormat;//設定緩衝區要捕捉的資料格式 iNotifySize = mWavFormat.AverageBytesPerSecond / iNotifyNum;//1秒的資料量/設定的通知數得到的每個通知大小小於0.2s的資料量,話音延遲小於200ms為優質話音 iBufferSize = iNotifyNum * iNotifySize;
bufferdescription.BufferBytes = iBufferSize;
bufferdescription.ControlEffects = true;
bufferdescription.WaveMapped = true;
capturebuffer = new CaptureBuffer(bufferdescription, capture);//建立裝置緩衝區物件
}
//設定通知 private void CreateNotification()
{
BufferPositionNotify[] bpn = new BufferPositionNotify[iNotifyNum];//設定緩衝區通知個數
//設定通知事件 notifyEvent = new AutoResetEvent(false);
notifyThread = new Thread(RecoData);//通知觸發事件 notifyThread.IsBackground = true;
notifyThread.Start();
for (int i = 0; i < iNotifyNum; i++)
{
bpn[i].Offset = iNotifySize + i * iNotifySize - 1;//設定具體每個的位置 bpn[i].EventNotifyHandle = notifyEvent.Handle;
}
myNotify = new Notify(capturebuffer);
myNotify.SetNotificationPositions(bpn);
}
//執行緒中的事件 private void RecoData()
{
while (true)
{
// 等待緩衝區的通知訊息 notifyEvent.WaitOne(Timeout.Infinite, true);
// 錄製資料 RecordCapturedData(Client,epServer);
}
}
//真正轉移資料的事件,其實就是把資料傳送到網路上去。 private void RecordCapturedData(Socket Client,EndPoint epServer )
{
byte[] capturedata = null;
int readpos = 0, capturepos = 0, locksize = 0;
capturebuffer.GetCurrentPosition(out capturepos, out readpos);
locksize = readpos - iBufferOffset;//這個大小就是我們可以安全讀取的大小 if (locksize == 0)
{
return;
}
if (locksize < 0)
{//因為我們是迴圈的使用緩衝區,所以有一種情況下為負:當文以載讀指標回到第一個通知點,而Ibuffeoffset還在最後一個通知處 locksize += iBufferSize;
}
capturedata = (byte[])capturebuffer.Read(iBufferOffset, typeof(byte), LockFlag.FromWriteCursor, locksize);
//capturedata = g729.Encode(capturedata);//語音編碼 try
{
Client.SendTo(capturedata, epServer);//傳送語音 }
catch
{
throw new Exception();
}
iBufferOffset += capturedata.Length;
iBufferOffset %= iBufferSize;//取模是因為緩衝區是迴圈的。 }