多媒體音頻播放簡單介紹

概述

基礎知識-音頻編解碼,音頻格式,音頻會話(session)

  • ios軟硬件音頻編解碼器
  • 音頻會話(Audio Sessions)

播放音頻

  • 使用iPod庫訪問播放音頻項目
  • 使用系統聲音服務播放UI聲音效果或者調用震動
  • 使用AVAudioPlayer 播放音樂更輕松
  • 使用音頻隊列服務播放控制聲音
  • 使用OpenAL播放定位聲音

音頻錄制

  • 使用AVAudioRecorder 類錄制音頻
  • 使用Audio Queue Services 錄制

解析流式音頻

ios中的音頻單元支持

ios音頻最佳實戰

  • 使用音頻提示
  • ios的首先音頻格式

今天學習開源框架LFLiveKit,看到音頻錄制的部分,該部分是采用的AVFoundation.frame中AVAudio.framework框架來完成的。以前沒有接觸過這部分,因此這里摘錄出來仔細研究學習。

首先想學習框架,肯定官網是最佳的場所,我搜尋了下官方文檔,找到這一點相關知識multimedia Programming guide。一點點學習嘛,先學會這塊再說。

概述

基礎知識-音頻編解碼,音頻格式,音頻會話(session)

ios的音頻開發,了解下ios設備的硬件和軟件架構的有關知識是很必要的。

ios軟硬件音頻編解碼器

為確保音頻的最佳性能和質量,我們需要選擇正確的音頻格式和音頻編解碼器類型。從ios3.0開始,大多數音頻格式可以使用軟件編碼和解碼(錄制和播放)。軟件編碼器支持多個聲音的同時播放,但是需要大量的cpu開銷。

硬件輔助解碼可以提供很好的性能,但是就不能支持同時播放多個聲音了。如果我們需要在應用程序中最大化視頻幀速率,最小的cpu音頻開銷,那么我們需要使用未壓縮的音頻或者IMA4格式,也可以使用硬件幫助解碼壓縮的音頻。

下表是ios設備上可用的播放音頻編解碼器。

Audio decoder/playback format Hardware-assisted decoding Software-based decoding
AAC (MPEG-4 Advanced Audio Coding) Yes Yes, starting in iOS 3.0
ALAC (Apple Lossless) Yes Yes, starting in iOS 3.0
HE-AAC (MPEG-4 High Efficiency AAC) Yes -
iLBC (internet Low Bitrate Codec, another format for speech) - Yes
IMA4 (IMA/ADPCM) - Yes
Linear PCM (uncompressed, linear pulse-code modulation) - Yes
MP3 (MPEG-1 audio layer 3) Yes Yes, starting in iOS 3.0
μ-law and a-law - Yes

通過上面的表格,我們知道同時支持硬編碼和軟編碼的格式有aac alac 和 mp3.

使用硬件輔助編碼時,設備一次只能播放一種支持格式的單個實例。例如,如果我們使用硬件編解碼器播放立體聲mp3音樂,那么第二個同步mp3聲音將使用軟件編碼(硬件只能編碼一個,)。同樣,我們無法使用硬件同時編碼aac和alac格式音樂。

要是要要播放多種聲音,或者在ipod在后臺播放音樂,我們應該使用線型PCM(未壓縮)或者IMA4(壓縮)音頻。

要了解運行時設備上可用的硬件和軟件編解碼器。我們可以看kAudioFormatProperty_HardwareCodecCapabilities常量來了解。

如何確定在運行時aac硬件編碼器的可用性。
ios4.0以及更高版本支持使用擴展音頻文件和音頻轉換器api進行硬件脫機編碼。這就是硬編碼
注意 ios3.1 只支持擴展音頻文件api。
要檢查acc硬件編碼器的可用性,使用下列代碼

Boolean IsAACHardwareEncoderAvailable(void)
{
    Boolean isAvailable = false;
    OSStatus error;
    
    // get an array of AudioClassDescriptions for all installed encoders for the given format
    // the specifier is the format that we are interested in - this is 'aac ' in our case
    UInt32 encoderSpecifier = kAudioFormatMPEG4AAC;
    UInt32 size;
    
    error = AudioFormatGetPropertyInfo(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier),
                                       &encoderSpecifier, &size);
    if (error) {
        printf("AudioFormatGetPropertyInfo kAudioFormatProperty_Encoders error %lu %4.4s\n", error, (char*)&error);
        return false;
        
    }
    
    UInt32 numEncoders = size / sizeof(AudioClassDescription);
    AudioClassDescription encoderDescriptions[numEncoders];
    error = AudioFormatGetProperty(kAudioFormatProperty_Encoders, sizeof(encoderSpecifier), &encoderSpecifier, &size, encoderDescriptions);
    if (error) {
        printf("AudioFormatGetProperty kAudioFormatProperty_Encoders error %lu %4.4s\n", error, (char*)&error); return false; }
    
    for (UInt32 i=0; i < numEncoders; ++i) {
        if (encoderDescriptions[i].mSubType == kAudioFormatMPEG4AAC &&
            encoderDescriptions[i].mManufacturer == kAppleHardwareAudioCodecManufacturer) isAvailable = true;
    }
    
    return isAvailable;
}
        

總結下ios如何支持單個或者多個播放音頻格式

  • 線型PCM 和IMA4(IMA/ADPCM) 我們可以在ios中同時播放多個線型的PCM或者IMA4 音樂,而不會產生cpu 性能問題。對于ILBC語音質量格式以及 μ-law 和 a-law 壓縮格式也是一樣的,當用壓縮格式,需要檢查音質以確保滿足需求。
  • AAC,HE-AAC,MP3和ALAC(Apple Lossless) 對AAC,HE-AAC,MP3和ALAC(Apple Lossless)的播放可以在設備上使用高效的硬件輔助編碼,但這些編碼都共享一條硬件路徑。因此,硬件編碼只能播放這些格式之一的單個實例。

AAC,HE-AAC,MP3和ALAC播放的單一硬件路徑對“播放”風格應用程序(如虛擬鋼琴)有影響。如果用戶正在ipod的應用程序中播放這三種格式之一的歌曲,那么我們的應用程序將通過軟編碼進行編碼。

下表記錄在ios設備上可用的錄制音頻編解碼器

Audio encoder/recording format Hardware-assisted encoding Software-based encoding
AAC (MPEG-4 Advanced Audio Coding) Yes, starting in iOS 3.1 for iPhone 3GS and iPod touch (2nd generation) Yes, starting in iOS 3.2 for iPad Yes, starting in iOS 4.0 for iPhone 3GS and iPod touch (2nd generation)
ALAC (Apple Lossless) - Yes
iLBC (internet Low Bitrate Codec, for speech) - Yes
IMA4 (IMA/ADPCM) - Yes
Linear PCM (uncompressed, linear pulse-code modulation) - Yes
μ-law and a-law - Yes

通過上表,我們知道了錄制音頻,同時支持硬件和軟件編碼的之后aac格式編碼

音頻會話(Audio Sessions)

ios音頻會話api允許我們定義應用程序的一般音頻行為。相關api在 Audio Session Services Reference and AVAudioSession Class Reference。這些使用這些api,可以完成下列對音頻的操作:

  • 設備靜音
  • 音頻是否在屏幕鎖定時停止
  • 當音頻開始的時候,其他音頻是否應該繼續播放或者靜音。

音頻會話api還會響應用戶操作,例如插入或者播出耳機,以及使用設備聲音硬件的事件,例如時鐘和日歷鬧鐘以及來電。

音頻會話的三個編程功能如下表

音頻會話功能 描述
設置categories category是標示應用程序的一組音頻行為的key。通過設置category,我們可以向ios表明我們的音頻意圖,例如屏幕鎖定時我們的音頻是否應該繼續。響應中斷中描述的六個類別。我們也可以微調某些category的行為,例如可以看 Use Modes to Specialize the Category.
處理中斷和路由更改 當音頻中斷,中斷結束以及硬件音頻路由發生變化時,音頻會話會發布通知。通過這些通知,我們可以優雅的響應較大音頻環境中的更改-例如由于來電而導致的中斷。更多細節可以看處理音頻硬件路由改變Audio Guidelines By App Type.
優化硬件性能 我們可以查詢音頻會話以發現運行的應用程序的設備的特征,例如硬件采樣率,硬件通道數以及音頻輸入是否可用有關詳細細節可看Optimizing for Device Hardware.

有兩個用于處理音頻會話的接口:

我們可以混合和匹配AVFoundation和audio sessionServices中的音頻會話代碼-他們兩個是相互兼容的。

音頻會話帶有一些默認行為,我們可以使用這些開始開發。

例如,使用默認音頻會話時,當自動鎖定時間超時且屏幕鎖定時,應用程序中的音頻將停止。 如果要確保在屏幕鎖定的情況下繼續播放,請在應用程序的初始化代碼中包含以下行:

NSError *setCategoryErr = nil;
NSError *activationErr  = nil;
[[AVAudioSession sharedInstance]
              setCategory: AVAudioSessionCategoryPlayback
                    error: &setCategoryErr];
[[AVAudioSession sharedInstance]
                setActive: YES
                    error: &activationErr];

AVAudioSessionCategoryPlayback category 確保當屏幕鎖屏的時候可以繼續播放音頻。

如何處理來電或者時鐘以及日歷鬧鐘導致的中斷取決于我們使用的音頻技術。見下表

Audio technology How interruptions work
AV Foundation framework AVAudioPlayer和AVAudioRecorder類為中斷開始和結束提供委托方法。實現這些方法來更新用戶界面,并且我們可以在中斷后,回復暫停的播放。系統在中斷時會自動的暫停播放和錄制,并在恢復播放或者錄制時候重新激活音頻會話。如果要在應用程序啟動時保存和恢復播放位置,請在中斷和應用程序退出時保存播放位置。
Audio Queue Services, I/O audio unit 我們可以通過該技術處理中斷。我們需要保存播放盒錄制位置,并且中斷結束后重新激活音頻會話。實現AVAudioSession中斷的委托代理方法或者編寫監聽回調函數-通知
OpenAL 使用openAL 進行播放,需要實現AVAudioSession中斷委托方法或編寫中斷回調函數-與使用音頻隊列服務時一樣的。這里需要注意的時,委托或者回調必須重新管理openAL上下文
System Sound Services 用系統聲音服務播放的音樂在終端開始時保持靜音。如果終端結束,他們可以自動的再次使用。應用程序不能影響使用此播放技術的聲音的中斷行為

每個ios應用程序(極少數例外)都應該主動管理其音頻會話。有關如何執行此操作的完整說明,可以看這里Audio Session Programming Guide

播放音頻

本節主要介紹如何播放在 iPod library access, System Sound Services, Audio Queue Services, t AV Foundation framework和OpenAL.中聲音。

使用iPod庫訪問播放音頻項目

在ios3.0開始,ipad 庫訪問可以應用程序播放用戶的歌曲,有聲讀物或者音頻播客。api設計使用基本播放非常簡單,同時還支持高級搜索和播放控制。

下圖展示應用程序有兩種方法來檢索媒體項目。左側顯示的媒體項目選擇器是一個易于使用的預打包視圖控制器,其行為類似于內置ipod應用程序的音樂選擇界面。對于許多應用來說,這已經足夠了。如果選擇器不能滿足我們的需求,那么就可以選擇右邊的medai query。他支持來自ipod庫的基于謂詞的項目規范。


如何將媒體項目添加到應用程序的完成實例,可以參考 *iPod Library Access Programming Guide。例子可以參考 AddMusic工程

使用系統聲音服務播放UI聲音效果或者調用震動

想要播放用戶界面聲音效果(如按鈕點擊),或在支持他的設備上調用振動,請使用系統服務聲音服務。詳細講解在System Sound Services Reference。我們可以在 iOS Dev Center中找到簡單的代碼。

注意:使用聲音系統服務播放的聲音不受使用音頻會話的配置限制。因此,我們無法使system sound services 音頻的行為和應用程序中的其他音頻行為保持一致。這是避免將system sound services用于除預期用途之外的任何音頻的最重要原因。

AudioServicesPlaySystemSound 函數能讓我們可以非常簡單的播放簡短的聲音文件。簡單必定帶來一些限制。我們的聲音文件必須是滿足下列要求:

  • 持續時間不能超過30s
  • 采用pcm 或者IMA4(IMA/ADPCM)格式
  • 打包在.caf .aif 或者 .wav文件中

此外,我們可以使用AudioServicesPlaySystemSound函數時:

  • 聲音播放使用當前系統音量,沒有可用的編程音量控制
  • 聲音立刻播放
  • 無法進行循環和立體聲定位
  • 同時不放不可用:我們一次只能播放一種聲音

有個類似的AudioServicesPlayAlertSound函數,可以用來播放短聲音作為警報。如果用戶已將其設備配置為在“震動設置”中的震動,那么調用此功能除了播放聲音文件之外還會調用振動。

注意:應用程序無法使用系統提供的警報聲和系統提供的用戶界面聲音效果。例如,使用kSystemSoundID_UserPreferredAlert常量作為AudioServicesPlayAlertSound函數的參數將不會播放任何內容。

舉例如下:

  // Get the main bundle for the app
    CFBundleRef mainBundle = CFBundleGetMainBundle ();
    
    // Get the URL to the sound file to play. The file in this case
    // is "tap.aif"
    CFURLRef soundFileURLRef;
    soundFileURLRef  = CFBundleCopyResourceURL(mainBundle,CFSTR ("2"),CFSTR ("caf"),NULL);
    SystemSoundID soundFileObject =0 ;
    AudioServicesCreateSystemSoundID (soundFileURLRef,
    &soundFileObject);
    self.soundFileObject = soundFileObject;

播放音樂

    AudioServicesPlaySystemSound (self.soundFileObject);

如何獲取.caf 文件呢?
通過終端命令,將簡單的mp3文件轉換,命令如下
afconvert /Users/Mina/Desktop/1.mp3 /Users/Mina/Desktop/2.caf -d ima4 -f caff -v

在典型的使用中,包含偶爾或者重復播放音樂,我們需要保留聲音的ID對象,知道應用程序退出釋放對象。如果我們知道只使用一次,那我們可以播放聲音后里面銷毀對象,釋放內存。

在支持振動的ios設備上運行的app可以使用 system sound services 觸發該共功能。使用kSystemSoundID_Vibrate標識符指定vibrate(振動) 選項。要觸發她,使用AudioServicesPlaySystemSound函數。

#import <AudioToolbox/AudioToolbox.h>
#import <UIKit/UIKit.h>
- (void) vibratePhone {
    AudioServicesPlaySystemSound (kSystemSoundID_Vibrate);
}

iPod touch不支持此功能。

使用AVAudioPlayer 播放音樂更輕松

AVAudioPlayer 類提供了一個簡單的oc接口,用于播放聲音。如果我們的app不需要立體聲定位或者精確同步,并且不需要播放從網絡流捕獲的音頻。我們可以使用此類播放。
該類可以完成下列功能:

  • 播放任何持續時間的聲音
  • 播放文件或內存緩存區的聲音
  • 循環聲音
  • 同時播放多個聲音(沒有精確同步)
  • 控制正在播放的每個聲音的相對播放水平
  • 尋找聲音文件中的特定點,該文件吃吃快進和快退等功能
  • 獲取音頻的電源數據,該數據可以用來音頻水平的測量。

AVAudioPlayer 類允許我們在ios中使用可用的任何音頻格式播放音樂。具體可以參考 AVAudioPlayer Class Reference

如何配置音頻播放器

  • 1.指定一個音樂文件給音頻播放器
  • 2.準備播放音頻播放器,獲取所需的硬件資源
  • 3.指定音頻播放器委托對象,該對象處理中斷以及播放完成的事件。

具體可看下面例子

-(void)avplay{
    NSString *soundFilePath =
    [[NSBundle mainBundle] pathForResource: @"1"
                                    ofType: @"mp3"];
    
    NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
    AVAudioPlayer *newPlayer =
    [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
                                           error: nil];
    self.player = newPlayer;
    [self.player prepareToPlay];
    [self.player setDelegate: self];
}

-(void)buttonEvent:(id)button{
    [self.player play];
}

我們可以設置音量

[self.player setVolume: 1.0];    // available range is 0.0 through 1.0

對于更多信息,可以看AVAudioPlayer Class Reference

使用音頻隊列服務播放控制聲音

音頻隊列服務增加了AVAudioPlayer的可用的播放功能。使用音頻隊列服務進行播放可以實現下來功能:

  • 精確的安排播放音樂,允許同步
  • 在煮個緩沖區的基礎上精確的控制音量
  • 使用音頻文件流服務播放您從六中捕獲的音頻。

音頻隊列服務允許我們播放任何可用的音頻格式音樂。該技術不僅可以播放,也可以用來錄制。
對于更多細節,可以看 Audio Queue Services Programming GuideAudio Queue Services Reference。 簡單代碼可以看SpeakHere

創建音頻隊列對象
創建音頻隊列對象進行播放音樂,用一下幾步:

  • 1.創建數據結構以管理音頻對象所需的信息,例如我們需要播放的數據的音頻格式。
  • 2.定義用于管理音頻隊列緩沖區的回調函數。回調使用音頻文件服務來讀取我們需要播放的文件。
  • 3.使用AudioQueueNewOutput函數實例化播放音頻隊列

代碼如下:

static const int kNumberBuffers = 3;
// Create a data structure to manage information needed by the audio queue
struct myAQStruct {
    AudioFileID                     mAudioFile;
    CAStreamBasicDescription        mDataFormat;
    AudioQueueRef                   mQueue;
    AudioQueueBufferRef             mBuffers[kNumberBuffers];
    SInt64                          mCurrentPacket;
    UInt32                          mNumPacketsToRead;
    AudioStreamPacketDescription    *mPacketDescs;
    bool                            mDone;
};
// Define a playback audio queue callback function
static void AQTestBufferCallback(
    void                   *inUserData,
    AudioQueueRef          inAQ,
    AudioQueueBufferRef    inCompleteAQBuffer
) {
    myAQStruct *myInfo = (myAQStruct *)inUserData;
    if (myInfo->mDone) return;
    UInt32 numBytes;
    UInt32 nPackets = myInfo->mNumPacketsToRead;
 
    AudioFileReadPackets (
        myInfo->mAudioFile,
        false,
        &numBytes,
        myInfo->mPacketDescs,
        myInfo->mCurrentPacket,
        &nPackets,
        inCompleteAQBuffer->mAudioData
    );
    if (nPackets > 0) {
        inCompleteAQBuffer->mAudioDataByteSize = numBytes;
        AudioQueueEnqueueBuffer (
            inAQ,
            inCompleteAQBuffer,
            (myInfo->mPacketDescs ? nPackets : 0),
            myInfo->mPacketDescs
        );
        myInfo->mCurrentPacket += nPackets;
    } else {
        AudioQueueStop (
            myInfo->mQueue,
            false
        );
        myInfo->mDone = true;
    }
}
// Instantiate an audio queue object
AudioQueueNewOutput (
    &myInfo.mDataFormat,
    AQTestBufferCallback,
    &myInfo,
    CFRunLoopGetCurrent(),
    kCFRunLoopCommonModes,
    0,
    &myInfo.mQueue
);

這段代碼直接復制到工程中會發生錯誤的.想要詳細了如何使用應該看SpeakHere,改工程中包含以上代碼。

因為這篇文章只是講解音頻知識的大概。所以不會過多設計技術細節。

控制播放水平
音頻隊列對象為我們提供了兩種控制播放級別的方法。
最直接的方式是用下列代碼

Float32 volume = 1;    // linear scale, range from 0.0 through 1.0
AudioQueueSetParameter (
    myAQstruct.audioQueueObject,
    kAudioQueueParam_Volume,
    volume
);

這里說的播放水平就是音量大小啦。
我們還可以使用AudioQueueEnqueueBufferWithParameters函數設置音頻隊列緩沖區的播放級別。這可以讓我們指定音頻隊列來設置,產生的效果是,改隊列攜帶了這次操作,當該隊列進行播放是,該設置才能生效。

以上兩種方式更改音頻隊列將一直有效。

提高播放水平

我們可以通過下列方式獲取當前播放水平:

  • 通過將kAudioQueueProperty_EnableLevelMetering屬性設置為true來啟用音頻隊列對象的計量
  • 查詢音頻隊列對象的kAudioQueueProperty_CurrentLevelMeter

此屬性的值是AudioQueueLevelMeterState結構的數組,每個通道一個。

typedef struct AudioQueueLevelMeterState {
    Float32     mAveragePower;
    Float32     mPeakPower;
};  AudioQueueLevelMeterState;

播放多個音樂

要同時播放多個聲音,我們需要為每個聲音創建一個播放音頻隊列對象。對于每個音頻隊列,使用AudioQueueEnqueueBufferWithParameters函數安排第一個音頻緩沖區同時啟動。

從iOS 3.0開始,幾乎所有支持的音頻格式都可用于同步播放 - 即所有可以使用軟件解碼播放的格式,如表1-1所示。 對于處理器效率最高的多重播放,請使用線性PCM(未壓縮)或IMA4(壓縮)音頻。

使用OpenAL播放定位聲音

OpenAL框架中的ios中的提供的開源openAL 音頻api提供了一個優化的界面,用于在播放期間定位立體生成中的聲音。播放,定位和移動聲音就想其他的平臺上一樣。openAL 還可以讓你混合聲音。openAL使用I / O單元進行播放,從而實現最低延遲。

出于以上原因,openAL是基于ios的設備上播放游戲應用程序中的聲音的最佳選擇。但是,openAL也是一般ios應用程序音頻播放需求的不錯的選擇。

對于更多的使用,我們可以看OpenAL FAQ for iPhone OS。demo 可以看oalTouch

音頻錄制

ios 可以使用AVAudioRecorder類和Audio Queue Services 進行音頻錄制。這些接口可以根據需要連接音頻硬件,管理內存和使用編解碼器。錄制音頻的格式見上面的表。

錄制音頻可以在系統定義的輸入水平進行。系統可以從用戶選擇的音頻源來獲取輸入信息-例如內置的麥克風,或者如果耳機連接,那么輸入源也可以是耳機麥克風或者其他輸入源。

使用AVAudioRecorder 類錄制音頻

在ios 中錄制聲音的最簡單的方式是使用AVAudioRecorder類。該類提供了一個高度簡化的oc接口,可以輕松的提供諸如暫停恢復錄制和處理音頻中斷等復雜操作。同時,我們也可以控制錄音的格式。

準備錄音需要以下步驟:

  • 1.指定一個聲音文件地址
  • 2.設置音頻會話
  • 3.配置音頻錄制的初始化的狀態

app在啟動的時候就對此部分進行配置是很好的時機。如下

- (void) audioRecorder {
    
    NSString *tempDir = NSTemporaryDirectory ();
    NSString *soundFilePath =
    [tempDir stringByAppendingString: @"sound.caf"];
    
    NSURL *newURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
    self.soundFileURL = newURL;
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    audioSession.delegate = self;
    [audioSession setActive: YES error: nil];
}

要處理中斷和錄制完成,我們需要增加AVAudioSessionDelegate和AVAudioRecorderDelegate協議的實現。如果我們的應用程序也需要播放,我們需要參考AVAudioPlayerDelegate Protocol Reference

開啟錄制代碼如下

- (IBAction) recordOrStop: (id) sender {
    
        
        [[AVAudioSession sharedInstance]
         setCategory: AVAudioSessionCategoryRecord
         error: nil];
        
        NSDictionary *recordSettings =
        [[NSDictionary alloc] initWithObjectsAndKeys:
         [NSNumber numberWithFloat: 44100.0], AVSampleRateKey,
         [NSNumber numberWithInt: kAudioFormatAppleLossless], AVFormatIDKey,
         [NSNumber numberWithInt: 1], AVNumberOfChannelsKey,
         [NSNumber numberWithInt: AVAudioQualityMax],
         AVEncoderAudioQualityKey,
         nil];
        
        AVAudioRecorder *newRecorder =
        [[AVAudioRecorder alloc] initWithURL: self.soundFileURL  settings: recordSettings
                                       error: nil];
        self.soundRecorder = newRecorder;
        self.soundRecorder.delegate = self;
        [self.soundRecorder prepareToRecord];
        [self.soundRecorder record];    
}

想要了解更多AVAudioRecorder信息可以看AVAudioRecorder Class Reference

使用Audio Queue Services 錄制

用Audio Queue Services錄制音頻,首先我們需要實例化一個錄制音頻隊列對象,提供一個回調函數。回調將傳入的音頻數據存儲在內存中以供立即使用,或者將其寫入文件以進行長期存儲。

與回放功能一樣,我們可以通過查詢其kAudioQueueProperty_CurrentLevelMeter屬性從音頻隊列對象獲取當前錄制音頻級別。

對于更多細節如何使用Audio Queue Services錄制音頻,可以參考Recording Audio inAudio Queue Services Programming Guide

解析流式音頻

要播放流式音頻內容,例如來說網絡的內容,我們需要用Audio Queue Services中的音頻文件流服務。音頻文件流服務從網絡比特流中的公共音頻文件容器格式解析音頻數據包和元數據。我們也可以使用他來解析磁盤文件中的數據包和元數據。

在ios中,我們可以解析的音頻文件和比特流數據形式如下

  • MPEG-1 Audio Layer 3, used for .mp3 files
  • MPEG-2 ADTS, used for the .aac audio data format
  • AIFC
  • AIFF
  • CAF
  • MPEG-4, used for .m4a, .mp4, and .3gp files
  • NeXT
  • WAVE

檢索到音頻數據包后,我們可以播放ios中支持的任何格式的恢復聲音。

想了解更多流信息,參考Audio File Stream Services Reference

ios中的音頻單元支持

ios提供了一組音頻處理插件,稱為音頻單元,可以在任何的應用程序中使用。Audio Unit框架中的接口允許我們打開,連接和使用這些音頻單元。

使用audio unit框架的功能,我們需要將audio toolbox 框架添加到xocde工程中。 #import <AudioToolbox/AudioToolbox.h>

下列表就是在ios提供的 audio units

Audio unit Description
iPod Equalizer unit iPod EQ單元的類型是kAudioUnitSubType_AUiPodEQ,它提供一個簡單的,基于預設的均衡器,可以在app中使用。有關如何使用此音頻單元,參考Mixer iPodEQ AUGraph Test
3D Mixer unit 3D混音器單元的類型是kAudioUnitSubType_AU3DMixerEmbedded,可以讓我們混合多個音頻流,指定立體聲輸出平移,操作播放速率等。OpenAL構建于此音頻單元之上,提供更適合游戲應用程序的更高級API
Multichannel Mixer unit 多通道混音器單元,類型是kAudioUnitSubType_MultiChannelMixer,允許將多個單聲道或者立體聲音頻流混合到單個立體聲中。他還支持每個輸入的左/右平移。
Remote I/O unit 遠程I/O單元,類型是kAudioUnitSubType_RemoteIO,連接到音頻輸入和輸出硬件,并支持實時I.O. aurioTouch
Voice Processing I/O unit 語音處理I/O,單元類型是kAudioUnitSubType_VoiceProcessingIO,具有I/O一單元的特性,并為雙向通信添加了回聲抑制和其他功能
Generic Output unit 通用輸出單元,類型是kAudioUnitSubType_GenericOutput,支持轉換為線型PCM格式和從線型PCM格式的轉換。;可以用于啟動和停止 graph
Converter unit 轉換器單元的類型是kAudioUnitSubType_AUConverter,允許我們將音頻數據從一種格式轉換成領一種格式。通常使用包含轉換器單元的遠程I/O單元獲得此音頻單元的功能

更多細節參考 Audio Unit Hosting Guide for iOS

簡單demo aurioTouch

ios音頻最佳實戰

使用音頻提示
Tip Action
適當使用壓縮視頻 對于aac,mp3,alac音頻,可以使用硬件輔助編碼器進行解碼。雖然有效,但一次僅限一個音頻流。如果需要同時播放多個聲音,請使用IMA4(壓縮)或者線型PCM(未壓縮)格式存儲這些聲音
轉換為我們需要的數據格式和文件 Mac OS X中的afconvert工具允許我們轉換為各種音頻數據格式和文件類型。 具體用法可以用man afconvert 或者 Preferred Audio Formats in iOS
評估音頻內存問題 使用音頻隊列服務播放聲音時,我們需要編寫一個回調,將短段音頻數據發送到音頻隊列的緩沖區。在默寫情況下,最好將整個聲音文件加載到內存中進行播放,從而最大限度的減少磁盤訪問。在其他情況下,一次加載足夠的數據以保持緩沖區滿是最好的。
通過限制采樣率,位深度和通道來減小音頻文件大小 采樣率和每個采樣的位數會直接影響音頻文件的大小。如果您需要播放許多此類聲音或者長時間聲音,需要考慮減少這些值以減少音頻數據的內存占用。例如,我們可以使用32KHZ或者更低的采樣率,而不是使用44.2KHZ的采樣率來獲取合理的音質效果。使用單聲道音頻而不是立體聲(雙聲道)可減少文件大小。對于每個聲音asset,需要考慮單聲道是否可以滿足需求
選擇合適的技術 如果需要方便的高階界面來定位立體聲場中的聲音或者低延遲播放時,可以使用openAL。要解析文件或網絡流總的音頻數據包,請使用 Audio File Stream Services。要簡單播放單個或者多個聲音,請使用AVAudioRecorder類。對于音頻聊天,可以使用語音處理I/O單元。要播放從用戶的iTunes資料庫同步的音頻資源,使用iPod Library Access。當我們需要音頻播放警報和用戶界面音效時,我們使用Core Audio’s System Sound Services。對于其他音頻應用程序,包含流式音頻的播放,精確同步以及對傳入音頻數據包的訪問,使用Audio Queue Services.
低延遲的代碼 要獲得盡可能低的播放延遲,使用openAL或者直接使用I/O單元
ios的首先音頻格式

對于未壓縮(最高質量的)音頻,請使用導報在caf文件中的16位小端線型PCM 音頻格式。我們可以使用afconvert 命令行工具來mac os x中將音頻文件轉換為此格式

/usr/bin/afconvert -f caff -d LEI16 {INPUT} {OUTPUT}

afconvert 工具允許我們轉換為各種音頻數據格式和文件類型。我們可以用 man afconvert 查看其功能。或者afconvert -h 查看

 man afconvert

對于一次播放一個聲音的壓縮音頻,以及當不需要與ipod應用程序同時播放音頻時,可以使用CAF或者m4a文件中打包成aac格式。

當需要同時播放多個聲音時候,為了減少內存使用量,使用IMA4(IMA/ADPCM)壓縮。這樣可以減少文件大小,但在解壓縮過程中對CPU的影響最小。與線型PCM數據一樣,在caf 文件中打包IMA4 數據。


Audio Session Programming Guide

multimedia Programming guide

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。