在Internet傳播聲音

來源:互聯網
上載者:User

 使用Audio Compression Manager(ACM)

 作者/Peter Morris  翻譯/陳省

  在幾年以前IP電話被炒的沸沸揚揚,但用過的人都覺得這個技術非常不成熟,語音品質很差,時斷時續,還經常有延遲,結果這項技術的應用沒有普及開來。但隨著Internet應用的越來越廣泛以及相關技術發展的日新月異,聲音品質不斷提高,通過Internet打電話早已不再是夢想,已經成為了我們生活中的一部分。今天我使用IP電話打長途,每分鐘只需要3毛錢,使用OICQ的語音交談,網友彷彿就在你的身邊。如果我們的頻寬足夠的,我們甚至還可以在網上收看QuicktimeApsaraVideo for Live,用RealAudio收聽電台廣播,也可以點播好聽的MP3歌曲。不過對於程式員來說,更好的訊息是我們對於這些媒體流的編程也也變得越來越容易。為什麼這麼說呢,下面讓我們先來瞭解一下Codec。

 Codecs

  什麼是Codecs?其實它就是音頻壓縮的解碼編碼器,實際上有點類似ActiveX控制項。ActiveX控制項使程式員可以調用一些他人實現好的功能而無需從頭做起。Codecs提供了類似的功能,只不過它集中在提供如何對媒體格式進行轉換的功能。例如,如果想寫一個把CD轉MP3的應用程式,我們只需要做下列工作:

 l         從CD音軌中讀取資料。

 l         產生一個有效MP3檔案頭。

 l         調用相應的codec把音軌資料編碼為MP3。

Windows本身已經帶了很多的codec。下面是其中幾個的說明:

名稱

說明

GSM

好像用於某些行動電話通訊網路。

DSP TrueSpeech

可以產生一種一位的聲音格式用於語音通話-聲音非常清楚。

Fraunhoffer IIS MP3

這種可以用來產生MP3格式。

PCM

用於產生Windows標準聲音格式。大多數Codec支援的聲音格式都可以和它相互轉化。

  當前安裝的codec的完整列表可以通過察看控制台中多媒體的部分來獲得。 

ACM API

  ACM是Audio Compression Manager縮寫,翻譯過來就是聲音壓縮管理器。它是微軟編寫的用於調用Codec功能的介面函數庫。它本來應該聲明在MMSystem.pas單元中,但是由於某些原因Borland把它給省略了。所以我們要作的第一件事是找到它的API聲明單元MSACM.pas。必須要感謝Francois Piette,他共用了他轉換的單元檔案,我們可以從www.Delphi-Jedi.org下載它。

  使用ACM轉換媒體格式包括以下幾步:

  l         首先必須指定輸入輸出格式,我們需要設定TWaveFormatEX記錄, 但是這個結構記錄太小無法容納大多數Codec所需要的資訊。為瞭解決這個問題,我們使用一個自訂的 TACMFormat記錄,這個記錄在TWaveFormatEX的基礎上增加了128位元組。

  l         開啟一個ACM流。首先調用acmStreamOpen函數,把輸入輸出格式作為參數傳遞過去。然後ACM或者返回一個有效控制代碼或者返回一個錯誤碼(比如ACMERR_NotPossible)來表明轉換的請求無法完成。

  l         接下來要確定輸出緩衝區的大小。調用acmStreamSize函數會通知ACM每次我們將產生多少位元組的資料,然後函數會返回請求大小的緩衝區(我們總是應該高估一下大小,保證提供一個足夠大的緩衝區)。

  l         然後,我們要產生一個轉換頭。需要調用acmStreamPrepareHeader函數,把先前調用acmStreamOpen函數返回的流控制代碼作為參數。產生的轉換頭會告訴ACM源緩衝區和目的緩衝區的地址。ACM不會自動分配記憶體,我們必須自己來申請記憶體。

  l         所有的準備工作基本上完成了,只剩下如何轉換資料了。這是非常簡單的,只需要調用acmStreamConvert函數。AcmStreamConvert函數的參數包括流控制代碼和轉換頭控制代碼。這個函數通過設定轉換頭中的cbDstLengthUsed表明轉換過程中真正被使用的位元組數。

  l         一旦完成了ACM的會話,我們必須釋放使用的全部資源。轉換頭用acmStreamUnprepareHeader函數來釋放,流用acmStreamClose來關閉。

 選擇格式

  正如前面提到的,在開始轉換以前必須先設定輸入輸出格式。TWaveFormatEX記錄(聲明在MMSystem.pas單元中),它僅僅指定了位元速率,頻率等等。除非我們只打算在不同的PCM格式間進行轉換,否則TWaveFormatEX是不夠用的。下面是它的替代格式:

TACMWaveFormat = packed record

     case integer of

       0 : (Format : TWaveFormatEx);

       1 : (RawData : Array[0..128] of byte);

   end;

  這個變體記錄使我們仍然可以讀取TWaveFormatEX結構資料,同時RawData提供了足夠的空間來容納其它Codec需要的額外資訊。

  雖然我們不知道額外資訊的大小,但我們可以使用acmFormatChoose函數來獲得。

  AcmFormatChoose函數只需要一個TACMFormatChooseA類型的參數。這個參數是一個簡單的結構可以包括下列資訊:


 

成員

說明

Pwfx

一個TWaveFormatEX結構指標用來接收結果(這裡我們實際上用的是TACMFormat)。

Cbwfx

接收結果的緩衝區大小。

CbStruct

結構大小。

 

另一個值得一提的成員是fdwStyle, 它包括用來指定格式額外資訊的標誌。特別是下面這個標誌:

 

ACMFORMATCHOOSE_STYLEF_INITTOWFXSTRUCT

 

這個標誌表明pwfx指向的緩衝區已經包括了一個有效格式,當acmFormatChoose函數調用後,會顯示一個格式選擇對話方塊,有效格式將顯示為預設值。

 

什麼情況下無法轉換?

 

一個原因就是一台機器上有的Codec可能另一台機器上沒有。這樣導致了你可以讀取一個聲音格式,但無法產生這個聲音格式。Fraunhoffer IIS MP3 Codec就有這個問題。在Windows 9x 和Windows NT下,我們可以產生MP3檔案,但在Windows 2000卻去掉了這一功能L,結果雖然在Windows2000下我們可以聽MP3,當我們無法產生MP3,除非我們交一筆錢,faint。

 

另一個原因是並非所有的ACM格式可以相互轉換。比如,我們無法在下面的格式間轉化:

 

GSM 8位 單聲道 > MP3 8位 單聲道

 

雖然無法直接轉換,但可以通過中間格式來間接轉換,中間格式通常是PCM格式,這是因為絕大多數Codec都支援PCM格式的轉換。新的轉換途徑就變成了:

 

GSM 8位 單聲道  > PCM 8位 單聲道  > MP3 8位 單聲道

 

而轉換為MP3 16位 立體聲還需要增加一步,就是把8位 PCM格式轉換為16位PCM格式。

 

ACM的潛在本領

 

可能從上面的介紹來看ACM的功能很有限,僅僅是能把一個媒體格式轉換為另一個媒體格式。不過一想到需要自己寫一個可用於Internet的聲音流的編碼解碼器的工作量,比如MP3的壓縮函數,你就會發現ACM真的是個好東東,價格便宜量又足J。

 

同時想像一下有了ACM我們實現一個Internet電話是多麼的簡單,首先從麥克風獲得輸入的聲音資料,壓縮為一個合適的基於低頻寬的流格式,然後通過TCP/IP協議傳到目的電腦。同時,目的電腦接收壓縮的資料,解壓縮,最後通過擴音器播放出來。

 

ACM的潛在本領就在這裡,有相當多的ACM codec是可映射為Wave格式的,這就是說它們可以作為標準的波裝置來即時的播放或記錄音頻。而網路電話的最主要的要求之一就是即時性。

 

比如,我們可以很容易的開啟一個GSM的聲音輸入源,一旦我們從波輸入裝置接收到資料,資料就已經被壓縮好了,可以立即傳輸。同時,一旦通過TCP/IP Socket接收到了資料,我們馬上可以通過波輸出裝置播放之。

 

要注意標準的PCM格式資料對於通過Modem實現即時的語音傳輸來說實在是太大了,而GSM 6.1隻要1.5K/秒就可以達到即時的效果,而16位單聲道的MP3 也僅僅需要2K/秒的頻寬。

 

另外對於MP3格式來說,它可以作為一個播放格式,但它不適合作為輸入格式(因為只有Windows NT平台上的MP3 Codec才支援MP3的編碼),通常我們需要用其它程式手工轉換產生MP3,所以它不適合應用在網路電話上,不過它是非常適合於網路點播的,因為它的壓縮比高,而且音質失真少。

 

原理就是象上面描述的那樣簡單,但很多事情總是說起來容易,做起來難。所以,下面實現了幾個控制項和程式來實際的示範一下。由於代碼比較長,這裡就不詳細列出來了,只簡單的說明一下。

 

控制項

 

l         TACMConverter:這個控制項有兩個作用。第一,它可以在兩個不同媒體格式間轉化資料。第二,這個控制項可以用來指定ACM流的輸入輸出格式。(用右鍵調出控制項的控制項編輯器可以在設計時調用AcmFormatChoose函數顯示格式選擇對話方塊來指定格式)。

l         TACMIn:用來從麥克風接收資料,我們使用標準的PCM格式或其它波輸入裝置支援的格式來記錄資料。

l         TACMOut:這個控制項是用來回放聲音的。NumBuffers屬性可以用來指定開始播放前使用的緩衝區數。這對於即時音頻傳輸意義不大,但對於在Internet上音頻廣播卻是很方便,同時當串連資料波動時可以緩衝額外的音頻資料。

 

示範

 

第一個例子使用TACMConvertor控制項來指定輸入輸出格式,然後開啟一個ACMIn和ACMOut控制項 。麥克風輸入的資料立刻回放,但有一點延遲,來產生一點迴響

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.