我正在尝试编写(应该是)一个简单的应用程序,它在AUGraph中有一堆顺序的音频单元,然后将输出写入一个文件。我使用AUGraphAddRenderNotify添加了一个回调。下面是我的回调函数:
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);
}
}这是一种可行的方法。该文件是可播放的,我可以听到我录制的内容,但有可怕的静电,使它几乎听不见。
有人知道这是怎么回事吗?或者,是否有人知道更好的方法来将AUGraph输出记录到文件中?
谢谢你的帮助。
发布于 2012-01-26 10:58:15
我刚刚对音频单元有了一个顿悟,这帮助我解决了自己的问题。我对音频单元连接和渲染回调的工作方式有误解。我以为它们是完全不同的东西,但事实证明,连接只是渲染回调的缩写。
从音频单元A的输出到音频单元B的输入执行kAudioUnitProperty_MakeConnection与在单元B的输入上执行kAudioUnitProperty_SetRenderCallback并使回调函数在音频单元A的输出上调用AudioUnitRender相同。
在设置渲染回调之后,我通过执行make connection来测试这一点,渲染回调不再被调用。
因此,我能够通过执行以下操作解决我的问题:
AURenderCallbackStruct callbackStruct = {0};
callbackStruct.inputProc = MyAURenderCallback;
callbackStruct.inputProcRefCon = mixerUnit;
AudioUnitSetProperty(ioUnit,
kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input,
0,
&callbackStruct,
sizeof(callbackStruct));我的回调函数做了这样的事情:
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;
}这对我来说可能是显而易见的,但既然不是这样,我打赌还有其他人也以同样的方式感到困惑,所以希望这对他们也有帮助。
我仍然不确定为什么我在使用AUGraphAddRenderNotify回调时会遇到问题。我稍后会更深入地研究这个问题,但现在我找到了一个似乎可行的解决方案。
发布于 2012-01-23 21:44:39
下面是来自苹果的一些示例代码(该项目是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, ¤tTime), fail);
if (shouldPrint && (++i % numTimesFor10Secs == 0))
printf ("current time: %6.2f beats\n", currentTime);
} while (currentTime < sequenceLength);
}
}发布于 2012-01-22 03:32:48
也许你可以试试这个。将音频单元回调中的数据复制到长缓冲区。播放缓冲区以对其进行测试,然后在验证整个缓冲区正常后将整个缓冲区写入文件。
https://stackoverflow.com/questions/8951458
复制相似问题