如果该单元同时连接到输入单元和输出单元,是不是有 iOS 核心音频单元的回调?

Posted

技术标签:

【中文标题】如果该单元同时连接到输入单元和输出单元,是不是有 iOS 核心音频单元的回调?【英文标题】:Is there a Callback for an iOS Core Audio Unit, if the unit is connected to both an input unit and output unit?如果该单元同时连接到输入单元和输出单元,是否有 iOS 核心音频单元的回调? 【发布时间】:2016-06-06 21:02:14 【问题描述】:

我有一个音频单元,它位于其他两个单元之间。也就是说,我的单元有另一个单元分配给它的输入节点,它有另一个单元分配给它的输出节点。

我想访问输入到我的单元中的 AudioBufferList。我想在回调中访问这个缓冲区列表。但是,如果我的单元的输入总线已经连接到另一个音频单元,那么我的 RenderCallback 永远不会被调用。

我可以使用什么回调来访问给定单元的传入音频缓冲区?

AURenderCallbackStruct splitterCallback;
    splitterCallback.inputProc = (AURenderCallback) SplitterCallback;
    splitterCallback.inputProcRefCon = (__bridge void*) self;
    status = AudioUnitSetProperty(splitterAuUnit,
                                  kAudioUnitProperty_SetRenderCallback,
                                  kAudioUnitScope_Input,
                                  0, &splitterCallback,  sizeof(splitterCallback));


  AudioUnitElement genericOutputBus  = 0;
    AudioUnitConnection genericOutToIoUnitIn;
    genericOutToIoUnitIn.sourceAudioUnit    = genericAuUnit;
    genericOutToIoUnitIn.sourceOutputNumber = genericOutputBus;
    genericOutToIoUnitIn.destInputNumber    = ioUnitOutputElement;



    AudioUnitSetProperty (
                          splitterAuUnit,                     // connection destination
                          kAudioUnitProperty_MakeConnection,  // property key
                          kAudioUnitScope_Input,              // destination scope
                          ioUnitOutputElement,                // destination element
                          &genericOutToIoUnitIn,                // connection definition
                          sizeof (genericOutToIoUnitIn)
                          );

// Callback
static OSStatus SplitterCallback(void                        *inRefCon,
                               AudioUnitRenderActionFlags  *ioActionFlags,
                               const AudioTimeStamp        *inTimeStamp,
                               UInt32                      inBusNumber,
                               UInt32                      inNumberFrames,
                               AudioBufferList             *ioData)
    
    @autoreleasepool 
        NSLog(@"splitterCallback"); // This is never called. :(
    

【问题讨论】:

我从未尝试过这是否可以在 ios 上运行,但在这个 answer 中,我将展示如何在 OSX 中设置这样的回调。关键在于使用AudioUnitAddRenderNotify() 函数设置和注册您的回调。您那里有示例代码,非常不言自明。 你是个天才!! :) 你的建议奏效了。我想将您的评论标记为“正确答案”,但我不知道如何。我使用了 AudioUnitAddRenderNotify() 而不是 AudioUnitSetProperty(),现在当我的音频单元从其输入单元获取数据时,我会收到一个回调。 【参考方案1】:

这是在不破坏 API 的情况下在 AUGraph API 中注册回调的 Core Audio 过程。它在 OSX 中进行了测试,但这部分 API 对 iOS 也是通用的。假设您想收听来自输出单元输入的信号,“上游”单元将是splitterAuUnit。我会通过以下方式注册回调MyRenderProc()

AudioUnitAddRenderNotify(splitterAuUnit,
                         MyRenderProc,
                         &player);

在您的回调中,检查渲染操作和发布渲染错误很重要:

if (*ioActionFlags & kAudioUnitRenderAction_PostRender)
    static int TEMP_kAudioUnitRenderAction_PostRenderError = (1 << 8);
    if (!(*ioActionFlags & TEMP_kAudioUnitRenderAction_PostRenderError))

        Float32* data = (Float32 *)ioData->mBuffers[0].mData; //just for one channel!
    //    …   …   
    

【讨论】:

以上是关于如果该单元同时连接到输入单元和输出单元,是不是有 iOS 核心音频单元的回调?的主要内容,如果未能解决你的问题,请参考以下文章

standard cell library中的那些功能单元

在 iOS 中同时使用两个音频单元进行 I/O 是不是安全?

执行单元测试时spring boot应用程序是不是需要连接到数据库

UICollectionView - 连接到自定义单元格

无法使用直线连接到配置单元,用户 root 无法模拟匿名

Verilog 算术和逻辑单元 (ALU) 编译错误