I'm using RemoteIO successfully to perform analysis on the incoming audio stream from the mic. I can't seem to get a file written to disk, though. I've read around a number of questions:
And tried to implement the suggestions there: Except they're not working. Where's the correct place to call ExtAudioFileWriteAsync, and how do I set it up?
Aside from the (fairly arduous but better covered by Apple's example code) setup process of RemoteIO itself, the key points of insight were:
AudioStreamBasicDescription
(*audioFormat
) that I used to set up the stream in the first place. I don't know how long I spent trying to set up a new one with slightly different parameters, based on other questions and posts. Just referencing the stream attributes from my ivar was sufficient.recordingCallback
, um, callback, but do it asynchronously. Lots of info talks about doing it in the playbackCallback or setting up some third audioFileWriteCallback. This resulted in silent files or 4KB (i.e. empty) files. Don't do it.in recordingCallback
after AudioUnitRender
into bufferList
:
AudioDeviceManager* THIS = (__bridge AudioDeviceManager *)inRefCon;
if (THIS->isRecording) {
ExtAudioFileWriteAsync(THIS->extAudioFileRef, inNumberFrames, bufferList);
}
-(void)startRecording {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *destinationFilePath = [documentsDirectory stringByAppendingPathComponent:kAudioFileName];
CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (CFStringRef)destinationFilePath, kCFURLPOSIXPathStyle, false);
OSStatus status;
// create the capture file
status = ExtAudioFileCreateWithURL(destinationURL, kAudioFileWAVEType, &audioFormat, NULL, kAudioFileFlags_EraseFile, &extAudioFileRef);
if (status) NSLog(@"Error creating file with URL: %ld", status);
// use the same "audioFormat" AudioStreamBasicDescription we used to set up RemoteIO in the first place
status = ExtAudioFileSetProperty(extAudioFileRef, kExtAudioFileProperty_ClientDataFormat, sizeof(AudioStreamBasicDescription), &audioFormat);
ExtAudioFileSeek(extAudioFileRef, 0);
ExtAudioFileWrite(extAudioFileRef, 0, NULL);
isRecording = YES;
}
- (void)stopRecording {
isRecording = NO;
OSStatus status = ExtAudioFileDispose(extAudioFileRef);
if (status) printf("ExtAudioFileDispose %ld \n", status);
}
That's it!