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 本身不支持循環播放的問題。
SystemSoundID soundID;
NSString *path = [[NSBundle mainBundle] pathForResource:@"shake" ofType:@"wav"];
AudioServicesCreateSystemSoundID((__bridge CFURLRef)[NSURL fileURLWithPath:path],&soundID);
播放 AudioServicesPlaySystemSound (soundID);
2. AVAudioPlayer 類
#import <AVFoundation/AVFoundation.h>
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創建
我之前講過AVAudio不可以播放網絡URL,但是可以播放NSData,我們似乎受到了啓發,我們可以通過網絡URL去創建NSData,然後再通過AVAudioPlayer來播放NSData,這樣是不是就可以播放網絡音樂了?但是此法並不可取,因爲AVAudioPlayer只能播放一個完整的文件,並不支持流式播放,所以必須是緩衝完才能播放,所以如果網絡文件過大抑或是網速不夠豈不是要等很久?所以播放網絡音頻我們一般用音頻隊列。二、播放器屬性
創建一個AVAudioPlayer以後你就可以對它的各種屬性進行訪問或設置了。
1、音量
player.volume =0.8;//0.0-1.0之間
player.numberOfLoops =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];
}
AVAudioPlayer就介紹到這吧。