PC到PC的IP電話實現


PC到PC的IP電話實現 作者:阮幫秋 發佈時間:2001/04/09
 
 
 
文章摘要:
  IP電話,也稱爲網絡電話,它的發展非常之迅速。本文設計並實現了一個計算機到計算機的IP電話的軟件模型,詳細講解了軟件設計中的重點和難點,分析了軟件中語音的採集和播放,語音的網絡傳輸等一些關鍵技術的實現方法和注意事項,並指出了軟件的不足和進一步工作。在局域網上用此軟件來做通話實驗,音質和時延都達到了電話的效果,說明此軟件達到了IP電話的基本要求。
  關鍵詞:IP電話 語音 網絡
 
        

--------------------------------------------------------------------------------
 
正文:   


PC到PC的IP電話實現  


  Internet是當今應用最廣泛、發展最迅速的通信網絡。這是基於數據包方式的數據分組交換方式,用戶數據被封裝在分組中,而分組還包含一些附加信息用於網絡中的路由選擇、差錯糾正、流量控制等。數據包各自獨立地在網絡中傳遞,由於網絡狀況的變化和經歷路徑的不同,數據包到達目的地的時間是不固定的、非實時的。故此,一般來說互聯網較適用於數據的傳輸。但是,我們知道視頻、音頻信號經過模數轉換後也可以作爲數據在互聯網上傳遞,因此將語音採樣,量化變爲數字信號,然後打包從網絡上傳輸,雙方也可以進行通話,這就是IP電話。
  IP電話是對模擬語音信號經過模數轉換,進行編碼壓縮後,按一定的打包規則將壓縮幀轉換成IP數據包通過數據網進行傳輸,在目的地經過數據解壓、數模轉換復原成話音,從而達到語音通信的目的。由於數據網是採用統計時分的方式分配、使用網絡資源,任何通信實體都不可能獨佔某一信道,所以IP電話可以大大提高網絡資源的利用率,降低運營成本。
  IP電話的初次亮相是在1995年初,VocalTec公司推出了一種Internet Phone客戶軟件。雖然當時該公司還沒有提出在IP上傳輸話音的概念,但這確實是IP電話第一次成功的商業化和市場化。在此之前,IP上的話音傳輸極爲困難,VocalTec的第一個產品用於LAN上的兩臺PC相互通話。現已有多家網絡公司開始利用因特網正式提供國際國內的長途電話服務。特別在美國,此類業務開展得更爲廣泛。類似的技術也可用於長途傳真(E-Fax)等電信服務項目。由於全球範圍內的因特網通信費用大大低於通常的電信長途費用,衆多的用戶已開始使用通過因特網的長途電話服務。
  基於實驗和研究的目的,本文實現了一個從計算機到計算機的IP電話的軟件。軟件的開發環境爲Windows 98平臺,開發工具採用Visual C++ 5.0。本軟件能夠在網絡上實現多人之間的文本傳輸和兩人之間的語音對話。下文將對本軟件展開分析。

一 軟件設計

實現此軟件的重點和難點如下:
  (1)實現語音的採集和播放,就是在發話方將聲音通過麥克風和聲卡採集成語音數據,在接收方通過聲卡和耳機播放出來。
  (2)實現語音數據的壓縮和解壓縮,在發話方壓縮採集的語音數據,在接收方解壓縮。
  (3)實現語音數據在網絡上的傳輸。
  (4)多用戶之間的連接方式和控制。
  (5)軟件整體結構和交互界面的設計。
  
  考慮到軟件的核心功能是傳輸語音,所以整個軟件的設計應該圍繞着語音傳輸來設計。首先分析語音傳輸的過程,如圖一是一個單向的語音傳輸過程。發話方首先由聲卡採集語音,將語音轉換爲數據,存入內存中,再通過CPU進行語音壓縮算法的運算,將語音數據進行壓縮,最後通過網卡將語音數據發送出去。接收方通過網卡接收到語音數據,首先由CPU採用解壓縮算法將語音數據進行解壓縮,然後通過聲卡將數據轉換爲語音,通過耳機播放。此流程圖實際上已經包含了上述問題中前三個問題的解答,當然這只是從理論上肯定了可行性,具體的實現後面還會進一步討論。

 

圖一 語音傳輸流程


  多個用戶之間的互相連接通常可以採用兩種方法。第一種方法是設置一個服務器,所有的客戶機都連接到服務器上,通過服務器互相連接。這種方法的好處是軟件控制比較簡單,用戶的連接也比較方便,用戶只需要知道服務器的IP地址就行了。但缺點也很明顯,它較適合於公司的商業性質的軟件,普通人員沒有資金去專門購買和設置一個服務器,也沒有時間和精力去管理和維護服務器。第二種方法是不要服務器,每兩個用戶之間都可以互相連接,只要知道對方的IP地址就可以去連接對方,同時別人只要知道你的IP地址,也可以與你連接,即每臺計算機都既是服務器,又是客戶機。採用這種方法的優缺點與第一種方法可以說是正好相反,不再贅述。也有某些比較完善的軟件對這兩種方法都予以採用,用戶可以自行選擇其中一種方法與其它用戶進行連接。
  由以上分析,作者決定採用第二種方式進行計算機之間的連接,這樣雖然增加了軟件的複雜度,但符合我們的實際情況。在實際程序中,採用了一個鏈表來保存與之相連的用戶的信息,充分利用了鏈表的無序性和動態的增加,刪除特性來表示無序的用戶的動態的連接和離開。這樣也從理論上解決了第四個問題。
  軟件的整體結構和數據流程如圖二,用戶交互界面用來響應用戶的操作,提示用戶重要的信息,顯示文本,播放語音等,實現軟件與用戶的交互。用戶可以通過鍵盤來輸入文本,通過麥克風來輸入語音。
語音採集模塊用來採集語音數據,將模擬語音信號轉換爲數字信號,在程序中爲了減少通話的延遲時間,直接分配內存塊,將採集的數據放在內存塊中,以便壓縮或傳輸。對語音的採集是通過調用聲卡的API函數來完成。在本軟件中語音的採樣格式爲WAVE_FORMAT_PCM,單聲道,採樣率爲8K,樣本量化率爲16位,即每秒的語音數據有16K字節。
數據傳輸模塊採用VC的CSocket類,通過TCP/IP協議將放在內存塊中的語音採集數據傳輸到接收方。
語音播放模塊將接收到的語音數據直接通過聲卡把數字信號轉換爲模擬信號,進行播放。
  語音壓縮模塊首先對輸入的語音幀進行高通濾波,去除信號中的直流分量和50Hz的成分,同時進行增益控制。再進行線性預測分析,提取線譜對參數,對線譜對進行預測和量化,利用線譜對參數構造共振峯感覺加權濾波器,對高通信號進行開環基音估計,在開環基音估計的基礎上進行閉環基音估計,在已經取得的參數的基礎上代入語音生成模型對激勵碼本進行搜索,提取激勵參數。對各參數進行量化,編幀。本軟件的壓縮率達到了1/20的效果,即壓縮後每秒的語音數據爲0.8K字節。
  語音解壓模塊從語音幀中提取各參數代入語音生成模型,輸出語音。

 


圖二 軟件的整體結構和數據流程

  至此我們已經搭起了整個軟件的基本框架,對於軟件的數據流程也已分析得比較透徹,下一步就是具體的實現了。


二 軟件實現

  下面具體分析軟件實現中的一些主要難點。

1.語音的採集和播放。
  本軟件中要把語音直接轉換爲數據,放在內存中,而不是存爲語音文件,而且播放語音時,也是直接播放語音數據,而不是播放語音文件。這樣的好處前面已經提到,即省略了讀寫硬盤的費時操作,提高了語音通話的實時性。
  要完成上述語音操作,編程語言中提供的容易使用的高級的多媒體語音函數是無法勝任的,只能用一些底層的語音函數來實現,這一類函數和結構的名字都以"wave"作爲前綴。
  下面簡要分析錄音和放音的流程,考慮到兩着的處理和流程基本上是類似的,本文就只以錄音爲例來分析,如圖三爲錄音流程。錄音的準備工作主要是三點,打開錄音設備,獲得錄音句柄,指定錄音格式,分配若干用於錄音的內存,內存的大小和數量下文將進一步分析。開始錄音時,先將所有內存塊都提供給錄音設備用來錄音,錄音設備就會依次將語音數據寫入內存,當一塊內存寫滿,錄音設備就會發一個Window 消息MM_WIM_DATA給相應的窗口,通知程序作相關的處理,這時程序通常的處理是把內存中的數據進行復制,如寫入文件等,在此我們的處理是把數據進行壓縮和網絡發送,然後把內存置空,返還給錄音設備進行錄音,這樣就形成一個循環不息的錄音過程。結束錄音時就釋放所有內存塊,關閉錄音設備。

 

圖三 錄音流程 

以錄音爲例,關鍵的錄音函數和順序如下:
WAVEFORMATEX waveformat;
waveformat.wFormatTag=WAVE_FORMAT_PCM;
waveformat.nChannels=1;
waveformat.nSamplesPerSec=8000;
waveformat.nAvgBytesPerSec=16000;
waveformat.nBlockAlign=2;
waveformat.cbSize=0;
waveformat.wBitsPerSample=16; //指定錄音格式
int res=waveInOpen(&m_hWaveIn,WAVE_MAPPER, &waveformat, (DWORD)m_hWnd,0L,CALLBACK_WINDOW); //打開錄音設備
waveInPrepareHeader(m_hWaveIn,m_pWaveHdr[i],sizeof(WAVEHDR)); //準備內存塊錄音
waveInAddBuffer(m_hWaveIn,m_pWaveHdr[i],sizeof(WAVEHDR)); //增加內存塊
waveInStart(m_hWaveIn);//開始錄音
waveInStop(m_hWaveIn); //停止錄音
waveInReset(m_hWaveIn); //清空內存塊
waveInClose(m_hWaveIn); //關閉錄音設備

  在錄音和放音的程序處理中,要特別注意兩點。一個是分配的內存的大小和數量。內存的大小與IP電話中語音的連續性和延時性有直接關係,內存越大,則語音的連續性越好,但延時性越差,反之,內存越小,則語音的延時性越小,但連續性越差,所以要權衡利弊,取一個折衷量,這就需要反覆實驗。根據作者的實驗,大約每個內存塊錄音的時間長度取0.1秒比較合適,具體的大小與採用的語音格式有關。內存的數量則與內存的大小和對每個內存的錄音數據的處理時間長短有關,一定要保證在錄音過程中,錄音設備至少有一塊內存可供錄音,也就是說錄滿的內存要及時返回,使得循環能夠順利進行。由此可知,內存大,分配的數量就可以少,對每個內存的錄音數據的處理時間短,分配的數量就可以少,反之,分配的數量就要多。當然可以分配足夠多的數量,但是太多則耗費資源,降低了程序的效率。根據作者的實驗,大約所有的內存塊錄音的時間長度和有0.5秒就足夠了,也就是說,如果每個內存塊錄音時間長度爲0.1秒,則可以分配5個內存塊。

  程序中還有特別重要的一點是語音設備的Window消息的相應,通過語音設備發送的一系列消息,如MM_WIN_OPEN錄音設備打開消息,MM_WIM_CLOSE錄音設備關閉消息等,我們可以響應語音設備的打開,關閉,開始錄音和放音,停止錄音和放音,錄音時一個內存塊錄滿,放音時一個內存塊放完等各種事件,來進行相關的處理。需要注意的是這些消息在VC的ClassWizard類工具的消息序列中是看不到的,需要手工編輯消息響應宏和代碼。

2.語音數據的網絡傳輸
  TCP/IP協議是網絡上最通用的協議,本軟件採用TCP/IP協議來進行數據語音的網絡傳輸。CSocket類是Visual C++ 4.0新增加的一個類,它是對原來的Windows Socket API的封裝,用它進行網絡編程比用Windows Socket API要方便得多。

  建立網絡的連接主要有如下三個步驟,一是在程序中加入Windows Sockets支持,二是以CSocket爲基類構造兩個新類CServerSocket和CMsgSocket。CServerSocket用來接收請求連接的申請,CMsgSocket用來傳輸數據。三是建立服務器方和客戶機方的連接。下表顯示了在服務器與客戶機之間建立通信所需做的工作的順序,具體的函數參數可查閱連機文檔。服務器方首先構造一個CServerSocket類的對象,用來接收請求連接的申請,調用此對象的Listen成員函數,表示處於等待連接狀態,等待客戶機方發出申請連接(Connect)的消息,當接收到此消息後,CServerSocket類的OnAccept消息響應函數即會響應,此時再構造一個CMsgSocket類的對象(用來傳輸數據),然後調用CServerSocket類的Accept成員函數表示接受連接申請,若此函數返回真值,則表示連接成功。客戶機方則只需構造一個CMsgSocket類的對象,調用此對象的Connect成員函數,申請連接即可。

 


  按上述順序建立連接後,服務器方和客戶機方都調用CMsgSocket對象的Send函數來發送數據,當接收到數據時,CMsgSocket類的OnReceive消息響應函數即會響應,再調用Receive函數來接收數據,這樣服務器方和客戶機方就可以進行數據通信了。
  在程序中要注意網絡消息的響應,如接收到數據,有客戶申請連接,已連接上,對方已斷開等等,與一般的消息響應函數不同,它已經集成在CSocket類的成員函數中,而不用消息響應宏。如在CServerSocket類中重載CSocket類的成員函數OnAccept,即可以處理申請連接的消息,在CMsgSocket類中重載CSocket類的成員函數OnReceive,即可以處理接收到數據的消息。重載CSocket類的成員函數OnClose函數,即可以處理對方網絡已斷開的消息。另外用CSocket類的成員函數GetPeerName可以得到對方的IP地址,在程序中可以保存下來,供以後連接使用,用戶不必再重新輸入。

3.對單工聲卡的支持
  聲卡有單工聲卡和雙工聲卡之分,雙工聲卡可以同時錄音和放音,而單工聲卡一個時間段只能從事一種工作,要麼錄音,要麼放音。
  對IP電話來說,當然是要用雙工聲卡,才能達到電話的效果。但考慮到當前廣大用戶的計算機配置的都是單工聲卡,本軟件也加入了對單工聲卡的支持。軟件可以自動檢測計算機的聲卡,針對不同的聲卡採用不同的工作方式。當聲卡爲雙工聲卡時,可以同時聽和說,當聲卡爲單工方式時則用戶可以控制,在聽和說之間進行切換。
  具體的實現方法是,當一方爲單工聲卡時,首先通過網絡通知對方,讓對方有心理準備。然後在實際的通話過程中,一方進行切換時,就通知另一方,另一方也自動進行切換,進入對應的方式。即一方爲說時,另一方就自動爲聽,反之亦然,這樣雙方就不會發生衝突。具體的編程實現比較複雜,但只要考慮周到,也並不困難,這裏不再贅述。


三 軟件界面和使用方法

  軟件界面如圖四,界面上方的IP地址欄可輸入欲連接的計算機的IP地址,單擊右邊的代表連接含義的圖標即可與之連接,連通或未連通在界面上方的文本框內都有提示。用戶也可以按連接按紐旁邊的斷開按紐斷開與任意已連通的對象的網絡連接。
  網上成員的下拉框內有當前與用戶連通的所有用戶的姓名。
  界面下方的文本框可以輸入多行文本,在界面下方的下拉框內選擇發送對象,發送對象就是所有與用戶連通的其他人,單擊左邊的按紐,就可以將文本發送給所選擇的對象。如下圖:接收到的文本和發送對象會在界面上方的文本框內顯示出來。
  單擊電話按紐,類似與電話撥號,用戶可以選擇一個與他連通的人進行語音通話,對方的計算機就會有振鈴聲,對方可以選擇是否接通進行通話,類似與摘機。若對方同意通話,雙方就可以用麥克風和耳機進行通話。若聲卡具備全雙工功能,即聲卡可以同時錄音和放音,雙方就可以象打電話一樣進行交談。若聲卡不具備全雙工功能,事實上當前市場上的大多數聲卡都不具備此性能,則聽和說同時只能選擇其中一種,考慮到實際情況,本軟件提供了對單工聲卡的支持,可以自動識別聲卡的單雙工特性,分別予以處理,如果是單工聲卡,用戶可以在說和聽時單擊電話圖標按紐(當通話時,電話圖標會改變爲麥克風圖標或喇叭圖標,麥克風圖標代表說,喇叭圖標代表聽),進行功能切換。當然最好是雙方都具備全雙工聲卡,都可以同時說和聽,這樣纔有電話的效果。
  通話完畢,雙方都可以單擊電話圖標旁邊的停止圖標按紐停止交談,類似與掛斷電話。
  用戶依據網絡狀況的好壞,可以採用壓縮和不壓縮的方式來傳輸語音。在局域網內用不壓縮的方式就可以達到很好的效果。

 

圖四 軟件界面


  實踐證明,本軟件在實際運行中穩定可靠,在局域網上音質和延遲都基本上達到了電話的效果。


四 軟件的不足和進一步工作

  本軟件從總體上已經達到了IP電話的基本要求,但是由於作者的時間和條件有限,軟件也存在一些不足和需要進一步完善的地方。
  最大的不足是每秒0.8K的語音數據在我們國家當前的Internet上還是顯得過高,本軟件中語音壓縮率還有待繼續提高。
  其次在本軟件中從通用性的目的出發,採用TCP/IP協議進行網絡傳輸。實際上IP電話的語音傳輸和視頻傳輸以及語音和視頻的壓縮方式等都有相應的國際標準,如果作爲一個嚴格的商業軟件,則必須採用這些標準。
  另外在軟件的整體功能上還可以進一步加強。例如語音通話中可以加入錄音功能,實現起來也並不困難,將內存中的語音數據寫入文件即可,同理也可以實現語音信箱的功能。其它一些重要的功能,如文件傳輸,多方通話等等,都可以加入軟件中。

 


作者會員名:ruan_bangqiu

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章