我正在尝试将传入的麦克风音频写入文件。因为音频样本在时间紧迫的回调中一次传送 4096 帧(我的项目的设置帧速率),所以我不能简单地将字节写入使用 AudioFileWriteBytes 的文件。我也不希望通过设置自己的环形缓冲区来存储样本以在其他地方写入的努力和复杂性。因此,我将扩展音频文件 API 用于其 ExtAudioFileWriteAsync 函数。
根据文档的指示,我使用 CFURL 创建了 ExtAudioFileRef,然后使用空缓冲区和 main 中的 0 帧运行它一次。然后我启动我的 AUHAL 单元并开始调用输入回调。
ExtAudioFileWriteAsync(player.recordFile, 0, NULL);
我有我的代码可以异步写入这个文件。我将调用嵌套在调度队列中,以便它在回调函数退出范围后运行(不确定是否有必要,但在没有封闭调度块的情况下出现此错误)。这是现在的回调。
OSStatus InputRenderProc(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList * ioData)
{
MyAUGraphPlayer *player = (MyAUGraphPlayer*) inRefCon;
// rendering incoming mic samples to player->inputBuffer
OSStatus inputProcErr = noErr;
inputProcErr = AudioUnitRender(player->inputUnit,
ioActionFlags,
inTimeStamp,
inBusNumber,
inNumberFrames,
player->inputBuffer);
printf("%i", inNumberFrames);
dispatch_async(player->fileWritingQueue, ^{
ExtAudioFileWriteAsync(player->recordFile, 4096, player->inputBuffer);
});
return inputProcErr;
}
它在第一次回调调用时立即退出错误访问异常。为清楚起见,这些是我开始创建文件时的设置。
// describe a PCM format for audio file
AudioStreamBasicDescription format = { 0 };
format.mBytesPerFrame = 4;
format.mBytesPerPacket = 4;
format.mChannelsPerFrame = 2;
format.mBitsPerChannel = 16;
format.mFramesPerPacket = 1;
format.mFormatFlags = kAudioFormatFlagIsPacked | kAudioFormatFlagIsFloat;
format.mFormatID = kAudioFormatLinearPCM;
CFURLRef myFileURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("./test2.wav"), kCFURLPOSIXPathStyle, false);
ExtAudioFileCreateWithURL(myFileURL,
kAudioFileWAVEType,
&format,
NULL,
kAudioFileFlags_EraseFile,
&player.recordFile);
player.fileWritingQueue = dispatch_queue_create("myQueue", NULL);
ExtAudioFileWriteAsync(player.recordFile, 0, NULL);