【问题标题】:AudioUnit Render callback issue (callback not invoked)AudioUnit 渲染回调问题(未调用回调)
【发布时间】:2015-07-20 10:22:57
【问题描述】:

此时我有一个简单的需求,一个 iOS 应用程序,它从音频文件中读取并使用 AudioUnits 输出到扬声器。不使用高级 API 的原因是,在某些时候,我需要处理来自音频文件的样本并最终通过网络发送它。

我有一个可以工作的代码,它可以读取音频文件并播放到扬声器。这里唯一的问题是,渲染回调不起作用。回调永远不会被调用,注册时我也不会收到任何错误。非常感谢您的帮助(我是 Core Audio 的初学者,这是我在 stackoverflow 上的第一个问题,所以请原谅任何基本的错误/忽略)。附上我用于初始化图形的代码。

void createMyAUGraph (MyAUGraphPlayerST *player) {
    // Create a new AUGraph

    CheckError(NewAUGraph(&player->graph), "New AUGraph failed");

    // Generate description for output

    AudioComponentDescription outputcd = {0};
    outputcd.componentType = kAudioUnitType_Output;
    outputcd.componentSubType = kAudioUnitSubType_RemoteIO;
    outputcd.componentManufacturer = kAudioUnitManufacturer_Apple;
    outputcd.componentFlags = 0;
    outputcd.componentFlagsMask = 0;

    // Add new node

    AUNode outputNode;
    CheckError(AUGraphAddNode(player->graph, &outputcd, &outputNode), "Add output node failed");

    // Node for file player

    AudioComponentDescription fileplayercd = {0};
    fileplayercd.componentType = kAudioUnitType_Generator;
    fileplayercd.componentSubType = kAudioUnitSubType_AudioFilePlayer;
    fileplayercd.componentManufacturer = kAudioUnitManufacturer_Apple;

    // Add new node

    AUNode fileNode;
    CheckError(AUGraphAddNode(player->graph, &fileplayercd, &fileNode), "Add file node failed");

    // Open graph

    CheckError(AUGraphOpen(player->graph), "Graph open failed");

    // Retrive AudioUnit

    CheckError(AUGraphNodeInfo(player->graph, outputNode, NULL, &player->outputAU), "file unit retrive failed");
    CheckError(AUGraphNodeInfo(player->graph, fileNode, NULL, &player->fileAU), "file unit retrive failed");

    // connect nodes

    CheckError(AUGraphConnectNodeInput(player->graph, fileNode, 0, outputNode, 0), "failed to connect nodes");

    // some other setup

    UInt32 flag = 1;
    CheckError(AudioUnitSetProperty(player->outputAU,
                                      kAudioOutputUnitProperty_EnableIO,
                                      kAudioUnitScope_Output,
                                      0,
                                      &flag,
                                      sizeof (flag)), "Set io property failed");

    // Register render callback

    AURenderCallbackStruct output_cb;
    output_cb.inputProc = recording_cb;
    output_cb.inputProcRefCon = player;
    CheckError(AudioUnitSetProperty(player->outputAU, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, 0, &output_cb, sizeof (output_cb)), "callback register failed");

    // initialize graph

    CheckError(AUGraphInitialize(player->graph), "graph initialization failed");
}

【问题讨论】:

  • 渲染回调在哪里?
  • 您的音频会话类别是什么?
  • 嗨,马特,我正在尝试使用没有 AudioSession 的 AudioUnits。根据我浏览的一些文档,我的理解是,它们可以独立使用。音频文件的读取和播放按预期工作,我只是无法获得样本。我是否需要设置 AudioSession 才能使回调起作用?渲染回调没有被调用,因此我没有在这里包含代码。

标签: ios callback core-audio audiounit


【解决方案1】:

您告诉图形将 RemoteIO 的输入连接到文件播放器节点,而不是连接到您的渲染回调。然后你初始化了图表,它覆盖了你的渲染属性。

如果您想从文件中提取样本进行处理,您的处理例程或渲染回调必须这样做,而不是从播放器输出到 RemoteIO 输入的连接。所以不要让图表建立这种联系。

更新答案:

在任何最新的 iOS 版本上,您需要先使用音频会话 API 请求麦克风隐私权限,然后才能启动音频单元,否则您将只能从麦克风获得静音。

要使用音频单元进行录制和播放以及录制,请尝试在 RemoteIO 的输出和输入上放置回调,然后使用循环缓冲区在两个回调之间传递样本数据。在一个或两个回调中,您可以根据需要记录或修改示例。确保注意音频上下文中的实时限制(无锁或内存管理等)

【讨论】:

  • 您确定要覆盖渲染属性吗?我提到的大多数示例,包括来自 Apple 的 iPhoneMixerEQGraphTest,似乎都是连接节点、设置渲染回调然后初始化图形。代码(iPhoneMixerEQGraphTest 应用程序)中的注释显示“// 现在我们已经设置了所有内容,我们可以初始化图形,这也将验证连接”,同时初始化图形。我需要在设备扬声器上播放音频文件中的数据包,因此需要从文件连接到 RemoteIO。
  • 但同时,我也想访问数据包,通过渲染回调处理并通过网络发送。那部分不起作用,我无法理解在哪里设置回调以使其按预期工作。
  • 我在这方面面临同样的问题,我不确定@hotpaw2 在这里说什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
相关资源
最近更新 更多