2017-10-21 83 views
0

有一件事我不明白MusicDeviceMIDIEvent。在我见过的每个例子中(搜索Github和Apple例子),它总是在主线程中使用。现在,为了使用样本偏移参数文档状态:从音频单元的渲染线程调用MusicDeviceMIDIEvent

inOffsetSampleFrame: 如果是从音频单元的渲染线程调度的MIDI事件,那么你可以提供一个 样本偏移音频单元可以在下一个音频单元渲染中应用该事件时应用。 这允许您安排样本,应用MIDI命令的时间,特别是在开始新笔记时重要。如果您没有在音频单元的渲染线程调度, 那么你应该将该值设置为0

不过,即使在最简单的情况下,你只能有一个采样音频单元和一个IO单元,你怎么能从音频单元的渲染线程调度MIDI事件,因为采样器不允许渲染回调,即使它会(或者如果你使用io的回调只是为了挖掘),它会感到hackish,因为渲染回调不适用于计划MIDI事件?

如何从音频单元的渲染线程正确调用此函数?

回答

2

renderNotify回调是从渲染线程进行调度的理想场所。您甚至可以在MusicDevice本身上设置renderNotify。这是它在AUSampler上的样子。

OSStatus status = AudioUnitAddRenderNotify(sampler, renderNotify, sampler); 

在这个例子中我通过采样器在经由inRefCon参数的引用,而我只是发送一个音符开(144)要注意64个每44100个样品,但在应用程序中,你会传递交流将inRefCon结构体引用到您的MIDI设备,以及执行计划所需的所有值。注意检查预渲染的渲染标志。

static OSStatus renderNotify(void       * inRefCon, 
          AudioUnitRenderActionFlags * ioActionFlags, 
          const AudioTimeStamp   * inTimeStamp, 
          UInt32      inBusNumber, 
          UInt32      inNumberFrames, 
          AudioBufferList    * ioData) { 

    AudioUnit sampler = inRefCon; 
    if (ioActionFlags & kAudioUnitRenderAction_PreRender) { 
     for (int i = 0; i < inNumberFrames; i++) { 
      if (fmod(inTimeStamp->mSampleTime + i, 44000) == 0) { 
       MusicDeviceMIDIEvent(sampler,144, 64, 127, i); // i is the offset from render start, so use it for offset argument. 
      } 
     } 
    } 

    return noErr; 
} 
+0

谢谢!我自己也找到了这个功能。肯定的渲染**通知**(在预渲染)不回调是正确的地方做到这一点。再次感谢! –