title: record sounds played by my iPhone app with audio units
body: <p>I have red a lot of interesting stuff today about <strong>iOS &amp; Audio Units</strong> and have found a lot of usefull resources (SO included).</p>
  
  <p><strong>First of all</strong>, i am confused with something : Is it really necessary to create an <em>audio graph</em> with <em>mixer unit</em> to record sounds played by an app ? </p>
  
  <p>Or is it sufficient to play sounds with <a href="https://github.com/kstenerud/ObjectAL-for-iPhone" rel="nofollow" title="ObjectAL, luv it !">ObjectAL</a> (or more simply AVAudioPlayer calls) and create a single <em>remote io unit</em> adressed on the correct bus with a recording callback ?</p>
  
  <p><strong>Second</strong>, a more programmatically issue !
  As i'm not already comfortable with <em>Audio Units</em> concepts, i try to adapt the <a href="http://developer.apple.com/library/ios/#samplecode/MixerHost/Introduction/Intro.html" rel="nofollow">apple Mixer Host project</a> with the ability to record the resulting mix. Obviously, i try to do this with the <a href="http://atastypixel.com/blog/using-remoteio-audio-unit/" rel="nofollow">Michael Tyson RemoteIO post</a>.</p>
  
  <p>And I get a EXC_BAD_ACCESS on my callback function :</p>
  
  <pre><code>static OSStatus recordingCallback       (void *inRefCon,
                                    AudioUnitRenderActionFlags *ioActionFlags,
                                    const AudioTimeStamp *inTimeStamp,
                                    UInt32        inBusNumber,
                                    UInt32        inNumberFrames,
                                    AudioBufferList *ioData) {
  
      AudioBufferList *bufferList; // &lt;- Fill this up with buffers (you will want to malloc it, as it's a dynamic-length list)
  
      EffectState *effectState = (EffectState *)inRefCon;
      AudioUnit rioUnit = effectState-&gt;rioUnit;
  
      OSStatus status;
  
      // BELOW I GET THE ERROR
      status = AudioUnitRender(rioUnit,      
                               ioActionFlags, 
                               inTimeStamp, 
                               inBusNumber, 
                               inNumberFrames, 
                               bufferList);
  
      if (noErr != status) { NSLog(@"AudioUnitRender error"); return noErr;}
  
      // Now, we have the samples we just read sitting in buffers in bufferList
      //ExtAudioFileWriteAsync(effectState-&gt;audioFileRef, inNumberFrames, bufferList);
  
      return noErr;
  }
  </code></pre>
  
  <p>Before using the callback function i did in <strong>MixerHostAudio.h</strong></p>
  
  <pre><code>typedef struct {
      AudioUnit rioUnit;
      ExtAudioFileRef audioFileRef;
  } EffectState;
  </code></pre>
  
  <p>And create in the interface :</p>
  
  <pre><code>AudioUnit                       iOUnit;
  EffectState effectState;
  AudioStreamBasicDescription     iOStreamFormat;
  ...
  @property                       AudioUnit           iOUnit;
  @property (readwrite)           AudioStreamBasicDescription iOStreamFormat;
  </code></pre>
  
  <p>Then in the implementation file <strong>MixerHostAudio.h</strong> :</p>
  
  <pre><code>#define kOutputBus 0
  #define kInputBus 1
  ...
  @synthesize iOUnit;                    // the Remote IO unit
  ...
  result =    AUGraphNodeInfo (
                               processingGraph,
                               iONode,
                               NULL,
                               &amp;iOUnit
                               );
  
  if (noErr != result) {[self printErrorMessage: @"AUGraphNodeInfo" withStatus: result]; return;}
  
  // Enable IO for recording
  UInt32 flag = 1;
  result = AudioUnitSetProperty(iOUnit, 
                                kAudioOutputUnitProperty_EnableIO, 
                                kAudioUnitScope_Input, 
                                kInputBus,
                                &amp;flag, 
                                sizeof(flag));
  
  if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}
  // Describe format
  iOStreamFormat.mSampleRate          = 44100.00;
  iOStreamFormat.mFormatID            = kAudioFormatLinearPCM;
  iOStreamFormat.mFormatFlags     = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
  iOStreamFormat.mFramesPerPacket = 1;
  iOStreamFormat.mChannelsPerFrame    = 1;
  iOStreamFormat.mBitsPerChannel      = 16;
  iOStreamFormat.mBytesPerPacket      = 2;
  iOStreamFormat.mBytesPerFrame       = 2;
  
  // Apply format
  result = AudioUnitSetProperty(iOUnit, 
                                kAudioUnitProperty_StreamFormat, 
                                kAudioUnitScope_Output, 
                                kInputBus, 
                                &amp;iOStreamFormat, 
                                sizeof(iOStreamFormat));
  
  if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}
  
  result = AudioUnitSetProperty(iOUnit, 
                                kAudioUnitProperty_StreamFormat, 
                                kAudioUnitScope_Input, 
                                kOutputBus, 
                                &amp;iOStreamFormat, 
                                sizeof(iOStreamFormat));
  
  if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}
  
  effectState.rioUnit = iOUnit;
  
  // Set input callback ----&gt; RECORDING
  AURenderCallbackStruct callbackStruct;
  callbackStruct.inputProc = recordingCallback;
  callbackStruct.inputProcRefCon = self;
  result = AudioUnitSetProperty(iOUnit, 
                                kAudioOutputUnitProperty_SetInputCallback, 
                                kAudioUnitScope_Global, 
                                kInputBus, 
                                &amp;callbackStruct, 
                                sizeof(callbackStruct));
  
  if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty" withStatus: result]; return;}
  </code></pre>
  
  <p>But I don't know what's wrong and don't know how to digg.
  Note : The <em>EffectState</em> struct is present because I also try to integrate the <a href="https://github.com/brennon/BioAudio" rel="nofollow">BioAudio project</a> ability to write file from buffers.</p>
  
  <p><strong>And Third</strong>, I wonder if there something easier to do to record sounds played by my iPhone app (ie microphone excluded) ?</p>