title: how to play music with audiounit and augraph in iphone sdk
body: <p>I am new to AudioUnit and AUGraph services.
  My need is to play a single sound file using these sevices.
   I have downloaded MixerHost project from apple's developer site and changed some codes.
  But the code is crashing now</p>
  
  <p>my new changed code is:</p>
  
  <pre><code>#import "JKAudioPlayer.h"
  #pragma mark Mixer input bus render callback
  
  //
  //    Declared as AURenderCallback in AudioUnit/AUComponent.h. See Audio Unit Component Services Reference.
  static OSStatus inputRenderCallback (
  
                                       void                        *inRefCon,  
                                       AudioUnitRenderActionFlags  *ioActionFlags, 
                                       const AudioTimeStamp        *inTimeStamp,  
                                       UInt32                      inBusNumber,  
                                       UInt32                      inNumberFrames,
                                       AudioBufferList             *ioData   
                                       ) {
  
      soundStructPtr    soundStructPointerArray   = (soundStructPtr) inRefCon;
      UInt32            frameTotalForSound        = soundStructPointerArray[inBusNumber].frameCount;
      BOOL              isStereo                  = soundStructPointerArray[inBusNumber].isStereo;
  
      AudioUnitSampleType *dataInLeft;
      AudioUnitSampleType *dataInRight;
  
      dataInLeft                 = soundStructPointerArray[inBusNumber].audioDataLeft;
      if (isStereo) dataInRight  = soundStructPointerArray[inBusNumber].audioDataRight;
  
      AudioUnitSampleType *outSamplesChannelLeft;
      AudioUnitSampleType *outSamplesChannelRight;
  
      outSamplesChannelLeft                 = (AudioUnitSampleType *) ioData-&gt;mBuffers[0].mData;
      if (isStereo) outSamplesChannelRight  = (AudioUnitSampleType *) ioData-&gt;mBuffers[1].mData;
  
      UInt32 sampleNumber = soundStructPointerArray[0].sampleNumber;
  
      for (UInt32 frameNumber = 0; frameNumber &lt; inNumberFrames; ++frameNumber) {
          outSamplesChannelLeft[frameNumber]                 = dataInLeft[sampleNumber];
          if (isStereo) outSamplesChannelRight[frameNumber]  = dataInRight[sampleNumber];
          sampleNumber++;
          if (sampleNumber &gt;= frameTotalForSound) sampleNumber = 0;
      }
      soundStructPointerArray[inBusNumber].sampleNumber = sampleNumber;
      return noErr;
  }
  
  #pragma mark -
  #pragma mark Audio route change listener callback
  static void audioRouteChangeListenerCallback (
                                                void                      *inUserData,
                                                AudioSessionPropertyID    inPropertyID,
                                                UInt32                    inPropertyValueSize,
                                                const void                *inPropertyValue
                                                ) {
      if (inPropertyID != kAudioSessionProperty_AudioRouteChange) return;
      JKAudioPlayer *audioObject = (__bridge_transfer JKAudioPlayer *) inUserData;  
      if (NO == audioObject.isPlaying) {
          NSLog (@"Audio route change while application audio is stopped.");
          return;
      } else {
          CFDictionaryRef routeChangeDictionary = inPropertyValue;
          CFNumberRef routeChangeReasonRef =
          CFDictionaryGetValue (
                                routeChangeDictionary,
                                CFSTR (kAudioSession_AudioRouteChangeKey_Reason)
                                );
  
          SInt32 routeChangeReason;
  
          CFNumberGetValue (
                            routeChangeReasonRef,
                            kCFNumberSInt32Type,
                            &amp;routeChangeReason
                            );        
          if (routeChangeReason == kAudioSessionRouteChangeReason_OldDeviceUnavailable) {
  
              NSLog (@"Audio output device was removed; stopping audio playback.");
              NSString *MixerHostAudioObjectPlaybackStateDidChangeNotification = @"MixerHostAudioObjectPlaybackStateDidChangeNotification";
              [[NSNotificationCenter defaultCenter] postNotificationName: MixerHostAudioObjectPlaybackStateDidChangeNotification object: audioObject]; 
  
          } else {
  
              NSLog (@"A route change occurred that does not require stopping application audio.");
          }
      }
  }
  
  @implementation JKAudioPlayer
  @synthesize monoStreamFormat;           // mono format for use in buffer and mixer input for "beats" sound
  @synthesize graphSampleRate;            // sample rate to use throughout audio processing chain
  @synthesize mixerUnit;                  // the Multichannel Mixer unit
  @synthesize playing;                    // Boolean flag to indicate whether audio is playing or not
  @synthesize interruptedDuringPlayback;  // Boolean flag to indicate whether audio was playing when an interruption arrived
  - (id) init {
  
      self = [super init];
  
      if (!self) return nil;
      NSURL *beatsLoop   = [[NSBundle mainBundle] URLForResource: @"beatsMono"
                                                   withExtension: @"caf"];
      sourceURL   = (__bridge_retained  CFURLRef) beatsLoop;
      self.interruptedDuringPlayback = NO;
      [self setupAudioSession];    
      [self setupMonoStreamFormat];
      [self readAudioFilesIntoMemory];
      [self configureAndInitializeAudioProcessingGraph];
      [self enableMixerInput: 0 isOn: YES];
      [self setMixerOutputGain:1];
      [self setMixerInput: 0 gain:YES];
      return self;
  }
  - (void) setupAudioSession {
      AVAudioSession *mySession = [AVAudioSession sharedInstance];
      [mySession setDelegate: self];
      NSError *audioSessionError = nil;
      [mySession setCategory: AVAudioSessionCategoryPlayback
                       error: &amp;audioSessionError];
  
      if (audioSessionError != nil) {
  
          NSLog (@"Error setting audio session category.");
          return;
      }
      self.graphSampleRate = 44100.0;    // Hertz
      [mySession setPreferredHardwareSampleRate: graphSampleRate
                                          error: &amp;audioSessionError];
      if (audioSessionError != nil) {
  
          NSLog (@"Error setting preferred hardware sample rate.");
          return;
      }
      [mySession setActive: YES
                     error: &amp;audioSessionError];
  
      if (audioSessionError != nil) {
  
          NSLog (@"Error activating audio session during initial setup.");
          return;
      }    
      self.graphSampleRate = [mySession currentHardwareSampleRate];
      AudioSessionAddPropertyListener (
                                       kAudioSessionProperty_AudioRouteChange,
                                       audioRouteChangeListenerCallback,
                                       (__bridge void*)self
                                       );
  }
  - (void) setupMonoStreamFormat {
      size_t bytesPerSample = sizeof (AudioUnitSampleType);
      monoStreamFormat.mFormatID          = kAudioFormatLinearPCM;
      monoStreamFormat.mFormatFlags       = kAudioFormatFlagsAudioUnitCanonical;
      monoStreamFormat.mBytesPerPacket    = bytesPerSample;
      monoStreamFormat.mFramesPerPacket   = 1;
      monoStreamFormat.mBytesPerFrame     = bytesPerSample;
      monoStreamFormat.mChannelsPerFrame  = 1;                  // 1 indicates mono
      monoStreamFormat.mBitsPerChannel    = 8 * bytesPerSample;
      monoStreamFormat.mSampleRate        = graphSampleRate;
  }
  
  
  - (void) readAudioFilesIntoMemory {
      ExtAudioFileRef audioFileObject = 0;
      OSStatus result = ExtAudioFileOpenURL (sourceURL, &amp;audioFileObject);
      if (noErr != result || NULL == audioFileObject) {NSLog(@"error ext audiofile open url %ld",result); return;}
      UInt64 totalFramesInFile = 0;
      UInt32 frameLengthPropertySize = sizeof (totalFramesInFile);
      result =    ExtAudioFileGetProperty (
                                           audioFileObject,
                                           kExtAudioFileProperty_FileLengthFrames,
                                           &amp;frameLengthPropertySize,
                                           &amp;totalFramesInFile
                                           );
  
      if (noErr != result) {NSLog(@"ExtAudioFileGetProperty (audio file length in frames %ld",result); return;}
      soundStruct.frameCount = totalFramesInFile;
      AudioStreamBasicDescription fileAudioFormat = {0};
      UInt32 formatPropertySize = sizeof (fileAudioFormat);
      result =    ExtAudioFileGetProperty (
                                           audioFileObject,
                                           kExtAudioFileProperty_FileDataFormat,
                                           &amp;formatPropertySize,
                                           &amp;fileAudioFormat
                                           );
  
      if (noErr != result) {NSLog( @"ExtAudioFileGetProperty (file audio format)%ld",result); return;}
  
      UInt32 channelCount = fileAudioFormat.mChannelsPerFrame;
      soundStruct.audioDataLeft =
      (AudioUnitSampleType *) calloc (totalFramesInFile, sizeof (AudioUnitSampleType));
  
      AudioStreamBasicDescription importFormat = {0};
      if (1 == channelCount) {
  
          soundStruct.isStereo = NO;
          importFormat = monoStreamFormat;
  
      } else {
  
          NSLog (@"*** WARNING: File format not supported - wrong number of channels");
          ExtAudioFileDispose (audioFileObject);
          return;
      }
      result =    ExtAudioFileSetProperty (
                                           audioFileObject,
                                           kExtAudioFileProperty_ClientDataFormat,
                                           sizeof (importFormat),
                                           &amp;importFormat
                                           );
  
      if (noErr != result) {NSLog( @"ExtAudioFileSetProperty (client data format %ld", result); return;}
      AudioBufferList *bufferList;
      bufferList = (AudioBufferList *) malloc (
                                               sizeof (AudioBufferList) + sizeof (AudioBuffer) * (channelCount - 1)
                                               );
  
      if (NULL == bufferList) {NSLog (@"*** malloc failure for allocating bufferList memory"); return;}
  
      bufferList-&gt;mNumberBuffers = channelCount;
      AudioBuffer emptyBuffer = {0};
      size_t arrayIndex;
      for (arrayIndex = 0; arrayIndex &lt; channelCount; arrayIndex++) {
          bufferList-&gt;mBuffers[arrayIndex] = emptyBuffer;
      }
      bufferList-&gt;mBuffers[0].mNumberChannels  = 1;
      bufferList-&gt;mBuffers[0].mDataByteSize    = totalFramesInFile * sizeof (AudioUnitSampleType);
      bufferList-&gt;mBuffers[0].mData            = soundStruct.audioDataLeft;
  
      if (2 == channelCount) {
          bufferList-&gt;mBuffers[1].mNumberChannels  = 1;
          bufferList-&gt;mBuffers[1].mDataByteSize    = totalFramesInFile * sizeof (AudioUnitSampleType);
          bufferList-&gt;mBuffers[1].mData            = soundStruct.audioDataRight;
      }
  
      UInt32 numberOfPacketsToRead = (UInt32) totalFramesInFile;
  
      result = ExtAudioFileRead (
                                 audioFileObject,
                                 &amp;numberOfPacketsToRead,
                                 bufferList
                                 );
  
      free (bufferList);
  
      if (noErr != result) {
  
          NSLog( @"ExtAudioFileRead failure - %ld " , result);
          free (soundStruct.audioDataLeft);
          soundStruct.audioDataLeft = 0;
  
          if (2 == channelCount) {
              free (soundStruct.audioDataRight);
              soundStruct.audioDataRight = 0;
          }
  
          ExtAudioFileDispose (audioFileObject);            
          return;
      }
  
      NSLog (@"Finished reading file  into memory");
      soundStruct.sampleNumber = 0;
      ExtAudioFileDispose (audioFileObject);
  }
  
  - (void) configureAndInitializeAudioProcessingGraph {
  
      NSLog (@"Configuring and then initializing audio processing graph");
      OSStatus result = noErr;
      result = NewAUGraph (&amp;processingGraph);
  
      if (noErr != result) {[self printErrorMessage: @"NewAUGraph" withStatus: result]; return;}
  
      // I/O unit
      AudioComponentDescription iOUnitDescription;
      iOUnitDescription.componentType          = kAudioUnitType_Output;
      iOUnitDescription.componentSubType       = kAudioUnitSubType_RemoteIO;
      iOUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
      iOUnitDescription.componentFlags         = 0;
      iOUnitDescription.componentFlagsMask     = 0;
  
      // Multichannel mixer unit
      AudioComponentDescription MixerUnitDescription;
      MixerUnitDescription.componentType          = kAudioUnitType_Mixer;
      MixerUnitDescription.componentSubType       = kAudioUnitSubType_MultiChannelMixer;
      MixerUnitDescription.componentManufacturer  = kAudioUnitManufacturer_Apple;
      MixerUnitDescription.componentFlags         = 0;
      MixerUnitDescription.componentFlagsMask     = 0;
  
  
      //............................................................................
      // Add nodes to the audio processing graph.
      NSLog (@"Adding nodes to audio processing graph");
  
      AUNode   iONode;         // node for I/O unit
      AUNode   mixerNode;      // node for Multichannel Mixer unit
  
      // Add the nodes to the audio processing graph
      result =    AUGraphAddNode (
                                  processingGraph,
                                  &amp;iOUnitDescription,
                                  &amp;iONode);
  
      if (noErr != result) {[self printErrorMessage: @"AUGraphNewNode failed for I/O unit" withStatus: result]; return;}
  
  
      result =    AUGraphAddNode (
                                  processingGraph,
                                  &amp;MixerUnitDescription,
                                  &amp;mixerNode
                                  );
  
      if (noErr != result) {[self printErrorMessage: @"AUGraphNewNode failed for Mixer unit" withStatus: result]; return;}
      result = AUGraphOpen (processingGraph);
  
      if (noErr != result) {[self printErrorMessage: @"AUGraphOpen" withStatus: result]; return;}
       result =    AUGraphNodeInfo (
                                   processingGraph,
                                   mixerNode,
                                   NULL,
                                   &amp;mixerUnit
                                   );
  
      if (noErr != result) {[self printErrorMessage: @"AUGraphNodeInfo" withStatus: result]; return;}
      UInt32 busCount   = 2;    // bus count for mixer unit input
  
      UInt32 beatsBus   = 1;    // mixer unit bus 1 will be mono and will take the beats sound
  
      NSLog (@"Setting mixer unit input bus count to: %lu", busCount);
      result = AudioUnitSetProperty (
                                     mixerUnit,
                                     kAudioUnitProperty_ElementCount,
                                     kAudioUnitScope_Input,
                                     0,
                                     &amp;busCount,
                                     sizeof (busCount)
                                     );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty (set mixer unit bus count)" withStatus: result]; return;}
     UInt32 maximumFramesPerSlice = 4096;
  
      result = AudioUnitSetProperty (
                                     mixerUnit,
                                     kAudioUnitProperty_MaximumFramesPerSlice,
                                     kAudioUnitScope_Global,
                                     0,
                                     &amp;maximumFramesPerSlice,
                                     sizeof (maximumFramesPerSlice)
                                     );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty (set mixer unit input stream format)" withStatus: result]; return;}
      for (UInt16 busNumber = 0; busNumber &lt; busCount; ++busNumber) {
  
          // Setup the struture that contains the input render callback 
          AURenderCallbackStruct inputCallbackStruct;
          inputCallbackStruct.inputProc        = &amp;inputRenderCallback;
          inputCallbackStruct.inputProcRefCon  = &amp;soundStruct;
  
          NSLog (@"Registering the render callback with mixer unit input bus %u", busNumber);
          // Set a callback for the specified node's specified input
          result = AUGraphSetNodeInputCallback (
                                                processingGraph,
                                                mixerNode,
                                                busNumber,
                                                &amp;inputCallbackStruct
                                                );
  
          if (noErr != result) {[self printErrorMessage: @"AUGraphSetNodeInputCallback" withStatus: result]; return;}
      }
  
  
      NSLog (@"Setting mono stream format for mixer unit \"beats\" input bus");
      result = AudioUnitSetProperty (
                                     mixerUnit,
                                     kAudioUnitProperty_StreamFormat,
                                     kAudioUnitScope_Input,
                                     beatsBus,
                                     &amp;monoStreamFormat,
                                     sizeof (monoStreamFormat)
                                     );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty (set mixer unit beats input bus stream format)" withStatus: result];return;}
  
  
      NSLog (@"Setting sample rate for mixer unit output scope");
       result = AudioUnitSetProperty (
                                     mixerUnit,
                                     kAudioUnitProperty_SampleRate,
                                     kAudioUnitScope_Output,
                                     0,
                                     &amp;graphSampleRate,
                                     sizeof (graphSampleRate)
                                     );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetProperty (set mixer unit output stream format)" withStatus: result]; return;}
       NSLog (@"Connecting the mixer output to the input of the I/O unit output element");
  
      result = AUGraphConnectNodeInput (
                                        processingGraph,
                                        mixerNode,         // source node
                                        0,                 // source node output bus number
                                        iONode,            // destination node
                                        0                  // desintation node input bus number
                                        );
  
      if (noErr != result) {[self printErrorMessage: @"AUGraphConnectNodeInput" withStatus: result]; return;}
      CAShow (processingGraph);
      result = AUGraphInitialize (processingGraph);
  
      if (noErr != result) {[self printErrorMessage: @"AUGraphInitialize" withStatus: result]; return;}
  }
  
  // Start playback
  - (void) startAUGraph  {
       OSStatus result = AUGraphStart (processingGraph);
      if (noErr != result) {[self printErrorMessage: @"AUGraphStart" withStatus: result]; return;}
  
      self.playing = YES;
  }
  
  // Stop playback
  - (void) stopAUGraph {
      Boolean isRunning = false;
      OSStatus result = AUGraphIsRunning (processingGraph, &amp;isRunning);
      if (noErr != result) {[self printErrorMessage: @"AUGraphIsRunning" withStatus: result]; return;}
  
      if (isRunning) {
  
          result = AUGraphStop (processingGraph);
          if (noErr != result) {[self printErrorMessage: @"AUGraphStop" withStatus: result]; return;}
          self.playing = NO;
      }
  }
  
  - (void) enableMixerInput: (UInt32) inputBus isOn: (AudioUnitParameterValue) isOnValue {
     OSStatus result = AudioUnitSetParameter (
                                               mixerUnit,
                                               kMultiChannelMixerParam_Enable,
                                               kAudioUnitScope_Input,
                                               inputBus,
                                               isOnValue,
                                               0
                                               );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetParameter (enable the mixer unit)" withStatus: result]; return;}
  
  
  }
  
  - (void) setMixerInput: (UInt32) inputBus gain: (AudioUnitParameterValue) newGain {
      NSLog(@"mixer input %lu gain %f",inputBus,newGain);
  
      OSStatus result = AudioUnitSetParameter (
                                               mixerUnit,
                                               kMultiChannelMixerParam_Volume,
                                               kAudioUnitScope_Input,
                                               inputBus,
                                               newGain,
                                               0
                                               );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetParameter (set mixer unit input volume)" withStatus: result]; return;}
  
  }
  - (void) setMixerOutputGain: (AudioUnitParameterValue) newGain {
      NSLog(@"mixer output  gain %f",newGain);
      OSStatus result = AudioUnitSetParameter (
                                               mixerUnit,
                                               kMultiChannelMixerParam_Volume,
                                               kAudioUnitScope_Output,
                                               0,
                                               newGain,
                                               0
                                               );
  
      if (noErr != result) {[self printErrorMessage: @"AudioUnitSetParameter (set mixer unit output volume)" withStatus: result]; return;}
  
  }
  - (void) printErrorMessage: (NSString *) errorString withStatus: (OSStatus) result {
  
      char resultString[5];
      UInt32 swappedResult = CFSwapInt32HostToBig (result);
      bcopy (&amp;swappedResult, resultString, 4);
      resultString[4] = '\0';
  
      NSLog (
             @"*** %@ error: %@ %@s",
             errorString,
             (char*) &amp;resultString
             );
  }
  
  @end
  </code></pre>
  
  <p>The app crashes at the point</p>
  
  <p>outSamplesChannelLeft[frameNumber]                 = dataInLeft[sampleNumber];
      if (isStereo) outSamplesChannelRight[frameNumber]  = dataInRight[sampleNumber];
   What is the error with my code
  Can anyone help me</p>