我可以对此有所帮助吗?

在一个测试项目中,我有一个AUSampler -> MixerUnit -> ioUnit并设置了一个渲染回调。一切正常。我正在使用MusicDeviceMIDIEvent中定义的MusicDevice.h方法来播放midi noteOn和noteOff。因此,在下面的hack测试代码中,noteOn发生了0.5秒。每2秒。
MusicDeviceMIDIEvent(以下)带有一个参数:inOffsetSampleFrame,以便在将来的时间安排事件。我想做的是同时播放noteOn并安排noteOff(无需在下面进行黑客时间检查)。我只是不了解inOffsetSampleFrame值应该是什么(例如:播放0.5秒或0.2秒的音符。(换句话说,我不了解音频计时的基础...)。

因此,如果有人可以指导我完成算法,以便从传入的AudioTimeStamp中获取正确的值,那就太好了!也可以纠正我/澄清以下任何一个问题:

  • AudioTimeStamp->mSampleTime-sampleTime是时间
    当前样本“切片”?这是毫秒吗?
  • AudioTimeStamp->mHostTime-吗?主机是运行该应用程序的计算机,并且这是计算机启动以来的时间(以毫秒为单位)?这是一个 HUGE 数字。它不会滚动然后引起问题吗?
  • inNumberFrames-在iOS5上好像是512(通过kAudioUnitProperty_MaximumFramesPerSlice)。这样就制成了 sample
    最多512帧?
  • 我见过很多建议不要使渲染回调重载
    功能-特别是避免Objective C的调用-我理解
    原因,但是如何向用户界面发送消息或执行其他操作
    加工?

  • 我想就是这样。感谢您的支持!



    //MusicDeviceMIDIEvent函数def:
    extern OSStatus
    MusicDeviceMIDIEvent(   MusicDeviceComponent    inUnit,
                        UInt32                  inStatus,
                        UInt32                  inData1,
                        UInt32                  inData2,
                        UInt32                  inOffsetSampleFrame)
    

    //我的回调
    OSStatus  MyCallback(   void *                          inRefCon,
                     AudioUnitRenderActionFlags *   ioActionFlags,
                     const AudioTimeStamp *         inTimeStamp,
                     UInt32                         inBusNumber,
                     UInt32                         inNumberFrames,
                     AudioBufferList *              ioData)
    {
    
    Float64 sampleTime = inTimeStamp->mSampleTime;
    UInt64 hostTime = inTimeStamp->mHostTime;
    
    [(__bridge Audio*)inRefCon audioEvent:sampleTime andHostTime:hostTime];
    
    return 1;
    }
    

    //OBJ-C方法
    - (void)audioEvent:(Float64) sampleTime andHostTime:(UInt64)hostTime
    {
    OSStatus result = noErr;
    
    Float64 nowTime = (sampleTime/self.graphSampleRate); // sample rate: 44100.0
    if (nowTime - lastTime > 2) {
    
        UInt32 noteCommand =    kMIDIMessage_NoteOn << 4 | 0;
        result = MusicDeviceMIDIEvent (mySynthUnit, noteCommand, 60, 120, 0);
        lastTime = sampleTime/self.graphSampleRate;
    }
    
    if (nowTime - lastTime > .5) {
        UInt32   noteCommand =  kMIDIMessage_NoteOff << 4 | 0;
        result = MusicDeviceMIDIEvent (mySynthUnit, noteCommand, 60, 0, 0);
    }
    }
    

    最佳答案

    答案是我误解了inOffsetSampleFrame的目的,尽管它被恰本地命名了。我以为可以在将来的任意时间使用它来安排noteOff事件,因此我不必管理noteOffs,但是其范围仅在当前示例框架之内。那好吧。

    10-08 03:22