Core Audio音頻基礎(chǔ)概述

Core Audio

Core Audio提供了數(shù)字音頻服務(wù)為iOS與OS X, 它提供了一系列框架去處理音頻.

1.Core Audio

Core Audio中包含我們最常用的Audio Toolbox與Audio Unit框架.

  • 使用Audio Queue做錄制,播放,暫停,循環(huán)與同步音頻
  • 使用Audio File, Converter, Codec Services去從磁盤讀取與寫入以及執(zhí)行音頻轉(zhuǎn)換等功能.
  • 使用Audio Unit與Audio Processing Graph在應(yīng)用程序中管理音頻單元.在OS X中可以自定義audio units.
  • 使用Music Sequencing Services播放基于MIDI控制的音頻數(shù)據(jù)
  • 使用Core Audio Clock Services用于音頻和MIDI同步以及時(shí)間格式管理
  • 使用System Sound Services播放系統(tǒng)聲音與界面的音效.

Core Audio在iOS中針對移動(dòng)平臺的計(jì)算資源作出了優(yōu)化,同時(shí),音頻服務(wù)必須嚴(yán)格由系統(tǒng)進(jìn)行管理,特別是HAL與I/O Kit,然而Apple也提供了只在iOS平臺中才有的服務(wù),如Audio Session Service將幫助我們管理音頻上下文.


2.iOS_Core Audio
3.CoreAudioLevel

1. Digital Audio與Linear PCM

PCM是最常用的無損壓縮數(shù)字音頻格式數(shù)據(jù),根據(jù)采樣率以規(guī)則間隔測量模擬(真實(shí)世界)數(shù)字音頻信號并將每個(gè)采集到的樣本轉(zhuǎn)換為數(shù)值來創(chuàng)建PCM數(shù)據(jù).如標(biāo)準(zhǔn)光盤(CD)音頻使用44.1 kHz的采樣率,16位整數(shù)描述每個(gè)樣本 - 構(gòu)成分辨率或位深度。

  • sample:一個(gè)采樣點(diǎn)是對單聲道采集到聲音的數(shù)值
  • frame:一幀數(shù)據(jù)是一組時(shí)間一致的samples,如雙聲道聲音文件中一幀有兩個(gè)samples,一個(gè)左聲道,一個(gè)右聲道.
  • packet:一個(gè)或多個(gè)連續(xù)幀的集合.在線性PCM中,一個(gè)packet總是單幀.在其他壓縮格式中,一個(gè)packet定義給定音頻數(shù)據(jù)格式的最小有意義的幀組蔼两。

iOS中使用integer與fixed-point音頻數(shù)據(jù),目的是在處理音頻數(shù)據(jù)時(shí)增加計(jì)算速度,減小電池能耗.iOS也提供了來自Audio Converter Services的Converter audio unit服務(wù).

iOS與OS X中,Core Audio提供了最常用的文件格式用于存儲域播放音頻數(shù)據(jù).

2.Audio Unit

Apple針對移動(dòng)平臺對iOS的Audio Unit作出了效率與性能優(yōu)化,在開發(fā)中我們必須將audio unit靜態(tài)編譯進(jìn)APP,所以無法使用別的APP中的Audio Unit.

3.HAL(Hardware Abstraction Layer)

大多情況下,我們無法直接與HAL進(jìn)行交互,Apple提供了一個(gè)特別的audio unit,即OS X中的AUHAL, iOS中的AURemoteIO, 我們可以通過它們讓音頻與硬件交互.

4.Properties, Scopes, and Elements

Core Audio接口中使用property管理對象的行為與狀態(tài).

  • 屬性通常用易記憶的關(guān)鍵字格式,如kAudioFilePropertyFileFormat or kAudioQueueDeviceProperty_NumberChannels.
  • 屬性值適用于特定的數(shù)據(jù)類型,如void*, Float64, AudioChannelLayout...
  • Core Audio對象有一個(gè)內(nèi)部結(jié)構(gòu),其中每一部分都有屬于自己的屬性,如一個(gè)audio unit對象都有一個(gè)input scope, output scope, global scope. 每個(gè)scope由一個(gè)或多個(gè)elements(類似于音頻總線)組成.

5.回調(diào)函數(shù)

Core Audio中常用回調(diào)函數(shù)以實(shí)現(xiàn)音頻數(shù)據(jù)通信,回調(diào)函數(shù)常有一下功能

  • 提供給應(yīng)用程序音頻數(shù)據(jù)(如:用麥克風(fēng)進(jìn)行錄制,將麥克風(fēng)采集的數(shù)據(jù)通過回調(diào)函數(shù)傳給使用者)
  • 從應(yīng)用程序中請求音頻數(shù)據(jù)(如:播放回調(diào))
  • 監(jiān)聽某個(gè)對象狀態(tài)的變化

為了去使用回調(diào)函數(shù),我們需要做以下兩件事情

  • 注冊回調(diào)函數(shù)(如實(shí)現(xiàn)錄制,播放回調(diào),需要我們在初始化時(shí)提供一個(gè)函數(shù))
  • 實(shí)現(xiàn)回調(diào)函數(shù)的功能.(實(shí)現(xiàn)初始化時(shí)提供的函數(shù))

Note: 在OC中,回調(diào)函數(shù)是一個(gè)C語言形式的函數(shù),我們回調(diào)OC本類對象作為對象傳入其中, 所以回調(diào)函數(shù)中不能直接引用self.xxx,需要借助傳入的OC對象去實(shí)現(xiàn)本類的功能.

6. 音頻數(shù)據(jù)格式

Core Audio封裝了音頻數(shù)據(jù)格式侵浸,我們只需要對給定結(jié)構(gòu)體賦正確的參數(shù)即可铜犬。

struct AudioStreamBasicDescription {
    Float64 mSampleRate;
    UInt32  mFormatID;
    UInt32  mFormatFlags;
    UInt32  mBytesPerPacket;
    UInt32  mFramesPerPacket;
    UInt32  mBytesPerFrame;
    UInt32  mChannelsPerFrame;
    UInt32  mBitsPerChannel;
    UInt32  mReserved;
};
typedef struct AudioStreamBasicDescription  AudioStreamBasicDescription;

struct  AudioStreamPacketDescription {
    SInt64  mStartOffset;
    UInt32  mVariableFramesInPacket;
    UInt32  mDataByteSize;
};
typedef struct AudioStreamPacketDescription AudioStreamPacketDescription;

注意匣掸,上面結(jié)構(gòu)體中mReserved是Apple的保留參數(shù)鸭叙,必須為0. 其他一些參數(shù)在特定情況下也需為0霹娄,如:壓縮音頻格式每個(gè)sample使用不同數(shù)量的bits能犯。對于這些格式鲫骗,mBitsPerChannel成員的值為0。

  • 為AudioStreamBasicDescription賦值

你可以手動(dòng)為ASBD的成員賦值踩晶,如果有些值是你不知道的执泰,可以賦0,Core Audio將自動(dòng)選擇適當(dāng)?shù)闹怠?/p>

  • 標(biāo)準(zhǔn)的音頻數(shù)據(jù)格式

iOS: 線性PCM 16bit integer, Noninterleaved linear PCM 8.24bit 定點(diǎn)samples

struct AudioStreamBasicDescription {
    mSampleRate       = 44100.0;
    mFormatID         = kAudioFormatLinearPCM;
    mFormatFlags      = kAudioFormatFlagsAudioUnitCanonical;
    mBitsPerChannel   = 8 * sizeof (AudioUnitSampleType);                    // 32 bits
    mChannelsPerFrame = 2;
    mBytesPerFrame    = mChannelsPerFrame * sizeof (AudioUnitSampleType);    // 8 bytes
    mFramesPerPacket  = 1;
    mBytesPerPacket   = mFramesPerPacket * mBytesPerFrame;     // 8 bytes
    mReserved         = 0;
};

7. Magic Cookie

在Core Audio中渡蜻,magic cookie表示被附加到壓縮音頻數(shù)據(jù)(文件或流)中的元數(shù)據(jù)(metadata)术吝。元數(shù)據(jù)為解碼器提供了正確解碼文件或流所需要的詳細(xì)信息。Core Audio可以復(fù)制茸苇,讀取排苍,使用元數(shù)據(jù)包含的信息。

下面的例子展示了如何將一個(gè)文件中magic cookie拷貝提供給audio queue.

- (void) copyMagicCookieToQueue: (AudioQueueRef) queue fromFile: (AudioFileID) file {
 
    UInt32 propertySize = sizeof (UInt32);
 
    OSStatus result = AudioFileGetPropertyInfo (
                            file,
                            kAudioFilePropertyMagicCookieData,
                            &propertySize,
                            NULL
                        );
 
    if (!result && propertySize) {
 
        char *cookie = (char *) malloc (propertySize);
 
        AudioFileGetProperty (
            file,
            kAudioFilePropertyMagicCookieData,
            &propertySize,
            cookie
        );
 
        AudioQueueSetProperty (
            queue,
            kAudioQueueProperty_MagicCookie,
            cookie,
            propertySize
        );
 
        free (cookie);
    }
}

8.Audio Data Packets

音頻數(shù)據(jù)包(packet)是一個(gè)或多個(gè)幀的集合学密,對于特定音頻格式淘衙,它是有意義的最小幀集合,因此它是最佳表示一段時(shí)間音頻數(shù)據(jù)的單位腻暮。

  • CBR(固定的比特率):PCM,IMA,ADPCM,所有packet具有相同size.
  • VBR(可變的比特率):AAC,MP3,Apple Lossless,所有packet都具有相同的幀數(shù)彤守,但是每一幀中的位數(shù)不同。
  • VFR(可變的幀率): 每個(gè)包中具有不同的幀數(shù)哭靖,沒有這種類型常用的格式具垫。

在CBR,VBR的格式中试幽,對于給定的音頻文件或流筝蚕,每秒鐘的包數(shù)是固定的,

9.數(shù)據(jù)格式轉(zhuǎn)換

使用audio converter可以改變音頻采樣率铺坞,交錯(cuò)或不交錯(cuò)起宽,以及壓縮與未壓縮數(shù)據(jù)格式相互轉(zhuǎn)換。

  • 將壓縮數(shù)據(jù)格式(如AAC)轉(zhuǎn)成線性PCM格式
  • 將線性PCM格式轉(zhuǎn)成其他格式
  • 在16位signed integer線性PCM與8.24定點(diǎn)PCM間相互轉(zhuǎn)換康震。

10.音頻文件

Core Audio中使用Audio File Service為創(chuàng)建與訪問音頻文件及包含在其中元數(shù)據(jù)提供了一個(gè)強(qiáng)大的抽象燎含。我們不僅可以使用文件的ID,type,數(shù)據(jù)格式,還可以添加標(biāo)記腿短,循環(huán),回放等等功能绘梦。

  • 創(chuàng)建一個(gè)音頻文件
    • 確定文件路徑(CFURL/NSURL)
    • 確定文件標(biāo)識符(ex CAF:kAudioFileCAFType)
    • 放在文件中的ABSD橘忱。
AudioFileCreateWithURL (
    audioFileURL,
    kAudioFileCAFType,
    &audioFormat,
    kAudioFileFlags_EraseFile,
    &audioFileID   // the function provides the new file object here
);

  • 打開一個(gè)音頻文件
    使用AudioFileOpenURL函數(shù)打開一個(gè)文件,提供URL,文件類型卸奉,訪問權(quán)限成功后返回一個(gè)文件ID,使用這個(gè)ID以及常用函數(shù)可以檢索我們需要的文件信息钝诚。下面列舉了一些常用函數(shù)
kAudioFilePropertyFileFormat
kAudioFilePropertyDataFormat
kAudioFilePropertyMagicCookieData
kAudioFilePropertyChannelLayout

當(dāng)一個(gè)VBR文件過大時(shí),檢索信息速度會較慢榄棵,可以使用kAudioFilePropertyPacketSizeUpperBound and kAudioFilePropertyEstimatedDuration.這兩個(gè)函數(shù)快速獲取近似值凝颇。

  • 讀寫文件

    • 讀寫包僅僅針對VBR數(shù)據(jù)
    • 使用基于包的操作更容易計(jì)算時(shí)間
  • 擴(kuò)展
    Core Audio提供了一個(gè)的API潘拱,稱為擴(kuò)展音頻文件服務(wù)。該接口包含音頻文件服務(wù)和音頻轉(zhuǎn)換器服務(wù)中的基本功能拧略,提供與線性PCM之間的自動(dòng)數(shù)據(jù)轉(zhuǎn)換

  • iPhone 支持的Audio file格式

Format name Format filename extensions
AIFF .aif,.aiff
CAF .caf
MPEG-1,layer 3 .mp3
MPEG-2 or MPEG-4 ADTS .aac
MPEG-4 .m4a, .mp4
WAV .wav
AC-3 (Dolby Digital) .ac3
Enhanced AC-3 (Dolby Digital Plus) .ec3

iOS與OS X中原生音頻文件格式為CAF(Core Audio Format),它可以支持平臺中任意音頻數(shù)據(jù)格式芦岂。它沒有大小限制,可以支持多種元數(shù)據(jù)垫蛆,如聲道信息禽最,文本注釋等

11.音頻流

與音頻文件不同,我們無法確定一個(gè)audio file stream(音頻流)的開始與結(jié)束點(diǎn).因?yàn)槲覀兺峭ㄟ^網(wǎng)絡(luò)接受音頻流數(shù)據(jù),開始與結(jié)束的時(shí)機(jī)取決于用戶的交互,并且,音頻流數(shù)據(jù)也無法保證一定可以獲取,因?yàn)榫W(wǎng)絡(luò)傳輸中可能會存儲在丟幀,暫停等等情況.

Audio File Service可以通過解析(parse)讓我們使用音頻流.通過回調(diào)函數(shù)獲取parse到的一系列音頻數(shù)據(jù).

12.Audio Sessions: 配合Core Audio工作

在iOS中,有時(shí)我們需要處理高優(yōu)先級任務(wù),如接電話,如果當(dāng)前APP正在播放視頻,我們必須做出符合用戶期望的事情以協(xié)調(diào)APP與系統(tǒng)電話.Audio Session對象充當(dāng)了兩者之間的一個(gè)中介.每個(gè)iPhone應(yīng)用程序只有一個(gè)audio session,通過配置其屬性以使用.

開始之前,我們要明確下面幾個(gè)問題

  • 如何讓應(yīng)用程序響應(yīng)一些意外中斷,如接電話
  • 你打算讓你的音頻與其他應(yīng)用程序中的音頻混合起來,還是打算對它們做靜音操作
  • 應(yīng)用程序如何響應(yīng)音頻線路改變,如用戶插拔耳機(jī)

為了解決上面的問題,我們需要配置audio session使用如下特性

Audio Session feature Description
Categories 一個(gè)category標(biāo)識著一組音頻行為的鍵,通過設(shè)置分類,可以表明音頻的行為,如鎖屏?xí)r是否應(yīng)該繼續(xù)播放音頻.
Interruptions and route changes 當(dāng)音頻被中斷或音頻線路發(fā)生改變時(shí),audio session將發(fā)送一個(gè)通知,通過接收通知以作出相應(yīng)響應(yīng).
Hardware characteristics 通過audio session可以查詢當(dāng)前設(shè)備的一些硬件信息,如采樣率,聲道數(shù),輸入源設(shè)備等
  • Audio Session默認(rèn)行為
    • 當(dāng)用戶將手機(jī)按鍵中的靜音撥動(dòng)時(shí),音頻將會被靜音
    • 當(dāng)用戶按下鎖屏鍵時(shí),音頻會被靜音
    • 當(dāng)你的音頻啟用時(shí),當(dāng)前正在播放的其他應(yīng)用程序的音頻會被靜音

以上行為是audio session默認(rèn)分類(kAudioSessionCategory_SoloAmbientSound)的行為

  • 中斷:停用與激活(Deactivation and Activation)
    默認(rèn)的audio session中缺少一個(gè)重要功能就是在中斷后無法恢復(fù).audio session有兩個(gè)重要狀態(tài):激活,停用.音頻僅能夠在激活狀態(tài)下使用.

啟動(dòng)時(shí),默認(rèn)的audio session是激活狀態(tài),然而,如果有電話打進(jìn)來(interruption),audio session馬上處于停用狀態(tài)且應(yīng)用程序音頻停止.如果用戶選擇忽略當(dāng)前電話,你的應(yīng)用程序繼續(xù)運(yùn)行,但是audio session仍是未激活狀態(tài),音頻無法繼續(xù)工作.

如果應(yīng)用程序中使用OpenAL, I/O unit, Audio Queue Services,我們必須寫一個(gè)監(jiān)聽中斷的回調(diào)函數(shù),在中斷結(jié)束后重新激活audio session.

  • 決定輸入源是否可用

使用錄制功能的APP是否能錄制取決于當(dāng)前選擇的硬件音頻輸入端,使用kAudioSessionProperty_AudioInputAvailable可以測試當(dāng)前輸入端是否可用

UInt32 audioInputIsAvailable;
UInt32 propertySize = sizeof (audioInputIsAvailable);
 
AudioSessionGetProperty (
    kAudioSessionProperty_AudioInputAvailable,
    &propertySize,
    &audioInputIsAvailable // A nonzero value on output means that
                           // audio input is available
);

  • 使用Audio Session

應(yīng)用程序僅有一個(gè)audio session分類在同一時(shí)間(此規(guī)則的一個(gè)例外是使用System Sound Services播放的音頻 - 用于警報(bào)和用戶界面聲音效果的API。此類音頻始終使用最低優(yōu)先級的音頻會話類別),

13.使用AVAudioPlayer播放

如果你的應(yīng)用程序不需要雙聲道,精確同步以及播放網(wǎng)絡(luò)流音頻,可以使用AVAudioPlayer類實(shí)現(xiàn)簡單的音頻播放.

以下使用范圍

  • 播放任意時(shí)間段音頻
  • 從文件或內(nèi)存中播放音頻
  • 循環(huán)音頻
  • 同時(shí)播放多個(gè)音頻
  • 控制正在播放每個(gè)聲音相對播放水平
  • 尋找音頻文件中特定點(diǎn),支持快進(jìn)快退
  • 獲取音量
NSString *soundFilePath =
                [[NSBundle mainBundle] pathForResource: @"sound"
                                                ofType: @"wav"];
 
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath: soundFilePath];
 
AVAudioPlayer *newPlayer =
                [[AVAudioPlayer alloc] initWithContentsOfURL: fileURL
                                                       error: nil];
[fileURL release];
 
self.player = newPlayer;
[newPlayer release];
 
[self.player prepareToPlay];
[self.player setDelegate: self];

- (void) audioPlayerDidFinishPlaying: (AVAudioPlayer *) player
                        successfully: (BOOL) flag {
    if (flag == YES) {
        [self.button setTitle: @"Play" forState: UIControlStateNormal];
    }
}

- (IBAction) playOrPause: (id) sender {
 
    // if already playing, then pause
    if (self.player.playing) {
        [self.button setTitle: @"Play" forState: UIControlStateHighlighted];
        [self.button setTitle: @"Play" forState: UIControlStateNormal];
        [self.player pause];
 
    // if stopped or paused, start playing
    } else {
        [self.button setTitle: @"Pause" forState: UIControlStateHighlighted];
        [self.button setTitle: @"Pause" forState: UIControlStateNormal];
        [self.player play];
    }
    
    [self.player setVolume: 1.0];    // available range is 0.0 through 1.0

14.錄制與播放 Audio Queue Services

Audio Queue Services提供了一種低開銷,直接的方式去錄制和播放音頻,它使你的應(yīng)用程序使用硬件(麥克風(fēng)與揚(yáng)聲器)錄制與播放并且無需了解硬件接口.它也讓我們使用復(fù)雜的編解碼器而無需了解編解碼器的工作原理.

Audio Queue提供了更精確的定時(shí)播放以支持預(yù)定播放與同步,你可以使用它去同步多個(gè)音頻播放隊(duì)列,同時(shí)播放聲音,獨(dú)立控制每個(gè)隊(duì)里的音量以及循環(huán)播放.

Audio Queue與AVAudioPlayer兩者是在iPhone上播放音頻的唯一方式

  • 錄制與播放的回調(diào)函數(shù)

通過屬性與回調(diào)函數(shù)讓我們與audio queue對象間交互.對于錄制,我們通過回調(diào)函數(shù)接收音頻數(shù)據(jù).


5.record_audioqueue

對于播放回調(diào),當(dāng)你的音頻播放隊(duì)列需要播放一個(gè)音頻數(shù)據(jù)時(shí)它將被調(diào)用.你的回調(diào)函數(shù)將從磁盤讀取指定數(shù)量的音頻數(shù)據(jù)包然后將它們封裝在audio queue對象的buffer中.audio queue將按順序播放這些buffer.


5.play_audioqueue
  • 創(chuàng)建Audio Queue
    • AudioQueueNewInput:創(chuàng)建錄制audio queue對象
    • AudioQueueNewOutput: 創(chuàng)建播放audio queue對象

實(shí)現(xiàn)一個(gè)播放隊(duì)列

a. 創(chuàng)建一個(gè)結(jié)構(gòu)體管理audio queue需要的信息,如音頻格式,采樣率等等

b. 定義一個(gè)回調(diào)函數(shù)管理audio queue buffers,這個(gè)回調(diào)函數(shù)使用Audio File Services去讀取你想要播放的文件.

c. 初始化audio queue并且使用AudioQueueNewOutput創(chuàng)建對象.

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
);

  • 控制Audio Queue播放的音量

Audio queue對象提供了兩種方式控制播放音量,一種是直接設(shè)置,如下,設(shè)置后可以立即生效.

Float32 volume = 1;
AudioQueueSetParameter (
    myAQstruct.audioQueueObject,
    kAudioQueueParam_Volume,
    volume
);

另一種是使用AudioQueueEnqueueBufferWithParameters,設(shè)置后在audio queue buffer開始播放時(shí)生效.

  • Indicating Audio Queue Playback Level

通過查詢audio queue對象的kAudioQueueProperty_CurrentLevelMeterDB屬性可以獲取當(dāng)前播放的級別.

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

  • 同時(shí)播放多個(gè)聲音

為了同時(shí)播放多個(gè)音頻,需要為每個(gè)音頻創(chuàng)建一個(gè)播放audio queue對象.對于每個(gè)audio queue,使用AudioQueueEnqueueBufferWithParameters函數(shù)安排第一個(gè)音頻buffer同時(shí)啟動(dòng)袱饭。

同時(shí)播放多個(gè)音頻,音頻格式顯得至關(guān)重要,因?yàn)閕OS中某些音頻格式使用了高效的硬件編解碼器,只能在設(shè)備上播放以下格式之一的單個(gè)實(shí)例.

a. AAC

b. ALAC

c. MP3

如果要播放高質(zhì)量同步的音頻,需要使用線性PCM或IMA4格式.

a. 線性PCM和IMA / ADPCM(IMA4)音頻您可以在iOS中同時(shí)播放多個(gè)線性PCM或IMA4格式聲音川无,而不會產(chǎn)生CPU資源問題。

b. AAC虑乖,MP3和Apple Lossless(ALAC)一次只能播放一首此類聲音

15.使用OpenAL定位播放

開源的OpenAL音頻API(可在OpenAL框架中使用懦趋,構(gòu)建于Core Audio之上)針對播放期間的聲音定位進(jìn)行了優(yōu)化。使用OpenGL建模的界面疹味,OpenAL可以輕松播放愕够,定位,混合和移動(dòng)聲音,OpenAL和OpenGL共享一個(gè)通用坐標(biāo)系統(tǒng)佛猛,使您可以同步音頻和視頻惑芭。OpenAL直接使用Core Audio的I / O audio unit),從而實(shí)現(xiàn)最低延遲播放继找。OpenAL是在iPhone和iPod touch上播放游戲應(yīng)用中的聲音效果的最佳選擇遂跟。

16.系統(tǒng)聲音

Audio Toolbox中的AudioServices.h提供了系統(tǒng)的聲音服務(wù),當(dāng)你僅僅想播放一個(gè)系統(tǒng)的短音頻時(shí),它將是最好的選擇,iOS中播放系統(tǒng)聲音最不不能超過30秒.

在iOS中,調(diào)用AudioServicesPlaySystemSound可以立即播放,你也可以調(diào)用AudioServicesPlayAlertSound提示用戶是否播放.

調(diào)用AudioServicesPlaySystemSound時(shí)使用kSystemSoundID_Vibrate常量可以顯式設(shè)置振動(dòng)效果.

#include <AudioToolbox/AudioToolbox.h>
#include <CoreFoundation/CoreFoundation.h>
 
// Define a callback to be called when the sound is finished
// playing. Useful when you need to free memory after playing.
static void MyCompletionCallback (
    SystemSoundID  mySSID,
    void * myURLRef
) {
        AudioServicesDisposeSystemSoundID (mySSID);
        CFRelease (myURLRef);
        CFRunLoopStop (CFRunLoopGetCurrent());
}
 
int main (int argc, const char * argv[]) {
    // Set up the pieces needed to play a sound.
    SystemSoundID    mySSID;
    CFURLRef        myURLRef;
    myURLRef = CFURLCreateWithFileSystemPath (
        kCFAllocatorDefault,
        CFSTR ("../../ComedyHorns.aif"),
        kCFURLPOSIXPathStyle,
        FALSE
    );
 
    // create a system sound ID to represent the sound file
    OSStatus error = AudioServicesCreateSystemSoundID (myURLRef, &mySSID);
 
    // Register the sound completion callback.
    // Again, useful when you need to free memory after playing.
    AudioServicesAddSystemSoundCompletion (
        mySSID,
        NULL,
        NULL,
        MyCompletionCallback,
        (void *) myURLRef
    );
 
    // Play the sound file.
    AudioServicesPlaySystemSound (mySSID);
 
    // Invoke a run loop on the current thread to keep the application
    // running long enough for the sound to play; the sound completion
    // callback later stops this run loop.
    CFRunLoopRun ();
    return 0;
}

17.Audio Unit

在iOS中,Audio Unit為應(yīng)用程序提供了實(shí)現(xiàn)低延遲輸入和輸出的機(jī)制婴渡。它們還提供某些DSP功能.

iOS中Audio Unit輸入輸出使用8.24位定點(diǎn)線性PCM音頻數(shù)據(jù).唯一例外的是以下情況.

  • 3D mix unit: 允許任意數(shù)量的單聲道輸入幻锁,每個(gè)輸入可以是8位或16位線性PCM.在8.24位定點(diǎn)PCM中提供一個(gè)立體聲輸出,3D混音器單元對其輸入執(zhí)行采樣率轉(zhuǎn)換,并對每個(gè)輸入通道提供大量控制边臼。此控件包括這些更改的音量哄尔,靜音,平移柠并,距離衰減和速率控制岭接。以編程方式,這是kAudioUnitSubType_AU3DMixerEmbedded單元臼予。
  • Multichannel mixer unit: 允許任意數(shù)量的單聲道或立體聲輸入鸣戴,每個(gè)輸入可以是16位線性或8.24位定點(diǎn)PCM醋火。在8.24位定點(diǎn)PCM中提供一個(gè)立體聲輸出呵萨。您的應(yīng)用程序可以靜音和取消靜音每個(gè)輸入通道以及控制其音量。以編程方式木柬,這是kAudioUnitSubType_MultiChannelMixer單元缰雇。
  • Converter unit: 提供采樣率入偷,位深度和位格式(線性到定點(diǎn))轉(zhuǎn)換追驴。 iPhone converter unit’s的規(guī)范數(shù)據(jù)格式是8.24位定點(diǎn)PCM。它轉(zhuǎn)換為此格式或從此格式轉(zhuǎn)換疏之。以編程方式殿雪,這是kAudioUnitSubType_AUConverter單元。
  • I/O unit:提供實(shí)時(shí)音頻輸入和輸出体捏,并根據(jù)需要執(zhí)行采樣率轉(zhuǎn)換冠摄。以編程方式,這是kAudioUnitSubType_RemoteIO單元几缭。
  • iPod EQ unit:提供可在應(yīng)用程序中使用的簡單均衡器河泳,并在內(nèi)置iPhone iPod應(yīng)用程序中提供相同的預(yù)設(shè)。 iPod EQ單元使用8.24位定點(diǎn)PCM輸入和輸出年栓。以編程方式拆挥,這是kAudioUnitSubType_AUiPodEQ單元。

每個(gè)Audio Unit的唯一標(biāo)識符由類型,子類型,制造商代碼(type, subtype, and manufacturer code)確定.每種子類型更加精確的描述了audio unit的用途.Audio Unit使用屬性配置音頻信息,如 Properties, Scopes, and Elements.每種audio unit需要一些指定屬性,

18.編解碼器

iOS中可以用的錄制和播放編解碼器來平衡音頻質(zhì)量某抓,應(yīng)用程序開發(fā)的靈活性纸兔,硬件功能和電池壽命。

19.Audio Processing Graphs

AUGraph:定義了一組復(fù)雜的音頻執(zhí)行任務(wù).

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末否副,一起剝皮案震驚了整個(gè)濱河市汉矿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌备禀,老刑警劉巖洲拇,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異曲尸,居然都是意外死亡赋续,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進(jìn)店門另患,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纽乱,“玉大人,你說我怎么就攤上這事昆箕⊙涣校” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵为严,是天一觀的道長敛熬。 經(jīng)常有香客問我,道長第股,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任话原,我火速辦了婚禮夕吻,結(jié)果婚禮上诲锹,老公的妹妹穿的比我還像新娘。我一直安慰自己涉馅,他們只是感情好归园,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著稚矿,像睡著了一般庸诱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上晤揣,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天桥爽,我揣著相機(jī)與錄音,去河邊找鬼昧识。 笑死钠四,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的跪楞。 我是一名探鬼主播缀去,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼甸祭!你這毒婦竟也來了缕碎?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤池户,失蹤者是張志新(化名)和其女友劉穎咏雌,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體煞檩,經(jīng)...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡处嫌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斟湃。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熏迹。...
    茶點(diǎn)故事閱讀 38,039評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凝赛,靈堂內(nèi)的尸體忽然破棺而出注暗,到底是詐尸還是另有隱情,我是刑警寧澤墓猎,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布捆昏,位于F島的核電站,受9級特大地震影響毙沾,放射性物質(zhì)發(fā)生泄漏骗卜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望寇仓。 院中可真熱鬧举户,春花似錦、人聲如沸遍烦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽服猪。三九已至供填,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間罢猪,已是汗流浹背近她。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坡脐,地道東北人泄私。 一個(gè)月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像备闲,于是被迫代替她去往敵國和親晌端。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內(nèi)容