title: AudioTimeStamp format + 'MusicDeviceMIDIEvent'
body: <p><strong>Can I get a little help with this?</strong></p>
  
  <p>In a test project, I have an <code>AUSampler -&gt; MixerUnit -&gt; ioUnit</code> and have a render callback set up. It all works. I am using the <code>MusicDeviceMIDIEvent</code> method as defined in <code>MusicDevice.h</code> to play a midi noteOn &amp; noteOff. So in the hack test code below, a noteOn occurs for .5 sec. every 2 seconds.</p>
  
  <p><code>MusicDeviceMIDIEvent</code> (below) takes a param: <code>inOffsetSampleFrame</code> in order to schedule an event at a future time. What I would like to be able to do is play a noteOn and schedule the noteOff at the same time (without the hack time check I am doing below). I just don't understand what the <code>inOffsetSampleFrame</code> value should be (ex: to play a .5 sec or .2 second note. (in other words, I don't understand the basics of audio timing...).</p>
  
  <p>So, if someone could walk me through the arithmetic to get proper values from the incoming <code>AudioTimeStamp</code>, that would be great! Also perhaps correct me/clarify any of these:</p>
  
  <ol>
  <li><p><code>AudioTimeStamp-&gt;mSampleTime</code> - sampleTime is the time of the
  current sample "slice"? Is this in milliseconds?</p></li>
  <li><p><code>AudioTimeStamp-&gt;mHostTime</code>  - ? host is the computer the app is running on and this is  time (in milliseconds?) since computer started? This is a <strong>HUGE</strong> number. Doesn't it rollover and then cause problems?</p></li>
  <li><p><code>inNumberFrames</code> - seems like that is 512 on iOS5 (set through
  <code>kAudioUnitProperty_MaximumFramesPerSlice</code>). So the sample is made
  up of 512 frames?</p></li>
  <li><p>I've seen lots of admonitions not to overload the render Callback
  function - in particular to avoid Objective C calls - I understand
  the reason, but how does one then message the UI or do other
  processing?</p></li>
  </ol>
  
  <p>I guess that's it. Thanks for bearing with me!</p>
  
  <blockquote>
    <p><strong>inOffsetSampleFrame</strong>
                    If you are scheduling the MIDI Event from the audio unit's render thread, then you can supply a 
                        sample offset that the audio unit may apply when applying that event in its next audio unit render. 
                        This allows you to schedule to the sample, the time when a MIDI command is applied and is particularly 
                        important when starting new notes. If you are not scheduling in the audio unit's render thread, 
                        then you should set this value to 0</p>
  </blockquote>
  
  <p>// MusicDeviceMIDIEvent function def:</p>
  
  <pre><code>extern OSStatus
  MusicDeviceMIDIEvent(   MusicDeviceComponent    inUnit,
                      UInt32                  inStatus,
                      UInt32                  inData1,
                      UInt32                  inData2,
                      UInt32                  inOffsetSampleFrame)
  </code></pre>
  
  <p>//my callback</p>
  
  <pre><code>OSStatus  MyCallback(   void *                          inRefCon,
                   AudioUnitRenderActionFlags *   ioActionFlags,
                   const AudioTimeStamp *         inTimeStamp,
                   UInt32                         inBusNumber,
                   UInt32                         inNumberFrames,
                   AudioBufferList *              ioData)
  {
  
  Float64 sampleTime = inTimeStamp-&gt;mSampleTime;
  UInt64 hostTime = inTimeStamp-&gt;mHostTime;
  
  [(__bridge Audio*)inRefCon audioEvent:sampleTime andHostTime:hostTime];
  
  return 1;
  }  
  </code></pre>
  
  <p>// OBJ-C method</p>
  
  <pre><code>- (void)audioEvent:(Float64) sampleTime andHostTime:(UInt64)hostTime
  {
  OSStatus result = noErr;
  
  Float64 nowTime = (sampleTime/self.graphSampleRate); // sample rate: 44100.0
  if (nowTime - lastTime &gt; 2) {
  
      UInt32 noteCommand =    kMIDIMessage_NoteOn &lt;&lt; 4 | 0;
      result = MusicDeviceMIDIEvent (mySynthUnit, noteCommand, 60, 120, 0); 
      lastTime = sampleTime/self.graphSampleRate;
  }
  
  if (nowTime - lastTime &gt; .5) {
      UInt32   noteCommand =  kMIDIMessage_NoteOff &lt;&lt; 4 | 0;
      result = MusicDeviceMIDIEvent (mySynthUnit, noteCommand, 60, 0, 0);
  }
  }
  </code></pre>