2015-11-24 18 views
0

在我的應用程序中,我正在渲染回調中進行音頻處理(僅輸入,不輸出)。 這裏是我初始化音頻:iOS在渲染回調處理之前添加音頻效果?

-(void) initAudio { 

OSStatus status; 

NewAUGraph(&graph); 

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

AUNode ioNode; 

status = AUGraphAddNode(graph, &desc, &ioNode); 
checkStatus(status, "At adding node"); 

AUGraphOpen(graph); 

AUGraphNodeInfo(graph, ioNode, NULL, &audioUnit); 

//Enable IO for recording 
UInt32 enableInput = 1; 
status = AudioUnitSetProperty(audioUnit, 
           kAudioOutputUnitProperty_EnableIO, 
           kAudioUnitScope_Input, 
           kInputBus, 
           &enableInput, 
           sizeof(enableInput)); 
checkStatus(status, "At setting property for input"); 

//Disable playback 
UInt32 enableOutput = 0; 
status = AudioUnitSetProperty(audioUnit, 
           kAudioOutputUnitProperty_EnableIO, 
           kAudioUnitScope_Output, 
           kOutputBus, 
           &enableOutput, 
           sizeof(enableOutput)); 
checkStatus(status, "At setting property for input"); 

// ASBD 
AudioStreamBasicDescription audioFormatIn; 
audioFormatIn.mSampleRate   = SampleRate; 
audioFormatIn.mFormatID   = kAudioFormatLinearPCM; 
audioFormatIn.mFormatFlags  = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; 
audioFormatIn.mFramesPerPacket = 1; 
audioFormatIn.mChannelsPerFrame = 1; 
audioFormatIn.mBitsPerChannel  = 16;//sizeof(AudioSampleType) * 8; 
audioFormatIn.mBytesPerPacket  = 2 * audioFormatIn.mChannelsPerFrame; 
audioFormatIn.mBytesPerFrame  = 2 * audioFormatIn.mChannelsPerFrame; 

//Apply format 
status = AudioUnitSetProperty(audioUnit, 
           kAudioUnitProperty_StreamFormat, 
           kAudioUnitScope_Output, 
           kInputBus, 
           &audioFormatIn, 
           sizeof(audioFormatIn)); 
checkStatus(status,"At setting property for AudioStreamBasicDescription for input"); 


//Set up input callback 
AURenderCallbackStruct callbackStruct; 
callbackStruct.inputProc = recordingCallback; 
callbackStruct.inputProcRefCon = (__bridge void *)self; 

status = AudioUnitSetProperty(audioUnit, 
           kAudioOutputUnitProperty_SetInputCallback, 
           kAudioUnitScope_Global, 
           kInputBus, 
           &callbackStruct, 
           sizeof(callbackStruct)); 
checkStatus(status,"At setting property for recording callback"); 

// Disable buffer allocation for the recorder 
UInt32 flag = 0; 
status = AudioUnitSetProperty(audioUnit, 
           kAudioUnitProperty_ShouldAllocateBuffer, 
           kAudioUnitScope_Output, 
           kInputBus, 
           &flag, 
           sizeof(flag)); 
checkStatus(status, "At set property should allocate buffer"); 

// Allocate own buffers 
tempBuffer.mNumberChannels = 1; 
tempBuffer.mDataByteSize = 1024 * 2; 
tempBuffer.mData   = malloc(1024 * 2); 

status = AUGraphInitialize(graph); 
checkStatus(status,"At AUGraph Initalize"); 
} 

現在,我想在渲染回調處理之前增加一個高通濾波器或帶通濾波器的輸入音頻。所以我覺得我應該增加這樣的:

desc.componentType   = kAudioUnitType_Effect; 
desc.componentSubType  = kAudioUnitSubType_BandPassFilter; 
desc.componentFlags   = 0; 
desc.componentFlagsMask  = 0; 
desc.componentManufacturer = kAudioUnitManufacturer_Apple; 

,但我沒能創造/正確連接節點,使這項工作... 感謝您的幫助!

+0

您的渲染鏈條是否在沒有帶通的情況下工作? – dave234

+0

@Dave我曾經使用過經典的音頻單元初始化,但是我開始轉向AUGraph,即使我不確定自己做的是否正確,我上面的代碼似乎也能正常工作。 – jcr

回答

0

當我想做類似的事情時,我發現你的問題 - 很遺憾沒有任何解決方案:-(現在幾天後,設法做到了這一點,所以這是我的工作解決方案,每個人都在努力解決同樣的問題:

  1. 準備Remote_IO的輸入作爲一個獨立的音頻單元,用於記錄音頻
  2. 添加一個回調到輸入我把它叫做「話筒回調」

    (注意:蘋果來電這是一個輸入回調,而事實上,這只是一個NOTIFICATION回調,對t來說ELL您的應用程序,樣品是可用的,你要「問」輸入單元明確地使它們...)

  3. 建立一個AU圖:轉換器單元 - >過濾器 - >通用輸出

    (注:通用輸出可以轉換,但不是過濾器。所以,如果你想喂入除8.24格式以外的鏈,那麼你需要轉換器。)

  4. 向轉換器單元的輸入添加一個回調。我將這稱爲「流程回調」。

現在關鍵的一點是,定期調用由操作系統到MIC回調將驅動整個處理鏈:

  • 在MIC回叫,準備一個與麥克風可用的輸入樣本數量一樣大的緩衝區,然後「請求」GENERIC OUTPUT(!)渲染相同數量的樣本(通過調用AudioUnitRender)。請注意,您並不是要求輸入單位進行渲染,而是要求輸出單位在圖表的最後!

  • 通用輸出將轉發呈現請求,直到它到達轉換器單元的輸入回調,即進程回調。在這個例子中,你得到了一個指向緩衝區的輸入參數,你必須填寫請求的樣本數。此時,請INPUT UNIT將樣本準確地渲染到該緩衝區。

  • 和中提琴,你完成了。你只需要開始/停止話筒單元!

    在整個過程的關鍵是,總是有來帶動整個渲染過程,並作爲通用輸出沒有任何規則的「需要」得到的樣品,你有輸出單元手動要求它渲染樣本。並且這必須與麥克風的A/D轉換器同步,該轉換器希望以規則的時間間隔放置樣本。

    理論上你可以鏈中的輸入單元和你的圖,但有兩個問題:

    1. MIC輸入單元計數作爲輸出單元和不能有在圖中,兩個輸出單元...

    2. 當單元連接在一起時,則不能在兩者之間進行回調。如果你在那裏放一個,它將永遠不會被調用...所以你會把回調放在鏈的末尾,並期望「樣本可用」通知將我們從麥克風單元的輸出傳播到通用輸出。但它不會。因此您必須將流程分爲麥克風輸入單元和處理鏈。

    最後說明:如果要直接呈現的麥克風的樣本插入到所述轉換器單元,那麼你必須設置相同的流格式(優選遠程IO(即16位的規範輸出格式,整數)的轉換器單元的輸入和麥克風單元的輸出(即遠程io,總線1的輸入範圍)。