I am trying to record from a RemoteIO device directly to AAC in renderCallback in iOS 5 on iPad 2. I saw conflicting information that this is not possible and that it is possible (in the comments here ). My reason for this is that writing to PCM requires so much disk space to record any length, even if it is subsequently converted to AAC.
I'm ready to give up, though. I slipped through Google, SO, the Core Audio book and the Apple Core-Audio mailing list and forums and reached the point where I get no errors and write something to disk, but the resulting file does not play. This applies to both the simulator and the device.
So ... if anyone has experience with this, I would really like to push you in the right direction. The setup is that RemoteIO plays the output from AUSamplers and works fine.
Here is what I do in the code below
Specify AudioStreamBasicDescription formats for the remote device unit to kAudioFormatLinearPCM
Create and specify a destination format for ExtAudioFileRef Specify the client format by extracting it from the RemoteIO module.
Specify renderCallback for the RemoteID module
In renderCallback, write data to the kAudioUnitRenderAction_PostRender phase
As I said, I do not get any errors, and as a result, the sizes of the audio files show that something is written, but the file does not play. Perhaps I have my own formats?
In any case, this is my message in the bottle and / or the flag โBe Here Dragonsโ for everyone who dares to the dark waters of Core-Audio.
// Unhappy msg that I get when I try to play the file:

// remoteIO configuration part
// Enable IO for recording UInt32 flag = 1; result = AudioUnitSetProperty(ioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, // == 1 &flag, sizeof(flag)); if (noErr != result) {[self printErrorMessage: @"Enable IO for recording" withStatus: result]; return;} // Describe format - - - - - - - - - - size_t bytesPerSample = sizeof (AudioUnitSampleType); AudioStreamBasicDescription audioFormat; memset(&audioFormat, 0, sizeof(audioFormat)); audioFormat.mSampleRate = 44100.00; audioFormat.mFormatID = kAudioFormatLinearPCM; audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked; audioFormat.mFramesPerPacket = 1; audioFormat.mChannelsPerFrame = 1; audioFormat.mBitsPerChannel = 16; audioFormat.mBytesPerPacket = 2; audioFormat.mBytesPerFrame = 2; result = AudioUnitSetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, kInputBus, // == 1 &audioFormat, sizeof(audioFormat)); result = AudioUnitSetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, // == 0 &audioFormat, sizeof(audioFormat));
// Function that sets the file and rendercallback
- (void)startRecordingAAC { OSStatus result; NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *recordFile = [documentsDirectory stringByAppendingPathComponent: @"audio.m4a"]; CFURLRef destinationURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)recordFile, kCFURLPOSIXPathStyle, false); AudioStreamBasicDescription destinationFormat; memset(&destinationFormat, 0, sizeof(destinationFormat)); destinationFormat.mChannelsPerFrame = 2; destinationFormat.mFormatID = kAudioFormatMPEG4AAC; UInt32 size = sizeof(destinationFormat); result = AudioFormatGetProperty(kAudioFormatProperty_FormatInfo, 0, NULL, &size, &destinationFormat); if(result) printf("AudioFormatGetProperty %ld \n", result); result = ExtAudioFileCreateWithURL(destinationURL, kAudioFileM4AType, &destinationFormat, NULL, kAudioFileFlags_EraseFile, &extAudioFileRef); if(result) printf("ExtAudioFileCreateWithURL %ld \n", result); AudioStreamBasicDescription clientFormat; memset(&clientFormat, 0, sizeof(clientFormat)); result = AudioUnitGetProperty(ioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, & clientFormat, &size); if(result) printf("AudioUnitGetProperty %ld \n", result); result = ExtAudioFileSetProperty(extAudioFileRef,kExtAudioFileProperty_ClientDataFormat,sizeof(clientFormat),&clientFormat); if(result) printf("ExtAudioFileSetProperty %ld \n", result); result = ExtAudioFileWriteAsync(extAudioFileRef, 0, NULL); if (result) {[self printErrorMessage: @"ExtAudioFileWriteAsync error" withStatus: result];} result = AudioUnitAddRenderNotify(ioUnit, renderCallback, (__bridge void*)self); if (result) {[self printErrorMessage: @"AudioUnitAddRenderNotify" withStatus: result];} }
// And finally rendercallback
static OSStatus renderCallback (void * inRefCon, AudioUnitRenderActionFlags * ioActionFlags, const AudioTimeStamp * inTimeStamp, UInt32 inBusNumber, UInt32 inNumberFrames, AudioBufferList * ioData) { OSStatus result; if (*ioActionFlags == kAudioUnitRenderAction_PostRender){ MusicPlayerController* THIS = (__bridge MusicPlayerController *)inRefCon; result = ExtAudioFileWriteAsync(THIS->extAudioFileRef, inNumberFrames, ioData); if(result) printf("ExtAudioFileWriteAsync %ld \n", result); } return noErr; }