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 本身不支援循環播放的問題。以下代碼可以實作一個在程式中循環播放的背景音樂:
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<code>static</code> <code>void</code> <code>completionCallback (SystemSoundID mySSID) {</code>
<code> </code><code>// Play again after sound play completion</code>
<code> </code><code>AudioServicesPlaySystemSound(mySSID);</code>
<code>}</code>
<code>- (</code><code>void</code><code>) playSound {</code>
<code> </code><code>// Get the main bundle for the app</code>
<code> </code><code>CFBundleRef mainBundle;</code>
<code> </code><code>SystemSoundID soundFileObject;</code>
<code> </code><code>mainBundle = CFBundleGetMainBundle ();</code>
<code> </code>
<code> </code><code>// Get the URL to the sound file to play</code>
<code> </code><code>CFURLRef soundFileURLRef = CFBundleCopyResourceURL (</code>
<code> </code><code>mainBundle,</code>
<code> </code><code>CFSTR (</code><code>"background"</code><code>),</code>
<code> </code><code>CFSTR (</code><code>"wav"</code><code>),</code>
<code> </code><code>NULL</code>
<code> </code><code>);</code>
<code> </code><code>// Create a system sound object representing the sound file</code>
<code> </code><code>AudioServicesCreateSystemSoundID (</code>
<code> </code><code>soundFileURLRef,</code>
<code> </code><code>&soundFileObject</code>
<code> </code><code>);</code>
<code> </code><code>// Add sound completion callback</code>
<code> </code><code>AudioServicesAddSystemSoundCompletion (soundFileObject, NULL, NULL,</code>
<code> </code><code>completionCallback,</code>
<code> </code><code>(</code><code>void</code><code>*) self);</code>
<code> </code><code>// Play the audio</code>
<code> </code><code>AudioServicesPlaySystemSound(soundFileObject);</code>
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對象隻能播放一個音頻檔案,如果要同時播放多個音頻,即産生混音則要再建立一個AVAudioPlayer對象來播放,AVAudioPlayer可以播放本地音頻和網絡音頻,但無論是哪種,它都要将整個音頻檔案資料預先加載到記憶體中完畢後,才能開始播放,對于本地的大音頻檔案和網絡上的大音頻檔案(網絡上太大的音頻檔案貌似也播放不成功,蘋果對此有限制)或網速不好的情況下會出現緩存很久的情況,這體驗顯然要注意(是以采用AVAudioPlayer制作本地音樂播放器也會有卡的問題,更别說網絡音樂播放器了,隻能在一些其他應用中播放一些比較小的音效),是以,最好能采用流式播放 要使用 AVAudioPlayer 的對象播放檔案,你隻需為其指定一個音頻檔案并設定一個實作了 AVAudioPlayerDelegate 協定的 delegate 對象。這裡舉一個簡單的例子,和上一個例子一樣,實作一直循環播放的背景音樂:
<code>- (</code><code>void</code><code>) playBackgroundSoundEffect {</code>
<code> </code><code>NSString *soundFilePath =</code>
<code> </code><code>[[NSBundle mainBundle] pathForResource: @</code><code>"background"</code>
<code> </code><code>ofType: @</code><code>"wav"</code><code>];</code>
<code> </code><code>NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];</code>
<code> </code><code>AVAudioPlayer *newPlayer =</code>
<code> </code><code>[[AVAudioPlayer alloc] initWithContentsOfURL: fileURL</code>
<code> </code><code>error: nil];</code>
<code> </code><code>[fileURL release];</code>
<code> </code><code>self.player = newPlayer;</code>
<code> </code><code>[newPlayer release];</code>
<code> </code><code>[self.player prepareToPlay];</code>
<code> </code><code>[self.player setDelegate: self];</code>
<code> </code><code>self.player.numberOfLoops = -1; </code> <code>// Loop playback until invoke stop method</code>
<code> </code><code>[self.player play];</code>
可以看到,隻要将 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 這類經過壓縮的音頻檔案時,在連接配接處可能出現一定的間隔時間。
iOS4 背景播放音樂最簡單的方法
打開你的XXX-Info.plist增加一項
Required background modes 預設是數組,在其下增加一個元素 App plays audio
然後在你播放音樂的代碼前增加一行
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
注意模拟器是不能展示背景效果的,不要實作了功能還以為沒實作,請用真機測試
3.MPMusicPlayerController 引入MediaPlayer.framework
MPMusicPlayerController隻能播放本地ipod中的歌曲,無法播放其他地方和網絡上的資源,播放本地時能實作不卡播放的效果,但一般在那種純音樂播放器中用的比較多(酷狗、酷我等)
播放在App中的音頻時,使用AVAudioPlayer;
播放音樂庫中的檔案時,使用MPMusicPlayerController;
雖然MPMusicPlayerController 能夠播放本地音頻檔案,但其主要用途還是內建現有的音樂庫多媒體檔案
4. Audio Queue Services
如果以上兩種音頻播放的解決方案都無 法滿足你的需求,那麼我想你肯定需要使用 Audio Queue Services。使用 Audio Queue Services 對音頻進行播放,你可以完全實作對聲音的控制。例如,你可以在聲音資料從檔案讀到記憶體緩沖區後對聲音進行一定處理再進行播放,進而實作對音頻的快速/慢速 播放的功能。
因為 Audio Queue Services 相對複雜很多,Apple 官方已經把它整理為一本書了,具體可以參考 Audio Queue Services Programming Guide 和 SpeakHere 的程式示例。
播放流音頻源代碼:http://code4app.com/ios/線上音頻播放器/4ffc45006803fa9e19000000
播放本地音樂采用SpeakHere中的音頻隊列模式播放,可以減少預加載時間,播放線上音樂采用Audio Streamer 這是老外寫的一個線上音頻流類 上述code4app的那個例子即可采用 發現伺服器不用特殊部署,隻要是一個音樂檔案就行
5. OpenAL
OpenAL 是一套跨平台的開源的音頻處理接口,與圖形處理的 OpenGL 類似,它為音頻播放提供了一套更加優化的方案。它最适合開發遊戲的音效,用法也與其他平台下相同。
iPhone 支援 OpenAL 1.1,我沒有在實際開發中使用過,具體的文檔可以參考 OpenAL 的網站 http://openal.org和 oalTouch 的程式示例。
網絡上志同道合,我們一起學習網絡安全,一起進步,QQ群:694839022