Question

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?

Was it helpful?

Solution

Aside from the (fairly arduous but better covered by Apple's example code) setup process of RemoteIO itself, the key points of insight were:

  1. Using the same 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.
  2. Set an "isRecording" bool so that you can turn on and off write-to-file without having to tear down and re-set-up your RemoteIO session
  3. It is ok to write to a file in the 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.
  4. Also, be sure to use a copy of the ioData that got passed into the callback

in recordingCallback after AudioUnitRender into bufferList:

    AudioDeviceManager* THIS = (__bridge AudioDeviceManager *)inRefCon;
    if (THIS->isRecording) {
      ExtAudioFileWriteAsync(THIS->extAudioFileRef, inNumberFrames, bufferList);
    }
  1. Start and stop recording functions, for reference:

-(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!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top