在面向iPhone開發遊戲之前我對音訊格式真的非常陌生。我只知道.WAVs和.MP3之間的區別,但是我卻怎麼都說不出.AAC或.CAF到底是什麼,或者在Mac上轉換音訊檔案的最佳方法是什麼。

後來我發現如果想要在iPhone上開發遊戲,我們就必須真正理解檔案,資料格式,檔案間的轉換,錄音以及API等基本元素。

sweet_sound(from dryicons.com)

sweet_sound(from dryicons.com)

檔案格式和資料格式

我們必須清楚每個音訊檔案都是由兩部分內容所構成:它的檔案格式(或者音訊容器)以及它的資料格式(或者音訊編碼)。

檔案格式(或音訊容器)是用於形容檔案本身的格式。我們可以通過多種不同的方法為真正的音訊資料編碼。例如CAF檔案便是一種檔案格式,它能夠包含MP3格式,線性PCM以及其它資料格式的音訊。

資料格式(或音訊編碼)

我們將從音訊編碼開始闡述(而不是檔案格式),因為編碼是最重要的環節。

以下是iPhone所支援的資料格式及其相關描述:

AAC:AAC是指“高階音訊編碼”,可以說它MP3格式的延續。你可能會想這種格式將壓縮最初的聲音而儲存在磁碟中,所以會降低原先聲音的質量。但是通常情況下我們很難注意到質量的降低,並且這主要是取決於我們所設定的位元率。實際上AAC的壓縮做得比MP3好多了,特別是在位元率低於每秒128千位元的情況下。

HE-AAC:HE-AAC是AAC的超集,HE表示“高效率”。HE-AAC是對於低位元率音訊(如流式音訊)的優化。

AMR:AMR代表“自適應多速率”,是語音優化的另一種編碼優化格式,能夠突出極低位元率音訊。

ALAC:同樣也被稱為“Apple Lossless”,它是一種可以不破壞質量而壓縮音訊的編碼。實際上它大概會壓縮原始資料的40-60%。再加上演算法是經過精心設計的,所以我們可以以較快的速度解壓資料,這非常適合像iPod或iPhone等裝置。

iLBC:這是另一種優化語音的編碼,有益於IP語音和流媒體格式。

IMA4:這是一種壓縮格式,將對16位體的音訊檔案進行4:1的壓縮。這是面向iPhone裝置的一種重要編碼。

線性PCM:這是表示線性脈衝編碼調製,主要是描寫用於將模擬聲音資料轉換成數字格式的技術。簡單地說也就是未壓縮的資料。因為資料是未壓縮的,所以我們便可以最快速地播放出音訊,而如果空間不是問題的話這便是iPhone音訊的優先程式碼選擇。

μ-law和a-law:這是兩種交替式編碼,能夠將模擬資料轉換成數字格式,但是比起線性PCM擁有更強的語音優化效果。

MP3:這是我們最熟悉也是最喜歡的一種格式。這麼多年以來MP3仍是最受歡迎的一種格式,而iPhone也支援這種格式。

所以我們該使用哪種格式?

在這一大串列表中我們必須選出幾個優選編碼格式。為了做出選擇我們首先需要清楚:

我們可以無需壓縮或簡單壓縮而同時播放線性PCM,IMA4等格式並且不會出現任何問題。

而對於更加高階的壓縮方法如AAC,MP3以及ALAC,iPhone也擁有相關硬體能夠幫助我們快速壓縮這些資料——但是問題在於它一次只能處理一種檔案。所以如果你一次希望播放2種以上的編碼,你就不得不對其進行壓縮,而這將耗費更多時間。

為了選擇合適的資料格式,你需要遵循以下規則:

如果空間不是問題的話,我們便可以使用線性PCM對任何內容進行編碼。這不僅是播放音訊最快速的方法,並且你也可以同時播放多種聲音且不會遭遇任何CPU資源問題。

如果空間是問題所在的話,你便可以使用AAC編碼去播放背景音樂而使用IMA4編碼去製造音效。

線性PCM的各種變體

關於線性PCM最需要注意的一點便是它應該算是iPhone首選的未壓縮資料格式。基於資料的儲存方式線性PCM具有多種變體。我們可以根據大端位元組序或小端位元組序,浮點數或整數以及不同位體去儲存資料。

在此我們需要清楚的是在iPhone中線性PCM的優選變體是小端位元組序整數16位體,或簡稱為LEI16。同時這也不同於Mac OSX中的優選變體。因為我們總是在Mac上創造音訊檔案,所以我們最好能夠仔細檢查檔案並將其轉換成iPhone中的優選格式。

檔案格式(或音訊容器)

iPhone支援許多檔案格式,包括MPEG-1(.mp3),MPEG-2 ADTS(.aac),AIFF,CAF以及WAVE。但是通常情況下我們都會選擇CAF,因為它能夠同時包含所有iPhone所支援的編碼,並且它也是iPhone中的優先檔案格式選擇。

位元率

在此我們必須強調音訊編碼中一個非常重要的術語:位元率。

位元率是指一個音訊檔案所佔有的每秒位元組數。像AAC或MP3等編碼便能夠指定位元組數而壓縮音訊檔案。當你降低每秒鐘的位元組數時,你同時也在降低音訊的質量。

你可以根據特定的音訊檔案選擇位元率——嘗試不同的位元率並判斷哪一種最能夠匹配檔案規格和音訊質量。如果你的檔案主要與語音有關,你便可以選擇較低的位元率。

以下是一些較常見的位元率:

每秒32千位元率:調頻廣播質量

每秒48千位元率:較長的語音部落格中常見的頻率

每秒64千位元率:標準長度的語音部落格中常見的頻率

每秒96千位元率:調頻收音機的質量

每秒128千位元率:MP3音樂最常見的位元率

每秒160千位元率:音樂家和敏感聽眾的優先選擇

每秒192千位元率:數字無線電廣播的質量

每秒320千位元率:和CD的質量沒兩樣了

每秒500千至1411千位元率:無失真的音訊編碼,如線性PCM

取樣頻率

我們最後需要提到的一個術語便是:取樣頻率。

當我們將模擬訊號轉換成數字格式時,取樣頻率是指我們多長時間抽取一次聲波去創造數字訊號。

通常情況下44100赫茲便是最常用的取樣頻率,因為這與CD音訊的頻率相同。

轉換和記錄

這是iPhone開發者需要掌握的製作音訊要素的第二部分。

在上文中我提到了檔案格式與資料格式間的區別,以及iPhone所支援的各種格式。而接下來我將說說如何在這兩種格式間進行轉換。

Afplay,AFConvert以及AFInfo

在Mac上轉換音訊檔案非常簡單,因為Mac中有三個內建命令列工具:afplay,afconvert以及afinfo。

最容易使用的便是afplay——你只要通過終端輸入音訊檔名它便能夠將其播放出來。當你想要將檔案壓縮成各種位元率以對比效果時這種工具便非常方便。

接下來便是afinfo——當你輸入音訊檔名時它將呈現出檔案格式,資料格式,位元率以及其它有用的資訊,如下:

afinfo pew-pew-lei.caf
File:           pew-pew-lei.caf
File type ID:   caff
Data format:     1 ch,  44100 Hz, ‘lpcm’ (0x0000000C)
16-bit little-endian signed integer no channel layout.
estimated duration: 0.560 sec
audio bytes: 49408
audio packets: 24704
audio 24704 valid frames + 0 priming + 0 remainder = 24704
bit rate: 705600 bits per second
packet size upper bound: 2
audio data file offset: 4096
optimized
sound check:
approximate duration in seconds          0.56
—-

從以上程式碼中我們可以看出這個檔案擁有一個CAF檔案型別,一個16位體小端位元組序帶符號整數資料格式(LEI16),一個44100赫茲的樣本頻率以及每秒705600的位元率。

最後我們來說說最實用的工具:afconvert。afconvert也是最容易使用的一種,我們只需要發出如下命令列便可:

afconvert -d [out data format] -f [out file format] [in file] [out file]

為了將檔案轉換成iPhone首選的未壓縮音訊編碼(提示:小端位元組序整數16位線性PCM變體,也就是LEI16)以及首選的檔案格式(提示:核心音訊檔案格式,也就是CAFF),你就需要發出如下命令列:

afconvert -d LEI16 -f ‘caff’ input_file.xxx output_file.caf

需要注意的是我並未在此指出輸入檔案的副檔名,因為afconvert已經能夠幫助我們判別任何音訊檔案型別並進行適當的轉換,所以它也算是帶有音訊檔案格式的音訊資料格式。

另外一點需要注意的便是:你可以在輸入/輸出檔案前新增-b選項以設定位元率。舉個例子來說吧,在此我將檔案儲存為每秒32千位元率,隨後又改為每秒128千位元率:

afconvert -d aac -f ‘caff’ -b 131072 background-music-lei.caf test_128.caf
afconvert -d aac -f ‘caff’ -b 32768 background-music-lei.caf test_32.caf

在Mac上記錄音訊

以下我將列出在Mac上製作應用音樂和聲音的一些好方法。

首先是GarageBand。GarageBand能夠幫助我們更容易組合一些預製的樂器聲,如鼓聲,吉他聲等,並如此創作出一首簡單的音樂。而如果你自己懂音樂的話你便可以將自己的演奏錄下來並創造出一些更酷的作品。

Garage Band Full(from raywenderlich)

Garage Band Full(from raywenderlich)

我發現“使用內建軟體工具”是最有效的一種方法。

而當我們記錄下滿意的歌曲後我們需要將其傳送到iTunes上,然後“記錄在Finder(遊戲邦注:Mac OS和Mac OS X中預設的應用程式,能讓使用者管理檔案,檔案,磁碟,網路,以及啟動其他的應用程式)”中以抓取檔案方便今後的使用。

我發現GarageBand並不能記錄下最簡單的音效。所以我便轉向了免費的音訊程式Audacity(遊戲邦注:一款跨平臺、免費開源的錄音、編輯聲音編輯器)。你可以將其插在麥克風上然後記錄下你的聲音,並輕鬆地將其儲存下來。

Audacity(from raywenderlich)

Audacity(from raywenderlich)

不要忘記當你錄下自己的聲音時它們將被儲存為16位體大端位元組序帶符號整數(BEI16),所以在整合到應用前一定要將其轉換為LEI16。

如果你不懂音樂的話也可以在The Freesound Project網站的創作共用許可版塊中找到一些合適的聲音授權,或者也可以聘請專業的音樂人士幫忙!

使用程式設計方式播放音訊

這是iPhone開發者需要掌握的製作音訊要素的第三部分。

之前我們已經談到了檔案和資料格式間的區別以及如何在Mac上轉換並記錄音訊。現在我們將嘗試著在手機上播放音訊。

在Mac上播放音訊的方法有很多,包括System Sound Services,AVAudioPlayer,Audio Queue Service以及OpenAL。如果沒有外部支援庫的話,最簡單的方法應該是System Sound Services和AVAudioPlayer——所以讓我們開始討論你何時想要(或不想要)使用哪種方法以及如何使用它們。

System Sound Services

System Sound Services為我們提供了一種非常簡單的方法以播放音訊檔案。而我們只需要如下進行操作:

NSString *pewPewPath = [[NSBundle mainBundle]
pathForResource:@”pew-pew-lei” ofType:@”caf”];
NSURL *pewPewURL = [NSURL fileURLWithPath:pewPewPath];
AudioServicesCreateSystemSoundID((CFURLRef)pewPewURL, &_pewPewSound);
AudioServicesPlaySystemSound(_pewPewSound);

沒有什麼比這個還簡單了。但是這一方法也存在許多缺陷:

它只支援音訊資料格式的線性PCM或IMA4.

它只支援音訊檔案格式CAF,AIF或WAV。

聲音的長度只能壓縮在30秒以內。

AVAudioPlayer

如果你想要以一個AAC或MP3格式的音訊檔案作為背景音樂的話你又該怎麼做?另外一種簡單的方法便是使用AVAudioPlayer類播放音樂。很大程度上看來這也是一種非常簡單的方法:

NSError *error;
_backgroundMusicPlayer = [[AVAudioPlayer alloc]
initWithContentsOfURL:backgroundMusicURL error:&error];
[_backgroundMusicPlayer prepareToPlay];
[_backgroundMusicPlayer play];

而AVAudioPlayer的缺陷則是速度非常慢。如果你按壓一個按鈕並嘗試著使用AVAudioPlayer去觸發一個聲音,此時便會出現一個非常明顯的延遲。而如果你不在乎這種延遲的話(就像啟動背景音樂),AVAudioPlayer便是一種非常合適的選擇。

同時我們還需牢記:

1.如果你正在播放背景音樂,請一定要檢檢視看是否已經播放了其它音訊,從而確保不會同時執行兩個層面的音樂!

2.如果一個電話接入而使用者選擇了“拒絕”後,你需要預設設定你的AVAudioPlayer為停止。你可以通過再次登入AVAudioPlayerDelegate而重新開啟AVAudioPlayer並在audioPlayerEndInterruption方法中再次播放音樂。

示例程式碼

我組合了一些示例程式碼以呈現System Sound Services和AVAudioPlayer的使用。這些程式碼不僅能夠演示出應用程式介面,同時也擁有一些特別的節拍和超酷的太空氛圍。

OpenAL

如果你正在編寫一款遊戲或應用並希望在較低延遲性的前提下通過低細粒度去控制音訊,那麼你便不會使用上述的方法。相反地,你可能會選擇使用OpenAL這個iPhone支援的跨平臺音訊庫。

OpenAL其實並不好理解。但是幸運的是Alex Restrepo已經在gehacktes.net網站上為我們呈現出一個非常棒的例子,並使用OpenAL創造了一個出色的聲音引擎庫,所以我們便能夠在自己的專案中使用這一引擎庫,或以它作為參考。

還有一個選擇便是Cocos2D遊戲庫,其中包含了一個非常容易使用的聲音引擎能夠創造出噼啪聲的音效。

總結

以上這些便是我對於iPhone音訊程式設計的相關內容,但是需要注意的是我只觸及一些基礎元素而未進行深入研究。我希望本文能夠為那些剛剛接觸音訊理念的開發者提供一些幫助。

遊戲邦注:原文發表於2010年2月5日,所涉事件和資料均以當時為準。

via:遊戲邦/gamerboom