【问题标题】:Where is the callback function in Apple's PlaySequence project?苹果的 PlaySequence 项目中的回调函数在哪里?
【发布时间】:2015-04-07 09:11:40
【问题描述】:

我想离线反弹一个 MIDI 文件,正如 PlaySequence 示例所做的那样,我试图理解它。
我一直在到处阅读,您需要一个回调函数来在 CoreAudio 中执行任何操作,但我在这个项目中看不到任何内容。
我粘贴了包含 AudioUnitRender 的循环,感谢您的帮助!

    CAStreamBasicDescription clientFormat = CAStreamBasicDescription();
    size = sizeof(clientFormat);
    FailIf ((result = AudioUnitGetProperty (outputUnit,
                                                kAudioUnitProperty_StreamFormat,
                                                kAudioUnitScope_Output, 0,
                                                &clientFormat, &size)), fail, "AudioUnitGetProperty: kAudioUnitProperty_StreamFormat");
    size = sizeof(clientFormat);
    FailIf ((result = ExtAudioFileSetProperty(outfile, kExtAudioFileProperty_ClientDataFormat, size, &clientFormat)), fail, "ExtAudioFileSetProperty: kExtAudioFileProperty_ClientDataFormat");

    {
        MusicTimeStamp currentTime;
        AUOutputBL outputBuffer (clientFormat, numFrames);
        AudioTimeStamp tStamp;
        memset (&tStamp, 0, sizeof(AudioTimeStamp));
        tStamp.mFlags = kAudioTimeStampSampleTimeValid;
        int i = 0;
        int numTimesFor10Secs = (int)(10. / (numFrames / srate));
        do {
            outputBuffer.Prepare();
            AudioUnitRenderActionFlags actionFlags = 0;
            FailIf ((result = AudioUnitRender (outputUnit, &actionFlags, &tStamp, 0, numFrames, outputBuffer.ABL())), fail, "AudioUnitRender");

            tStamp.mSampleTime += numFrames;

            FailIf ((result = ExtAudioFileWrite(outfile, numFrames, outputBuffer.ABL())), fail, "ExtAudioFileWrite");   

            FailIf ((result = MusicPlayerGetTime (player, &currentTime)), fail, "MusicPlayerGetTime");
            if (shouldPrint && (++i % numTimesFor10Secs == 0))
                printf ("current time: %6.2f beats\n", currentTime);
        } while (currentTime < sequenceLength);
    }

【问题讨论】:

    标签: core-audio midi audiounit


    【解决方案1】:

    我查看了该项目,您是对的,它没有渲染回调。渲染回调在coreaudio audiounit effect processing 中占有一席之地。设置渲染回调的调用如下所示:

    inline OSStatus     SetInputCallback (CAAudioUnit &inUnit, AURenderCallbackStruct &inInputCallback)
    {
        return inUnit.SetProperty (kAudioUnitProperty_SetRenderCallback, 
                                                kAudioUnitScope_Input, 
                                                0,
                                                &inInputCallback, 
                                                sizeof(inInputCallback));
    }
    

    然而,这段代码只是一个大的main(),它设置了序列、augraph、音乐播放器,然后是文件编写器WriteOutputFile,以防有一个输出文件可以跳转到。

    我建议您在关键方法处设置一些断点,并遍历代码,观察它的作用并查看变量。

    编辑:请注意,在 iOS 上的 RemoteIO(兼作输入和输出单元)上设置渲染回调时,在 setproperty 调用中的正确范围和总线元素编号上获取正确的流格式可能会很棘手。请参阅 Apple 文档中的此内容。

    【讨论】:

    • 谢谢 ruoho。实际上,我正在对这段代码进行更彻底的“分析”,因为我正在将它移植到 iPhone 和 Swift 上。我已经成功地设置了图表(我可以听一个 MIDI 文件播放),但是在将 MIDI 文件弹回音频文件时我仍然遇到了麻烦。一切似乎都很好,但循环无法提取数据:MusicTimeStamp 始终为 0.0
    • 好的,这段代码正在获取 AUGraph 的输出单元 (kAudioUnitType_Output),并且渲染调用将样本写入写入磁盘的缓冲区。在 iOS 上,RemoteIO 是您的“输出单元”,RemoteIO 上的渲染调用(注意正确的总线 = 0)将为您提供可以写入磁盘的示例。更多详情见:stackoverflow.com/questions/8951458/…stackoverflow.com/questions/6930609/…
    • 我已经知道你给我的第一个链接,但谁知道为什么,当你指出它时,我从另一个角度看到了它。我被 AudioBufferList 分心了,以至于我没有注意到我的 ASBD 是一团糟(多个,“get”而不是“set”......你的名字)。如果我做得好,您需要一个 ASBD,并且您必须手动将其应用于图表中的每个单元。没有某种“反向传播”:如果我将 ASBD 分配给输出节点,这不会自动扩展到上游节点(在我的情况下是混音器和合成器),对吗?
    猜你喜欢
    • 1970-01-01
    • 2021-07-03
    • 2018-11-03
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 2018-04-11
    • 2014-10-15
    相关资源
    最近更新 更多