適用于ios的音頻單元指南(2)

構建音頻單元應用程序

首先選擇設計模式

  • I/O 直接相連模式
  • 沒有渲染回調函數(shù)的i/o
  • 帶有渲染回調函數(shù)的 I/O
  • 僅有渲染回調函數(shù)的輸出
  • 其他音頻單元托管設計模式

構建app

  • 配置音頻會話
  • 指定想要的音頻單位
  • 構建音頻處理graph
  • 配置音頻單元
  • 寫入并附加渲染回調函數(shù)
  • 連接音頻單元節(jié)點
  • 提供用戶界面
  • 初始化并啟動音頻處理graph

故障排除提示

使用特定的音頻單元

使用I/O 音頻單元

  • 遠程I/O單元
  • 語音處理I/O單元
  • 通用輸出單元

使用混音器單元

  • 多聲道混音器單元
  • 3D 混音器單元

使用效果單元


構建音頻單元應用程序

現(xiàn)在我們已經(jīng)了解音頻單元托管的工作方式爱榔,也已經(jīng)準備好構建app應用程序的音頻單元部分革答。主要步驟是選擇設計模式男杈,然后編寫代碼來實現(xiàn)該模式峦萎。

首先選擇設計模式

在ios應用中托管音頻單元有六種基本設計模式闷叉。首先選擇最能代表希望應用對音頻做什么的那個。在學習每種模式的時候滚婉,注意下常用功能。每種模式

  • 只有一個I/O單元
  • 在整個音頻處理的grahp中使用音頻單元流格式-盡管該模式可能存在改變篇裁,例如為混音器單元提供單聲道和立體聲。
  • 要求在特定位置設置流格式和流格式的某些部分

正確設置流格式對于建立音頻數(shù)據(jù)流至關重要赡若。這些模式中的大多數(shù)依賴于音頻流格式從源到目的地的自動傳播达布,如音頻單元連接鎖提供的。盡可能的利用這種傳播逾冬,因為它減少了編寫和維護的代碼量黍聂。同時,請確保您了解設置流格式所需要的流格式。例如分冈,我們必須在ipod EQ 設備的輸入和輸出上設置完整的流格式圾另。有關所有ios音頻單元流格式的要求可以看 Using Specific Audio Units
在大多數(shù)情況下霸株,本章中的設計模式采用音頻處理grahp(AUGraph類型)雕沉。我們可以在不使用grahp的情況下實現(xiàn)這些模式中的任意一種,但是用簡化代碼并不支持動態(tài)分配重新配置去件。

I/O 直接相連模式

I/O直通模式將傳入的音頻直接發(fā)送到輸出硬件坡椒,沒有選項可以處理音頻數(shù)據(jù)。雖然這沒有多大的實用價值尤溜,但是基于此模式構建托管的app的音頻單元是驗證和鞏固我們對音頻單元概念的理解的好方法倔叼。


如圖所示,音頻輸入硬件將流格式強制放在遠程 I/O 單元輸入原件的朝外側宫莱。反過來丈攒,我們指定此元素的向內側使用的格式。音頻單元關鍵需要執(zhí)行格式轉換授霸。為避免不必要的采樣率轉換巡验,請使用流格式使用的音頻硬件采樣率。

默認情況下是禁止 輸入的 element 碘耳,因此我們需要手動開啟它显设。否則,音頻無法流動辛辨。

在圖中所示的模式利用了兩個遠程I/O 元件之間的音頻單元連接捕捂。具體來說,我們不需要在音頻元件的輸入scope 上的output element 設置流格式斗搞。連接傳播我們?yōu)閕nput element 指定的格式指攒。

輸出元件的朝外側采用音頻輸出硬件的流格式,輸出元件需要根據(jù)對輸出音頻格式執(zhí)行格式轉換僻焚。

該模式允悦,我們無需配置任何音頻數(shù)據(jù)緩沖區(qū)。

沒有渲染回調函數(shù)的i/o

在遠程I/O 單元的element之間添加一個或者多個其他音頻單元溅呢,可以構建更有趣的app澡屡。例如,我們可以使用多聲道混音器單元將傳入的麥克風音頻定位在立體聲場中或提供輸出音量控制咐旧。在這種設計模式中驶鹉,仍然沒有回調功能,如下圖铣墨,這簡化了模式室埋,但是先知了它的實用性。


在此模式中,我們可以像I/O直接相連模式中一樣配置遠程的I/O 單元的兩個元素姚淆。要設置多聲道混音器單元孕蝉,必須在混音器輸出上設置流格式的采樣率,如上圖

混音器的輸入流格式通過傳輸從遠程I/O單元的輸入 element 的輸出通過音頻單元連接自動建立腌逢。類似的降淮,遠程I/O 單元的輸出的element 的input scope的流格式是也是通過音頻單元連接,該數(shù)據(jù)來自混音器單元的output的傳播搏讶。

在這種模式的任何實例中-實際上佳鳖,除了I/O單元之外,每當使用其他音頻單元時-必須按照 Audio Unit Properties Reference
中的描述設置kAudioUnitProperty_MaximumFramesPerSlice

與I/O 直接相連模式一樣媒惕,我們不需要配置任何音頻數(shù)據(jù)緩沖區(qū)系吩。

帶有渲染回調函數(shù)的 I/O

通過在遠程I/O 單元的輸入和輸出元件之間防止渲染回調函數(shù),我們可以在傳入音頻到達硬件之前對其進行操作妒蔚。在一個非常簡單的情況下穿挨,我們可以使用渲染回調函數(shù)來調整輸出音量,也可以添加顫音肴盏,鈴聲調制科盛,回聲或者其他效果。通過使用Accelerate框架中提供的傅里葉變化和積分公式叁鉴,我們可以做的事情可就是無窮無盡的土涝。

如圖所示,此模式使用遠程i/o單元的兩個element幌墓。將渲染回調函數(shù)附加到output element 的input scope上但壮。當該元素需要另一組音頻樣本值時,他會調用我們的回調函數(shù)常侣。反過來蜡饵,我們的回調通過調用遠程I/O 單元的輸入 element的渲染會地哦啊函數(shù)來獲取新樣本

與其他I/O 模式一樣胳施,我們必須在遠程I/O 單元上開啟輸入溯祸,默認情況下輸入是禁止的。而且舞肆,對于其他I/O模式焦辅,我們無需要配置任何音頻數(shù)據(jù)緩沖區(qū)

注意,當我們使用渲染回調涵涵說建立從一個音頻單元到另一個音頻單元的音頻路徑時椿胯,回調函數(shù)取代了音頻單元連接

僅有渲染回調函數(shù)的輸出

對于游戲音樂和合成器選擇此模式-當我們需要為其生成聲音并需要最大的響應app筷登。最簡單的是,這種模式設計到一個渲染回調函數(shù)哩盲,它直接連接到遠程I/O 單元輸出element 的 output的 scope


image.png

你可以使用相同的模式構建具有更復雜的音頻結構的app前方。例如狈醉,當我們希望生成多個聲音,將它們混合在一起惠险,然后通過設備的輸出硬件播放他們苗傅,看下圖。這里該模式采用音頻處理grahp和兩個額外的音頻單元班巩,多聲道混音器和Ipod EQ

上圖渣慕,需要注意Ipod EQ 要求我們在在輸入和輸出上設置完整的流格式。另一方面趣竣,多通道混音器只需要再其輸出上設置正確的采樣率摇庙。然后旱物,整個流格式由音頻單元連接從混音器的輸出傳播到遠程I/O單元輸出單元的input scope遥缕。具體細節(jié)看Using Specific Audio Units.

對于每個多通道混音器收入單元,如上圖宵呛,需要設置完整的流格式单匣。對于輸入0,可以顯示設置它宝穗。對于輸入1 户秤,格式通過音頻單元連接從Ipod EQ 單元的輸出傳播。通常逮矛,我們必須分別考慮每個音頻單元的流格式需求鸡号。

其他音頻單元托管設計模式

音頻單元托管還有兩種設計模式。要錄制和分析音頻须鼎,請使用渲染回調函數(shù)創(chuàng)建僅限輸入的應用鲸伴。回調函數(shù)由應用程序調用晋控,然后它調用RemoteI/O 單元的input元素的render方法汞窗。但是,在大多數(shù)情況下赡译,像這樣的應用程序的更好選擇是使用音頻隊列對象仲吏。使用音頻隊列對象提高了更大的靈活性,因為他的渲染回調函數(shù)不在實時線程上蝌焚。

要執(zhí)行離線音頻處理裹唆,需要使用通用輸出單元。與遠程I/O 單元不同只洒,該音頻單元不連接到設備的音頻硬件许帐。當使用它向app發(fā)送音頻時,它取決于app調用其render 方法

構建app

無論選擇哪種設計模式红碑,構建音頻單元托管app的步驟基本相同:

  • 1.配置音頻會話
  • 2.指定音頻單元
  • 3.創(chuàng)建音頻處理graph舞吭,然后獲取音頻單元
  • 5.配置音頻單元
  • 6.連接音頻單元節(jié)點
  • 7.提供用戶界面
  • 8.初始化然后啟動音頻處理graph
配置音頻會話

構建音頻單元app的第一步與任何ios音頻app 相同泡垃,配置音頻會話。音頻會話的特性在很大程度上決定了app的音頻功能以及與系統(tǒng)其它部分的交互性羡鸥。首先指定要在app中使用的采樣率蔑穴,如下

self.graphSampleRate = 44100.0; // Hertz

接下來,使用音頻會話對象請求系統(tǒng)使用您的首選采樣率作為設備硬件的采樣率惧浴,如下列代碼存和。這里的目的是避免硬件和app之間的采樣率轉換。這可以最大程度的提高cpu的性能和音質衷旅,并最大限度的減少電池消耗捐腿。

NSError *audioSessionError = nil;
AVAudioSession *mySession = [AVAudioSession sharedInstance];     // 1
[mySession setPreferredHardwareSampleRate: graphSampleRate       // 2
                                    error: &audioSessionError];
[mySession setCategory: AVAudioSessionCategoryPlayAndRecord      // 3
                                    error: &audioSessionError];
[mySession setActive: YES                                        // 4
               error: &audioSessionError];
self.graphSampleRate = [mySession currentHardwareSampleRate];    // 5

上述代碼解釋

  • 1獲取app 的單例音頻會話對象的引用
  • 2.請求硬件的采樣率。
  • 3.請求我們想要的音頻會話category柿顶。這里是錄制和播放
  • 4.激活音頻會話
  • 5.音頻會話激活后茄袖,根據(jù)系統(tǒng)提供的實際采樣率更新自己的采樣率變量。

這里可能需要配置一個硬件特性:音頻硬件I/O 緩沖區(qū)持續(xù)時間嘁锯。在44.1KHZ采樣率下宪祥,模式持續(xù)時間約為23ms。相當于1024個樣本的slice大小家乘。如果app的I/O 延遲至關重要蝗羊,那么我們需要請求較小的持續(xù)時間,最低月為0.005毫秒(相當256個樣本)

self.ioBufferDuration = 0.005;
[mySession setPreferredIOBufferDuration: ioBufferDuration
                                  error: &audioSessionError];

這里關于音頻會話的向導可以參考 Audio Session Programming Guide

指定想要的音頻單位

在運行時仁锯,音頻會話配置代碼后耀找,app還是沒有獲取音頻單元。我們可以使用AudioComponentDescription指定音頻單元业崖。

AudioComponentDescription ioUnitDescription;
 
ioUnitDescription.componentType          = kAudioUnitType_Output;
ioUnitDescription.componentSubType       = kAudioUnitSubType_RemoteIO;
ioUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
ioUnitDescription.componentFlags         = 0;
ioUnitDescription.componentFlagsMask     = 0;

獲取到音頻單元說明符野芒,然后根據(jù)我們選擇的模式構建音頻處理graph

構建音頻處理graph

一般步驟如下

    1. 實例化AUGraph對象。該對象代表音頻處理grahp
  • 2.實例化一個或者多個AUNode 對象腻要。每個類型代表grahp中的音頻單元
  • 3.將 AUNode 加入到 AUGraph中
  • 4.打開圖形并實例化音頻單元
  • 5.獲取對音頻單元的引用

如下列代碼

AUGraph processingGraph;
NewAUGraph (&processingGraph);
 
AUNode ioNode;
AUNode mixerNode;
 
AUGraphAddNode (processingGraph, &ioUnitDesc, &ioNode);
AUGraphAddNode (processingGraph, &mixerDesc, &mixerNode)

AUGraphAddNode 函數(shù)調用使用音頻單元說明符ioUnitDesc和mixerDesc复罐。此時,graph 將被實例化雄家,并擁有app中使用的結點效诅。打開graph 并實例化音頻單元使用AUGraphOpen

AUGraphOpen (processingGraph);

然后,通過AUGraphNodeInfo函數(shù)獲取對音頻單元實例的引用

AudioUnit ioUnit;
AudioUnit mixerUnit;
 
AUGraphNodeInfo (processingGraph, ioNode, NULL, &ioUnit);
AUGraphNodeInfo (processingGraph, mixerNode, NULL, &mixerUnit)

ioUinit 和mixerUnit 變量現(xiàn)在包含了對graph中音頻單元實例的引用趟济,允許您配置并互聯(lián)音頻單元乱投。

配置音頻單元

每個ios 音頻單元都需要自己的配置,可以參考 Using Specific Audio Units顷编。但是有些配置是常見的戚炫,所有ios音頻開發(fā)人員都應該熟悉他們。
默認情況下媳纬,遠程I/O 單元已啟用輸出但是禁止輸入双肤。如果想app同時執(zhí)行I/O 或者僅僅使用輸入施掏,那么必須要重新配置I/O 單元。具體看而已看Audio Unit Properties Reference中的kAudioOutputUnitProperty_EnableIO

除了遠程I/O 和語音處理I/O 單元外茅糜,所有的ios音頻單元都需要配置其kAudioUnitProperty_MaximumFramesPerSlice屬性七芭。該屬性確保音頻單元準好相應于渲染調用產(chǎn)生足夠數(shù)量的音頻數(shù)據(jù)幀。具體可以參考Audio Unit Properties Reference中的 kAudioUnitProperty_MaximumFramesPerSlice

所有的音頻單元都需要再輸入和輸出或者兩者上定義其音頻流格式蔑赘。具體可以看 Audio Stream Formats Enable Data Flow.
有關各種ios音頻設備的特定流格式要求狸驳。可以看Using Specific Audio Units.

寫入并附加渲染回調函數(shù)

對于采用渲染回調函數(shù)的設計模式缩赛,我們必須編寫這些函數(shù)耙箍,然后將他們附加到正確的點上。 Render Callback Functions Feed Audio to Audio Units描述了這些回調函數(shù)并且解釋了如何正確的工作原理酥馍。這里我們可以參考官方demo aurioTouch

當音頻不流動辩昆,我們可以使用音頻單元API 立即附加渲染回調如下

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc        = &renderCallback;
callbackStruct.inputProcRefCon  = soundStructArray;
 
AudioUnitSetProperty (
    myIOUnit,
    kAudioUnitProperty_SetRenderCallback,
    kAudioUnitScope_Input,
    0,                 // output element
    &callbackStruct,
    sizeof (callbackStruct)
);

通過使用音頻處理graph API ,我們可以以現(xiàn)場安全的方式附加渲染回調,即使在音頻流動時候也可以這樣做物喷。
如下

AURenderCallbackStruct callbackStruct;
callbackStruct.inputProc        = &renderCallback;
callbackStruct.inputProcRefCon  = soundStructArray;
 
AUGraphSetNodeInputCallback (
    processingGraph,
    myIONode,
    0,                 // output element
    &callbackStruct
);
// ... some time later
Boolean graphUpdated;
AUGraphUpdate (processingGraph, &graphUpdated);
連接音頻單元節(jié)點

在大多數(shù)情況下卤材,使用音頻處理graph API中的AUGraphConnectNodeInput和AUGraphDisconnectNodeInput函數(shù)建立或斷開音頻之間的連接是最好和最容易的。這些函數(shù)是線程安全的峦失,可以避免顯示定義連接的編碼開銷,因為在不使用graph的時候必須這么做术吗。

下列代碼顯示如何處理使用音頻處理grahp API 混合器結點的輸出連接到I/O 單元輸出元件的輸入

AudioUnitElement mixerUnitOutputBus  = 0;
AudioUnitElement ioUnitOutputElement = 0;
 
AUGraphConnectNodeInput (
    processingGraph,
    mixerNode,           // source node
    mixerUnitOutputBus,  // source node bus
    iONode,              // destination node
    ioUnitOutputElement  // desinatation node element
);

我們也可以使用音頻單元屬性機制直接建立和斷開音頻單元之間的連接尉辑。我們使用AudioUnitSetProperty函數(shù)的kAudioUnitProperty_MakeConnection屬性,如下较屿,該方法要求我們?yōu)槊總€連接定義AudioUnitConnection結構以用做其屬性值隧魄。

AudioUnitElement mixerUnitOutputBus  = 0;
AudioUnitElement ioUnitOutputElement = 0;
 
AudioUnitConnection mixerOutToIoUnitIn;
mixerOutToIoUnitIn.sourceAudioUnit    = mixerUnitInstance;
mixerOutToIoUnitIn.sourceOutputNumber = mixerUnitOutputBus;
mixerOutToIoUnitIn.destInputNumber    = ioUnitOutputElement;
 
AudioUnitSetProperty (
    ioUnitInstance,                     // connection destination
    kAudioUnitProperty_MakeConnection,  // property key
    kAudioUnitScope_Input,              // destination scope
    ioUnitOutputElement,                // destination element
    &mixerOutToIoUnitIn,                // connection definition
    sizeof (mixerOutToIoUnitIn)
);
提供用戶界面

到這里,我們構建的app已經(jīng)完成構建和配置隘蝎。在許多情況下购啄,我們需要提供一個用戶界面,讓用戶微調音頻行為嘱么。我們可以定制用戶界面以允許用戶調整特定的音頻單元參數(shù)狮含,并在某些特使情況下調整音頻單元屬性。
這里構建UI就不做贅述了

初始化并啟動音頻處理graph

在開始音頻流之前曼振,我們必須通過調用AUGraphInitialize函數(shù)來初始化音頻graph几迄,如下

  • 1.通過為每個音頻單獨的調用AudioUnitInitialize函數(shù)來初始化graph所擁有的音頻單元。(如果要在不適用grahp的情況下構建處理鏈冰评,則必須依次顯示初始化每個音頻單元)
  • 2.驗證graph的連接和音頻流數(shù)據(jù)格式
  • 3.在音頻單元連接上傳播流格式
OSStatus result = AUGraphInitialize (processingGraph);
// Check for error. On successful initialization, start the graph...
AUGraphStart (processingGraph);
 
// Some time later
AUGraphStop (processingGraph);

故障排除提示

每當Core Audio功能提供返回值映胁,捕獲該值并檢查成功或失敗。失敗時候甲雅,使用xcode的調試功能解孙,可以看Xcode Debugging Guide坑填。

注意函數(shù)調用之間的依賴關系。例如弛姜,只有在成功初始化后才能啟動音頻處理graph穷遂。檢查AUGraphInitialize的返回值。如果函數(shù)成功返回娱据,則可以啟動graph蚪黑。如果失敗,確定出了什么問題中剩。檢查導致初始化的所有音頻單元函數(shù)調用是否成功返回忌穿。具體可以參考mixerHost工程中的configureAndInitializeAudioProcessingGraph方法。

其次结啼,如果圖形初始化失敗掠剑,請利用CAShow函數(shù),此函數(shù)將graph的狀態(tài)打印在xcode的控制臺郊愧。mixerHost也有此技術的演示朴译。

確保將每個AudioStreamBasicDescription結構初始化為0,如下

AudioStreamBasicDescription stereoStreamFormat = {0};

將ASBD的的字段初始化為0 属铁,可以確保沒有字段包含垃圾數(shù)據(jù)眠寿。(在外部存儲中聲明結構的情況下-例如,作為類聲明中的實例變量-其字段會自動初始化為0焦蘑,我們無需自己初始化他們)

要將AudioStreamBasicDescription結構的字段值打印到xcode控制臺盯拱,可以執(zhí)行下列代碼

- (void) printASBD: (AudioStreamBasicDescription) asbd {
 
    char formatIDString[5];
    UInt32 formatID = CFSwapInt32HostToBig (asbd.mFormatID);
    bcopy (&formatID, formatIDString, 4);
    formatIDString[4] = '\0';
 
    NSLog (@"  Sample Rate:         %10.0f",  asbd.mSampleRate);
    NSLog (@"  Format ID:           %10s",    formatIDString);
    NSLog (@"  Format Flags:        %10X",    asbd.mFormatFlags);
    NSLog (@"  Bytes per Packet:    %10d",    asbd.mBytesPerPacket);
    NSLog (@"  Frames per Packet:   %10d",    asbd.mFramesPerPacket);
    NSLog (@"  Bytes per Frame:     %10d",    asbd.mBytesPerFrame);
    NSLog (@"  Channels per Frame:  %10d",    asbd.mChannelsPerFrame);
    NSLog (@"  Bits per Channel:    %10d",    asbd.mBitsPerChannel);
}

以上方法可以快速找到asbd中的問題

在為音頻單元流格式定義ASBD的時候,請注意確保您遵循使用特定音頻單元的使用表中的“Recommended stream format attributes”和“Stream format notes”例嘱。

使用特定的音頻單元

每個ios音頻單元都有一些與所有其他東西相同的東西以及某些獨特的東西狡逢。本文檔前面的章節(jié)描述了常見的方法,其中包括需要再運行時查詢音頻單元拼卵,實例化它奢浑,并確保其流格式的正確。本章將介紹音頻單元之間的差異腋腮,并提供了有關如何使用它們的詳細情況雀彼。

使用I/O 音頻單元

ios 提供三個i/o (輸入和輸出)單元。絕大數(shù)音頻單元app使用遠程 I/O 單元低葫,他連接到輸入和輸入音頻的硬件详羡,并提供對各個輸入和輸出音頻樣本值的低延遲的訪問。對于VoIP應用嘿悬,語言處理I/O單元通過添加回聲消除和其他功能來擴展遠程I/O單元实柠。要將音頻發(fā)送回app而不是輸出音頻硬件,需要通用輸入單元善涨。

遠程I/O單元

遠程I/O 單元(subtype kAudioUnitSubType_RemoteIO)連接到硬件設備窒盐,用于輸入草则,輸出或同時輸入和輸出。用于播放蟹漓,錄制或低延遲同時輸入和輸出炕横,不需要回聲消除。

設備的音頻硬件將其音頻流格式強制放置在遠程I/O 單元的外側葡粒,可以看 Understanding Where and How to Set Stream Formats.音頻單元提供硬件音頻格式和應用音頻格式之間的格式轉換份殿,通過附帶的格式轉換器音頻單元進行格式轉換。

有關代碼可以看 aurioTouch

Audio unit feature Details
Elements 一個input element:element 1嗽交,一個output element:element 0
推薦流格式屬性 kAudioFormatLinearPCM
AudioUnitSampleType
kAudioFormatFlagsAudioUnitCanonical
流格式說明 遠程I/O的朝外側從音頻硬件獲取其格式:如下所示:
input element(element 1)所在的input scope從當前活動的音頻輸入硬件獲取其流格式
output element(element 0)所在的output scope從當前活動的輸出音頻硬件獲取其流格式
在input element所在的output scope 設置app格式卿嘲。input element根據(jù)需要在其input 和ouptut的scope 之間進行格式轉換。使用app流格式的硬件采樣率
如果output element的input scope 由音頻單元連接提供夫壁,那么它從該連接獲取其流格式拾枣。但是金赦,如果他由渲染回調函數(shù)提供嫉戚,我們需要在其上設置app格式
參數(shù)
屬性 See I/O Audio Unit Properties.
屬性說明 我們不需要才次音頻設備上設置kAudioUnitProperty_MaximumFramesPerSlice屬性

上表流格式說明如下圖


語音處理I/O單元

語音處理I/O單元(subtype kAudioUnitSubType_VoiceProcessingIO)具有遠程I/O單元的特性,并為雙向雙工通信添加了回聲抑制沐序。他還增加了自動增益校正邑茄,語音處理質量調整和靜音功能姨蝴。該單元用于
VoIP 的應用

該單元包含所有遠程I/O 單元的所有功能。此外撩扒,次音頻單元還有特定的屬性似扔,可以看Voice-Processing I/O Audio Unit Properties

通用輸出單元

將音頻處理graph的輸出發(fā)送到app而不是輸出硬件的時候,需要使用子類型是kAudioUnitSubType_GenericOutput搓谆。我們通常會使用通用輸出單元進行離線音頻處理。與其他I/O單元一樣豪墅,通用輸出單元包含格式轉換單元泉手。這使通用輸出單元可以在音頻處理graph中使用的流格式與所需格式之間執(zhí)行格式轉換。

我們還可以使用通用輸入單元作為作為subgraph的最終借點偶器,放入superGraph 中斩萌。

使用混音器單元

ios 提供了兩個混音器單元。在大多數(shù)情況下屏轰,我們應該使用多聲道混音器單元颊郎,他可以為任意數(shù)量的單聲道或者立體聲流提供混音。如果需要3D 混音器單元的功能霎苗,我們可能會使用openAL.openAL建立在3DMixer 單元之上姆吭,提供與簡單API 相同的性能,非常適合游戲app 開發(fā)唁盏。

多聲道混音器單元

多聲道混音器單元(子類型kAudioUnitSubType_MultiChannelMixer)可接收任意數(shù)量的單聲道和立體聲流内狸,并將它們組合成單個立體聲輸出检眯。它控制每個輸入和輸出的音頻增益,并允許我們分別打開或者關閉每個輸入昆淡。從ios4.0 開始锰瘸,多聲道混音器支持每個輸入的立體聲聲像。
有關代碼可以看mixerHost

Audio unit feature Details
Elements 一個或者多個input element 昂灵,每個input element可以是單聲道或立體聲 避凝,一個立體聲output element
推薦流格式屬性 kAudioFormatLinearPCM
AudioUnitSampleType
kAudioFormatFlagsAudioUnitCanonical
流格式說明 在input scope,管理流格式如下:
如果input bus由音頻單元連接眨补,它將從該連接獲取其流格式
如果input bus 由渲染回調函數(shù)提供管削,那么bus上設置完整的應用程序流格式。使用于回調提供的數(shù)據(jù)相同的流格式
在output scope渤涌,僅僅設置app的采樣率就可以了
參數(shù) See Multichannel Mixer Unit Parameters.
屬性 kAudioUnitProperty_MeteringMode
屬性說明 默認情況下kAudioUnitProperty_MaximumFramesPerSlice屬性的值是1024 佩谣,當屏幕鎖定并且顯示器休眠時,該值不夠 实蓬。如果app在屏幕鎖定的時候要播放音頻茸俭,那么必須增加此屬性的值。做法如下:
如果音頻輸入處于活動狀態(tài)安皱,那么無需設置kAudioUnitProperty_MaximumFramesPerSlice屬性
如果音頻輸入為激活调鬓,需要將該值設置為4096
3D 混音器單元

3D 混音器單元(subtype kAudioUnitSubType_3DMixe)控制每個輸入的立體聲聲像,回放速度和增益酌伊,并控制其他特征腾窝,例如與收聽者的視距。輸出具有音頻增益控制居砖。要了解音頻單元可以執(zhí)行的操作可以考慮使用openAL

在大多數(shù)情況下虹脯,如果需要3D混音器單元的功能,最佳選擇的是使用OpenAL. 可以看代碼oalTouch

Audio unit feature Details
Elements 一個或者多個input element 奏候,每個input element可以是單聲道或立體聲 循集,一個立體聲output element
推薦流格式屬性 UInt16
kAudioFormatFlagsCanonical
流格式說明 在input scope,管理流格式如下:
如果input bus由音頻單元連接蔗草,它將從該連接獲取其流格式
如果input bus 由渲染回調函數(shù)提供咒彤,那么bus上設置完整的應用程序流格式。使用于回調提供的數(shù)據(jù)相同的流格式
在output scope咒精,僅僅設置app的采樣率就可以了
參數(shù) See 3D Mixer Unit Parameters.
屬性 看3D Mixer Audio Unit Properties. 注意镶柱,大多數(shù)這些屬性僅在該音頻單元的max os X 版本中實現(xiàn)的
屬性說明 默認情況下kAudioUnitProperty_MaximumFramesPerSlice屬性的值是1024 ,當屏幕鎖定并且顯示器休眠時模叙,該值不夠 歇拆。如果app在屏幕鎖定的時候要播放音頻,那么必須增加此屬性的值。做法如下:
如果音頻輸入處于活動狀態(tài)查吊,那么無需設置kAudioUnitProperty_MaximumFramesPerSlice屬性
如果音頻輸入為激活谐区,需要將該值設置為4096

使用效果單元

iPod EQ單元(子類型kAudioUnitSubType_AUiPodEQ)是iOS 4中提供的唯一效果單元。這與內置IPodapp使用的均衡器相同逻卖。要查看此音頻設備的iPod應用程序用戶界面宋列,請轉至設置> iPod> EQ。該音頻單元提供一組預設均衡曲線评也,如低音增強器炼杖,流行音樂和口語。

您必須為iPod EQ設備提供自己的用戶界面盗迟,就像您必須為任何音頻設備一樣坤邪。 Mixer iPodEQ AUGraph Test 項目演示了如何使用iPod EQ單元并顯示一種為其提供用戶界面的用法。

Audio unit feature Details
Elements 一個單聲道或者立體聲input element罚缕,一個單聲道或者立體聲output element
推薦流格式屬性 kAudioFormatLinearPCM
AudioUnitSampleType
kAudioFormatFlagsAudioUnitCanonical
流格式說明 在input scope艇纺,管理流格式如下:
如果input bus由音頻單元連接,它將從該連接獲取其流格式
如果input bus 由渲染回調函數(shù)提供邮弹,那么bus上設置完整的應用程序流格式黔衡。使用于回調提供的數(shù)據(jù)相同的流格式
在output scope,僅僅設置app的采樣率就可以了
參數(shù)
屬性 kAudioUnitProperty_FactoryPresetskAudioUnitProperty_PresentPreset
屬性說明

oalTouch
aurioTouch
mixerHost
audio unit ios

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末腌乡,一起剝皮案震驚了整個濱河市盟劫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌与纽,老刑警劉巖侣签,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異急迂,居然都是意外死亡影所,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進店門僚碎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來型檀,“玉大人,你說我怎么就攤上這事听盖。” “怎么了裂七?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵皆看,是天一觀的道長。 經(jīng)常有香客問我背零,道長腰吟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮毛雇,結果婚禮上嫉称,老公的妹妹穿的比我還像新娘。我一直安慰自己灵疮,他們只是感情好织阅,可當我...
    茶點故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著震捣,像睡著了一般荔棉。 火紅的嫁衣襯著肌膚如雪润樱。 梳的紋絲不亂的頭發(fā)上壹若,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天,我揣著相機與錄音壁查,去河邊找鬼睡腿。 笑死席怪,一個胖子當著我的面吹牛挂捻,可吹牛的內容都是我干的刻撒。 我是一名探鬼主播耿导,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼舱呻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了芥驳?” 一聲冷哼從身側響起兆旬,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤爵憎,失蹤者是張志新(化名)和其女友劉穎宝鼓,沒想到半個月后愚铡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體碍舍,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡片橡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了经瓷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡舆吮,死狀恐怖,靈堂內的尸體忽然破棺而出色冀,到底是詐尸還是另有隱情,我是刑警寧澤柱嫌,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站慎式,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜瘪吏,卻給世界環(huán)境...
    茶點故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一癣防、第九天 我趴在偏房一處隱蔽的房頂上張望掌眠。 院中可真熱鬧,春花似錦级遭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拟淮。三九已至干茉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間很泊,已是汗流浹背角虫。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留撑蚌,地道東北人上遥。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像争涌,于是被迫代替她去往敵國和親粉楚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內容

  • 為什么婚后就被會茶米油鹽醬醋所難倒亮垫,一副主婦像模软。感覺自己不再美麗了感覺自己把青春貢獻給了廚房。問題是婚前我也要吃飯...
    nymph莉閱讀 341評論 0 0
  • 那是一段金光閃閃的歲月, 艱苦中帶著溫馨继蜡, 努力時含著微笑回俐。 初中的時候逛腿,我的生活費是一個月50塊錢左右。有朋友驚...
    梁涵閱讀 939評論 0 3
  • 物質社會,區(qū)分弱小與強大的方式很粗暴簡單:誰有錢誰強大忘瓦,誰沒錢誰弱小搁廓。 在這篇文章中,我們暫且把精神上的分化和意識...
    袁大島閱讀 370評論 0 0
  • 第一次開著空調午睡耕皮,舒服了境蜕,愜意了,便夢見了想見的人凌停。 夢里粱年,朋友贈我兩張戲票,說是專場苦锨。糊亂的夢里逼泣,一張票一會兒...
    清靜超然閱讀 288評論 0 0
  • 大黃刪了蘇媽的微信。 周一上班舟舒,她沖過來拉庶。大黃你翅膀硬了吧你,刪我秃励,憑什么刪我氏仗。你還不服氣是不是啊你。我還沒刪你夺鲜,...
    忘了名字的人閱讀 209評論 0 0