iPhone OS 主要提供以下了幾種播放音頻的方法:
- System Sound Services
- AVAudioPlayer 類
- Audio Queue Services
- OpenAL
1. System Sound Services
System Sound Services 是最底層也是最簡單的聲音播放服務,調用 AudioServicesPlaySystemSound 這個方法就可以播放一些簡單的音頻文件,使用此方法只適合播放一些很小的提示或者警告音,因為它有很多限制:
■ 聲音長度要小於 30 秒
■ In linear PCM 或者 IMA4 (IMA/ADPCM) 格式的
■ 打包成 .caf, .aif, 或者 .wav 的文件
■ 不能控制播放的進度
■ 調用方法后立即播放聲音
■ 沒有循環播放和立體聲控制
另外,它還可以調用系統的震動功能,方法也很簡單。具體的代碼可以參考官方的示例 SysSound
,但是官方的示例只有一些簡單的用法,從文檔中我們發現可以通過 AudioServicesAddSystemSoundCompletion 方法為音頻播放添加 CallBack 函數,有了 CallBack 函數我們可以解決不少問題,比如可以克服 System Sound Services 本身不支持循環播放的問題。
2. AVAudioPlayer 類
AVAudioPlayer 是 AVFoundation.framework 中定義的一個類,所以使用要先在工程中引入 AVFoundation.framework。我們可以把 AVAudioPlayer 看作是一個高級的播放器,它支持廣泛的音頻格式,主要是以下這些格式:
■ AAC
■ AMR(AdaptiveMulti-Rate, aformatforspeech)
■ ALAC(AppleLossless)
■ iLBC(internetLowBitrateCodec, anotherformatforspeech)
■ IMA4(IMA/ADPCM)
■ linearPCM(uncompressed)
■ µ-lawanda-law
■ MP3(MPEG-1audiolayer3
AVAudioPlayer 可以播放任意長度的音頻文件、支持循環播放、可以同步播放多個音頻文件、控制播放進度以及從音頻文件的任意一點開始播放等,更高級的功能可以參考 AVAudioPlayer 的文檔 。要使用 AVAudioPlayer 的對象播放文件,你只需為其指定一個音頻文件並設定一個實現了 AVAudioPlayerDelegate 協議的 delegate 對象。
只要將 AVAudioPlayer 的 numberOfLoops 屬性設為負數,音頻文件就會一直循環播放直到調用 stop 方法。
AVAudioPlayer 同樣支持 Callback,這是 AVAudioPlayerDelegate 的一個可選 delegate 方法:
- (void ) audioPlayerDidFinishPlaying: (AVAudioPlayer *) player successfully: (BOOL ) flag { if (player == self .player && flag == YES) { NSLog(@"Playback finish." ); } }
另外,你可以隨時控制 AVAudioPlayer 對象的播放、暫停以及停止,通過判斷對象的狀態,分別調用 play、pause 和 stop 方法即可:
- (IBAction) playOrPause: (id ) sender { // if playing, pause if (self .player.playing) { [self .player pause]; // if stopped or paused, start playing } else { [self .player play]; }
雖然 AVAudioPlayer 可以播放很多格式,但是我們在實際開發過程中還是最好使用一些沒有壓縮的格式,比如 WAVE 文件,這樣可以減少系統處理單元的資源占用,以便更好的完成程序的其他功能。另外,在使用 AVAudioPlayer 連續播放 mp3 這類經過壓縮的音頻文件時,在連接處可能出現一定的間隔時間。
3. Audio Queue Services
如果以上兩種音頻播放的解決方案都無法滿足你的需求,那么我想你肯定需要使用 Audio Queue Services。使用 Audio Queue Services 對音頻進行播放,你可以完全實現對聲音的控制。例如,你可以在聲音數據從文件讀到內存緩沖區后對聲音進行一定處理再進行播放,從而實現對音頻的快速/慢速 播放的功能。
因為 Audio Queue Services 相對復雜很多,Apple 官方已經把它整理為一本書了,具體可以參考 Audio Queue Services Programming Guide 和 SpeakHere 的程序示例。
4. OpenAL
OpenAL 是一套跨平台的開源的音頻處理接口,與圖形處理的 OpenGL 類似,它為音頻播放提供了一套更加優化的方案。它最適合開發游戲的音效,用法也與其他平台下相同。
本篇主要講AVAudioPlayer,
AVAudioPlayer類封裝了播放單個聲音的能力。播放器可以用NSURL或者NSData來初始化,要注意的是NSURL不可以是網絡url而必須是本地文件url,因為AVAudioPlayer不具備播放網絡音頻的能力。
一個AVAudioPlayer只能播放一個音頻,如果你想混音你可以創建多個AVAudioPlayer實例,每個相當於混音板上的一個軌道。
一、創建一個播放器
AVAudioPlayer *player = [[AVAudioPlayeralloc] initWithContentsOfURL:[NSURLfileURLWithPath:[[NSBundlemainBundle] pathForResource:@"星月神話" ofType:@"mp3"]] error:nil];//使用本地URL創建 AVAudioPlayer *player = [[AVAudioPlayer alloc] initWithData:Data error:nil];//使用NSData創建
二、播放器屬性
創建一個AVAudioPlayer以后你就可以對它的各種屬性進行訪問或設置了。
1、音量
player.volume =0.8;//0.0-1.0之間
2、循環次數player.numberOfLoops =3;//默認只播放一次
3、播放位置player.currentTime =15.0;//可以指定從任意位置開始播放
4、聲道數
NSUInteger channels = player.numberOfChannels;//只讀屬性
5、持續時間
NSTimeInterval duration = player.duration;//獲取持續時間
6、儀表計數
player.meteringEnabled =YES;//開啟儀表計數功能
[playerupdateMeters];//更新儀表計數
三、播放聲音[player prepareToPlay];//分配播放所需的資源,並將其加入內部播放隊列
[playerplay];//播放
[playerstop];//停止
四、代理方法
這個類對應的AVAudioPlayerDelegater的委托方法。 audioPlayerDidFinishPlaying:successfully: 當音頻播放完成之后觸發。當播放完成之后,可以將播放按鈕的文本重新回設置成:Play Audio File
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { //播放結束時執行的動作 [audioButton setTitle:@"Play Audio File" forState:UIControlStateNormal]; }
- (void)audioPlayerDecodeErrorDidOccur:(AVAudioPlayer *)player error:(NSError *)error; { //解碼錯誤執行的動作 }
- (void)audioPlayerBeginInterruption:(AVAudioPlayer *)player; { //處理中斷的代碼 } audioPlayerEndInterruption:,當程序被應用外部打斷之后,重新回到應用程序的時候觸發。在這里當回到此應用程序的時候,繼續播放音樂。 - (void)audioPlayerEndInterruption:(AVAudioPlayer *)player { [audioPlayer play]; }