2012-07-18 140 views
1

我一直在這個昨天掙扎,真的很感激幫助。音頻單元錄製噪音

我有一個多通道混音器音頻單元,分配給每個通道的回調函數在調用時填充所需的音頻緩衝區。我試圖通過將數據寫入文件來在相同的回調中進行記錄。

此刻音頻記錄爲噪音,如果我不打電話給AudioUnitRender,如果我確實打電話給我,我會得到兩個錯誤。錯誤10877和錯誤50.

回調的記錄代碼看起來像這樣

if (recordingOn) 
{ 
    AudioBufferList *bufferList = (AudioBufferList *)malloc(sizeof(AudioBuffer)); 

    SInt16 samples[inNumberFrames]; 
    memset (&samples, 0, sizeof (samples)); 

    bufferList->mNumberBuffers = 1; 
    bufferList->mBuffers[0].mData = samples; 
    bufferList->mBuffers[0].mNumberChannels = 2; 
    bufferList->mBuffers[0].mDataByteSize = inNumberFrames*sizeof(SInt16); 

    OSStatus status; 
    status = AudioUnitRender(audioObject.mixerUnit,  
          ioActionFlags, 
          inTimeStamp, 
          inBusNumber, 
          inNumberFrames, 
          bufferList); 

    if (noErr != status) { 
     printf("AudioUnitRender error: %ld", status); 
     return noErr; 
    } 

    ExtAudioFileWriteAsync(audioObject.recordingFile, inNumberFrames, bufferList); 
} 

是不是正確的在每個通道的回調將數據寫入或者我應該把它連接到遠程I/O單元?

我使用LPCM和ASBD的記錄文件(CAF)是

recordingFormat.mFormatID = kAudioFormatLinearPCM; 
recordingFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | 
kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsPacked; 
recordingFormat.mSampleRate = 44100; 
recordingFormat.mChannelsPerFrame = 2; 
recordingFormat.mFramesPerPacket = 1; 
recordingFormat.mBytesPerPacket = recordingFormat.mChannelsPerFrame * sizeof (SInt16); 
recordingFormat.mBytesPerFrame = recordingFormat.mChannelsPerFrame * sizeof (SInt16); 
recordingFormat.mBitsPerChannel = 16; 

我真的不知道我在做什麼錯。

在寫入文件之前,立體聲如何影響記錄數據的處理方式?

回答

2

有幾個問題。如果您試圖記錄最終的「混音」,則可以使用AudioUnitAddRenderNotify(iounit,callback,file)在I/O單元上添加回調。回調然後簡單地採用ioData並將其傳遞給ExtAudioFileWriteAsync(...)。所以,你也不需要創建任何緩衝區。附註:在渲染線程中分配內存不好。你應該避免渲染回調中的所有系統調用。不能保證這些調用將在音頻線程的非常嚴格的最後期限內執行。因此,爲什麼有一個ExtAudioFileWriteAsync,它會考慮到這一點,並在另一個線程中寫入磁盤。

+0

我真的很感激幫助。這些音頻問題的意見越來越少。好吧,我會補充一點,看看它是如何發展的。所以在這個添加的錄音回調中,我可以將&ioData傳遞給writeAsync調用?關於回調中的分配,是的,它真的很糟糕,我的頭目前一團糟,需要一步一步分解。我也在回調中做這個[[NSNotificationCenter defaultCenter] postNotificationName:MixerAudioObjectSampleFinishedPlayingNotification object:nil];以便通過kMultiChannelMixerParam_Enable將完成的通道設置爲無聲。這是不好的權利? – jarryd 2012-07-18 12:39:06

+0

是的,那很糟糕。常用的方法是在主線程中進行輪詢並收聽/觀看數據。並且該數據應該是一個c結構或C++對象。是的,ioData在緩衝區列表中具有渲染的音頻。 – 2012-07-19 23:15:53

0

我找到了一個演示代碼,也許有用4 U;

DEMO網址:https://github.com/JNYJdev/AudioUnit

OR

博客:http://atastypixel.com/blog/using-remoteio-audio-unit/

static OSStatus recordingCallback(void *inRefCon, 
          AudioUnitRenderActionFlags *ioActionFlags, 
          const AudioTimeStamp *inTimeStamp, 
          UInt32 inBusNumber, 
          UInt32 inNumberFrames, 
          AudioBufferList *ioData) { 
// Because of the way our audio format (setup below) is chosen: 
// we only need 1 buffer, since it is mono 
// Samples are 16 bits = 2 bytes. 
// 1 frame includes only 1 sample 

AudioBuffer buffer; 

buffer.mNumberChannels = 1; 
buffer.mDataByteSize = inNumberFrames * 2; 
buffer.mData = malloc(inNumberFrames * 2); 

// Put buffer in a AudioBufferList 
AudioBufferList bufferList; 
bufferList.mNumberBuffers = 1; 
bufferList.mBuffers[0] = buffer; 

// Then: 
// Obtain recorded samples 

OSStatus status; 

status = AudioUnitRender([iosAudio audioUnit], 
        ioActionFlags, 
        inTimeStamp, 
        inBusNumber, 
        inNumberFrames, 
        &bufferList); 
checkStatus(status); 

// Now, we have the samples we just read sitting in buffers in bufferList 
// Process the new data 
[iosAudio processAudio:&bufferList]; 

// release the malloc'ed data in the buffer we created earlier 
free(bufferList.mBuffers[0].mData); 

return noErr; 
}