天天看點

iOS 播放音頻的幾種方法

Phone 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建立

我之前講過AVAudio不可以播放網絡URL,但是可以播放NSData,我們似乎受到了啟發,我們可以通過網絡URL去建立NSData,然後再通過AVAudioPlayer來播放NSData,這樣是不是就可以播放網絡音樂了?但是此法并不可取,因為AVAudioPlayer隻能播放一個完整的檔案,并不支援流式播放,是以必須是緩沖完才能播放,是以如果網絡檔案過大抑或是網速不夠豈不是要等很久?是以播放網絡音頻我們一般用音頻隊列。

二、播放器屬性

建立一個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];

}

 AVAudioPlayer就介紹到這吧。

繼續閱讀