gpt4 book ai didi

ios - AUGraph - 即时重新配置?

转载 作者:塔克拉玛干 更新时间:2023-11-01 21:22:04 25 4
gpt4 key购买 nike

我正在尝试在播放(渲染)期间重新排列 AUGraph 中的节点。特别是,我试图在这两种设置之间切换:

  1. 多 channel 调音台 -> 远程 I/O
  2. 多 channel 混频器 -> 转换器 #0 -> 带通滤波器 -> 转换器 #1 -> 远程 I/O

(需要流转换器,因为带通滤波器使用浮点格式)

两种设置都经过测试并且可以独立运行;即,如果我从给定的设置(节点连接)开始,图形会正确呈现。但是当我尝试在播放过程中重新排列节点时,出现了问题。

我的连接代码是这样的:

void enableBandpassFilter(Boolean enable)
{
OSStatus result;

if (enable) {

// [ A ] Enable

// Connect mixer to converter0
result = AUGraphConnectNodeInput(processingGraph, // (in) graph
mixerNode, // (in) src node
0, // (in) src output number
converterNode0, // (in) dst node
0); // (in) dst input number
if ( result != noErr ){
DLog(@"AUGraphConnectNodeInput() Failed for mixer->converter0");
}

// Connect converter0 to bandpass
result = AUGraphConnectNodeInput(processingGraph, // (in) graph
converterNode0, // (in) src node
0, // (in) src output number
bandpassNode, // (in) dst node
0); // (in) dst input number
if ( result != noErr ){
DLog(@"AUGraphConnectNodeInput() Failed for converter0->bandpass");
}

// Connect bandpass to converter1
result = AUGraphConnectNodeInput(processingGraph, // (in) graph
bandpassNode, // (in) src node
0, // (in) src output number
converterNode1, // (in) dst node
0); // (in) dst input number
if ( result != noErr ){
DLog(@"AUGraphConnectNodeInput() Failed for bandpass->converter1");
}

// Connect converter1 to i/o
result = AUGraphConnectNodeInput(processingGraph,
converterNode1,
0,
remoteIONode,
0);
if ( result != noErr ){
DLog(@"AUGraphConnectNodeInput() Failed for converter1->output");
}
}
else{
// [ B ] Disable


result = AUGraphDisconnectNodeInput(processingGraph,
remoteIONode,
0);
if ( result != noErr ){
DLog(@"AUGraphDisconnectNodeInput() Failed for output");
}

// Connect mixer to remote I/O
result = AUGraphConnectNodeInput(processingGraph, // (in) graph
mixerNode, // (in) src node
0, // (in) src output number
remoteIONode, // (in) dst node
0); // (in) dst input number
if ( result != noErr ){
DLog(@"AUGraphConnectNodeInput() Failed for mixer->output");
}
}
}

(图形和节点是文件范围的全局变量。此 C 函数定义在与我的 Obj-C 声音管理器类相同的文件中)。我在图形初始化和之后都使用了相同的函数进行切换。

我尝试了两种方法:

  • 立即调用 enableBandpassFilter()(从一个Obj-C 方法)和

  • 使用 AUGraphAddRenderNotify() 注册一个通知回调(在“实时优先线程”中运行)并调用enableBandpassFilter() 来自回调。

这两种方法都惨遭失败。为了简单起见并避免图表开始时未初始化断开连接的音频单元的陷阱,我从上面的 5 节点配置 #2(带通滤波器:开)开始,然后尝试切换到上面的旁路配置 #1(带通滤波器:关闭)。

启动时,音频图如下所示:

AudioUnitGraph 0x1E9B000:
Member Nodes:
node 1: 'aumx' 'mcmx' 'appl', instance 0x170820fe0 O
node 2: 'aufc' 'conv' 'appl', instance 0x178424040 O
node 3: 'aufx' 'bpas' 'appl', instance 0x1784241a0 O
node 4: 'aufc' 'conv' 'appl', instance 0x1708295a0 O
node 5: 'auou' 'rioc' 'appl', instance 0x17082b020 O
Connections:
node 1 bus 0 => node 2 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 2 bus 0 => node 3 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 3 bus 0 => node 4 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 4 bus 0 => node 5 bus 0 [ 2 ch, 0 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
Input Callbacks:
{0x10000d17c, 0x10004ea90} => node 1 bus 0 [2 ch, 44100 Hz]
{0x10000d17c, 0x10004ea90} => node 1 bus 1 [2 ch, 44100 Hz]
{0x10000d17c, 0x10004ea90} => node 1 bus 2 [2 ch, 44100 Hz]
{0x10000d17c, 0x10004ea90} => node 1 bus 3 [2 ch, 44100 Hz]
CurrentState:
mLastUpdateError=0, eventsToProcess=F, isInitialized=F, isRunning=F

(最后连接中的“0Hz”部分有点令人担忧,但此时声音正常流动)

当我尝试使用回调绕过过滤器时,在将混音器连接到输出时出现可怕的 -10861 错误 (kAUGraphErr_InvalidConnection)。

当我尝试绕过主线程上的过滤器(Obj-C 方法)时,我没有收到任何错误结果代码,但过滤器并未停用。

在这两种情况下,切换后图形日志变为:

AudioUnitGraph 0x1EA2000:
Member Nodes:
node 1: 'aumx' 'mcmx' 'appl', instance 0x178228d80 O I
node 2: 'aufc' 'conv' 'appl', instance 0x17062c760 O I
node 3: 'aufx' 'bpas' 'appl', instance 0x17062dfe0 O I
node 4: 'aufc' 'conv' 'appl', instance 0x170636d00 O I
node 5: 'auou' 'rioc' 'appl', instance 0x170637200 O I
Connections:
node 1 bus 0 => node 2 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000C2C) 8.24-bit little-endian signed integer, deinterleaved]
node 2 bus 0 => node 3 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
node 3 bus 0 => node 4 bus 0 [ 2 ch, 44100 Hz, 'lpcm' (0x00000029) 32-bit little-endian float, deinterleaved]
Input Callbacks:
{0x1000452fc, 0x100086a40} => node 1 bus 0 [2 ch, 44100 Hz]
{0x1000452fc, 0x100086a40} => node 1 bus 1 [2 ch, 44100 Hz]
{0x1000452fc, 0x100086a40} => node 1 bus 2 [2 ch, 44100 Hz]
{0x1000452fc, 0x100086a40} => node 1 bus 3 [2 ch, 44100 Hz]
Problem Events when updated:
connect:source=1,bus=0,dest=5,bus=0
CurrentState:
mLastUpdateError=0, eventsToProcess=F, isInitialized=T, isRunning=T (1)

(注意更新时的问题事件:部分详细说明了无法连接Multichannel MixerRemote I/O。也,每个节点后的O变为O I。)

我不敢相信这些节点是不兼容的,因为如果我从那个配置开始,它就可以工作。

那么,动态重新连接节点的正确方法是什么?我错过了什么?

*很抱歉这个问题很长。

编辑(解决方案?): 正如我在评论中提到的,事实证明图形重新布线必须在主线程中完成 ,而不是在 Core Audio 线程中(相关对象在该上下文中被锁定)。我将重新布线代码移至主线程(实例方法),并且还添加了对 AUGraphClearConnections() 的调用 before 任何对 AUGraphConnectNodeInput() 的调用>,现在它可以工作了,即使我不停止/重新启动图表

现在唯一的问题是,每当我重新布线时,所有声音播放都会停止(停止调用渲染回调),直到我再次停止/启动这些声音。我必须检查混音器的每条总线以查看回调是否已附加、总线是否已启用等...我现在就做。

最佳答案

事实证明,图表重新布线必须在主线程中完成,而不是在 Core Audio 线程中:相关对象被锁定在该上下文中(一些 - 公认的碎片,有时是矛盾的? - Core Audio 官方文档似乎建议您可以在任何上下文中执行此操作,因为 AUGraph 是线程安全的并且会处理所有事情)。

所以我将重新布线的代码移到了我的类的一个实例方法中(在主线程上运行),并且还在调用 AUGraphConnectNodeInput( ),现在它可以工作了,即使我不停止/重新启动图表也是如此。

所以我做的是(主线程):

  1. 调用 AUGraphClearConnections()(断开所有连接)。
  2. 建立所有连接(新节点和现有节点,最终形式的完整图表)。这包括节点以及输入渲染回调。
  3. 同步 模式调用AUGRaphUpdate()(将NULL 传递给第二个参数)。

这就是诀窍。

关于ios - AUGraph - 即时重新配置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23039319/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com