如何将AUGraph的输出写入文件?

我试图写一个简单的应用程序(应该是什么),在AUGraph中有一堆audio单元,然后将输出写入文件。 我使用AUGraphAddRenderNotify添加了一个callback。 这是我的callback函数:

OSStatus MyAURenderCallback(void *inRefCon, AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { if (*actionFlags & kAudioUnitRenderAction_PostRender) { ExtAudioFileRef outputFile = (ExtAudioFileRef)inRefCon; ExtAudioFileWriteAsync(outputFile, inNumberFrames, ioData); } } 

这种作品。 该文件是可播放的,我可以听到我录制的内容,但有可怕的数量的静态,使其几乎听不到。

有人知道这有什么问题吗? 还是有人知道更好的方法来loggingAUGraph输出到文件?

谢谢您的帮助。

刚才我对audio单元有了一个顿悟,帮助我解决了自己的问题。 我对audio单元连接和呈现callback是如何工作有一个误解。 我认为他们是完全分开的东西,但事实certificate,一个连接只是一个渲染callback的简称。

从audio单元A的输出端到audio单元B的input端执行kAudioUnitProperty_MakeConnection与在单元B的input端进行kAudioUnitProperty_SetRenderCallback并且在audio单元A的输出端上具有callback函数调用AudioUnitRender相同。

我设置我的渲染callback后,通过做连接testing了这一点,并不再调用渲染callback。

因此,我能够通过以下方式解决我的问题:

 AURenderCallbackStruct callbackStruct = {0}; callbackStruct.inputProc = MyAURenderCallback; callbackStruct.inputProcRefCon = mixerUnit; AudioUnitSetProperty(ioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 0, &callbackStruct, sizeof(callbackStruct)); 

而他们我的callback函数做了这样的事情:

 OSStatus MyAURenderCallback(void *inRefCon, AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList *ioData) { AudioUnit mixerUnit = (AudioUnit)inRefCon; AudioUnitRender(mixerUnit, actionFlags, inTimeStamp, 0, inNumberFrames, ioData); ExtAudioFileWriteAsync(outputFile, inNumberFrames, ioData); return noErr; } 

这可能对我来说应该是显而易见的,但既然不是,我敢打赌还有其他人以同样的方式感到困惑,所以希望这对他们也有帮助。

我仍然不确定为什么我遇到了AUGraphAddRenderNotifycallback的麻烦。 稍后我会深入探讨这个问题,但现在我发现了一个似乎可行的解决scheme。

下面是一些来自Apple的示例代码(该项目是PlaySequence,但不是MIDI特定的)可能有所帮助:

 { CAStreamBasicDescription clientFormat = CAStreamBasicDescription(); ca_require_noerr (result = AudioUnitGetProperty(outputUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &clientFormat, &size), fail); size = sizeof(clientFormat); ca_require_noerr (result = ExtAudioFileSetProperty(outfile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat), fail); { MusicTimeStamp currentTime; AUOutputBL outputBuffer (clientFormat, numFrames); AudioTimeStamp tStamp; memset (&tStamp, 0, sizeof(AudioTimeStamp)); tStamp.mFlags = kAudioTimeStampSampleTimeValid; int i = 0; int numTimesFor10Secs = (int)(10. / (numFrames / srate)); do { outputBuffer.Prepare(); AudioUnitRenderActionFlags actionFlags = 0; ca_require_noerr (result = AudioUnitRender (outputUnit, &actionFlags, &tStamp, 0, numFrames, outputBuffer.ABL()), fail); tStamp.mSampleTime += numFrames; ca_require_noerr (result = ExtAudioFileWrite(outfile, numFrames, outputBuffer.ABL()), fail); ca_require_noerr (result = MusicPlayerGetTime (player, &currentTime), fail); if (shouldPrint && (++i % numTimesFor10Secs == 0)) printf ("current time: %6.2f beats\n", currentTime); } while (currentTime < sequenceLength); } } 

也许试试这个。 将audio单元callback中的数据复制到长缓冲区。 播放缓冲区以testing它,然后在确认整个缓冲区正常之后,将整个缓冲区写入文件。