title: iOS, AudioUnits record to local URL
body: <p>In my iPhone application I want to record sounds internally produced by my own application, v.s. recording external sounds captured by the mic. Another way of saying this is that I want to record sound straight off the sound card as it's being played. From there I want to save the new recorded sound file to a specified, local URL. A similar question was posted <a href="https://stackoverflow.com/questions/9493989/record-audio-ios">here</a>. I've read a few tutorials and have some code, however there are a few things I need help with. Here is my code: </p>
  
  <p><strong>header file</strong></p>
  
  <pre><code>OSStatus status;
  </code></pre>
  
  <p><strong>implementation file</strong></p>
  
  <pre><code>#define kOutputBus 0
  #define kInputBus 1
  
  static AudioComponentInstance audioUnit;
  
  static OSStatus recordingCallback(void *inRefCon,
                                    AudioUnitRenderActionFlags *ioActionFlags,
                                    const AudioTimeStamp *inTimeStamp,
                                    UInt32 inBusNumber,
                                    UInt32 inNumberFrames,
                                    AudioBufferList *ioData) {
  
      // TODO: Use inRefCon to access our interface object to do stuff
      // Then, use inNumberFrames to figure out how much data is available, and make
      // that much space available in buffers in an AudioBufferList.
  
      AudioBufferList *bufferList; // &lt;- Fill this up with buffers (you will want to malloc it, as it's a dynamic-length list)
  
      // Then:
      // Obtain recorded samples
  
      OSStatus status;
  
      status = AudioUnitRender([audioInterface audioUnit],
                               ioActionFlags,
                               inTimeStamp,
                               inBusNumber,
                               inNumberFrames,
                               bufferList);
      checkStatus(status);
  
      // Now, we have the samples we just read sitting in buffers in bufferList
      DoStuffWithTheRecordedAudio(bufferList);
      return noErr;
  }
  
  static OSStatus playbackCallback(void *inRefCon,
                                   AudioUnitRenderActionFlags *ioActionFlags,
                                   const AudioTimeStamp *inTimeStamp,
                                   UInt32 inBusNumber,
                                   UInt32 inNumberFrames,
                                   AudioBufferList *ioData) {
      // Notes: ioData contains buffers (may be more than one!)
      // Fill them up as much as you can. Remember to set the size value in each buffer to match how
      // much data is in the buffer.
      return noErr;
  }
  
  
  void initializeInternalAudioRecorder() {
      AudioStreamBasicDescription audioFormat; //this is currently being called as a local variable, try calling it as a golbal variable if it doesnt work
      OSStatus status;
      AudioComponentInstance audioUnit;
  
  
      // Describe audio component
      AudioComponentDescription desc;
      desc.componentType = kAudioUnitType_Output;
      desc.componentSubType = kAudioUnitSubType_RemoteIO;
      desc.componentFlags = 0;
      desc.componentFlagsMask = 0;
      desc.componentManufacturer = kAudioUnitManufacturer_Apple;
  
      // Get component
      AudioComponent inputComponent = AudioComponentFindNext(NULL, &amp;desc);
  
      // Get audio units
      status = AudioComponentInstanceNew(inputComponent, &amp;audioUnit);
      checkStatus(status);
  
      // Enable IO for recording
      UInt32 flag = 1;
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioOutputUnitProperty_EnableIO,
                                    kAudioUnitScope_Input,
                                    kInputBus,
                                    &amp;flag,
                                    sizeof(flag));
      checkStatus(status);
  
      // Enable IO for playback
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioOutputUnitProperty_EnableIO,
                                    kAudioUnitScope_Output,
                                    kOutputBus,
                                    &amp;flag,
                                    sizeof(flag));
      checkStatus(status);
  
      // Describe format
      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;
  
      // Apply format
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioUnitProperty_StreamFormat,
                                    kAudioUnitScope_Output,
                                    kInputBus,
                                    &amp;audioFormat,
                                    sizeof(audioFormat));
      checkStatus(status);
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioUnitProperty_StreamFormat,
                                    kAudioUnitScope_Input,
                                    kOutputBus,
                                    &amp;audioFormat,
                                    sizeof(audioFormat));
      checkStatus(status);
  
  
      // Set input callback
      AURenderCallbackStruct callbackStruct;
      callbackStruct.inputProc = recordingCallback;
      callbackStruct.inputProcRefCon = self;
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioOutputUnitProperty_SetInputCallback,
                                    kAudioUnitScope_Global,
                                    kInputBus,
                                    &amp;callbackStruct,
                                    sizeof(callbackStruct));
      checkStatus(status);
  
      // Set output callback
      callbackStruct.inputProc = playbackCallback;
      callbackStruct.inputProcRefCon = self;
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioUnitProperty_SetRenderCallback,
                                    kAudioUnitScope_Global,
                                    kOutputBus,
                                    &amp;callbackStruct,
                                    sizeof(callbackStruct));
      checkStatus(status);
  
      // Disable buffer allocation for the recorder (optional - do this if we want to pass in our own)
      flag = 0;
      status = AudioUnitSetProperty(audioUnit,
                                    kAudioUnitProperty_ShouldAllocateBuffer,
                                    kAudioUnitScope_Output,
                                    kInputBus,
                                    &amp;flag,
                                    sizeof(flag));
  
      // TODO: Allocate our own buffers if we want
  
      // Initialise
      status = AudioUnitInitialize(audioUnit);
      checkStatus(status);
  }
  
  -(void)startInternalRecorder {
          OSStatus status = AudioOutputUnitStart(audioUnit);
          checkStatus(status);
      }
  
  -(void)stopInternalRecorder {
          OSStatus status = AudioOutputUnitStop(audioUnit);
          checkStatus(status);
          AudioComponentInstanceDispose(audioUnit);
      }
  </code></pre>
  
  <p>Now, I'm getting the following errors in my implementation</p>
  
  <ul>
  <li>'audioInterface' undeclared, </li>
  <li>'self' undeclared,</li>
  </ul>
  
  <p>So my questions are how to fix those errors, and how to specify a URL to save the recorded sound file to.</p>
  
  <p>Here is where I got my code: <a href="http://atastypixel.com/blog/using-remoteio-audio-unit/comment-page-6/#comment-6734" rel="nofollow noreferrer">http://atastypixel.com/blog/using-remoteio-audio-unit/comment-page-6/#comment-6734</a></p>
  
  <p>I know a lot of my problems have to do with my lack of understanding regarding Audio Units, but I would be very very grateful to anyone who helped out. Thank you.</p>