AVAudioEngine在连接节点上崩溃

时间:2018-10-15 21:30:02

标签: audio core-audio audiounit avaudioengine

我已经按照自己的方法设置了AVAudioEngine,如下所示:     

AVAudioSession* session = [AVAudioSession sharedInstance];
[session setPreferredSampleRate:[session sampleRate] error:nil];
[session setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:nil];
[session setActive:YES error:nil];

audioEngine_ = [[AVAudioEngine alloc] init];

//tap the outputNode to create the singleton
[audioEngine_ outputNode];
NSError* error;
[audioEngine_ startAndReturnError:&error];

启动它没有错误。我有另一种方法可以从我从应用程序间音频乐器收到的AudioComponentDescription附加AVAudioUnitMIDIInstrument。我的connect方法看起来像这样:

-(void)connectInstrument:(AudioComponentDescription)desc {  
    instNode_ = nil;
    instNode_ = [[AVAudioUnitMIDIInstrument alloc] initWithAudioComponentDescription:desc];

    [audioEngine_ attachNode:instNode_];

    //Crashes here
    [audioEngine_ connect:instNode_ to:[audioEngine_ outputNode] format:nil];

    [audioEngine_ startAndReturnError:nil];

    NSLog(@"done connecting");
}

崩溃没有任何有用的信息。我明白了:

提供给CFRunLoopRunSpecific的无效模式'kCFRunLoopCommonModes'-在_CFRunLoopError_RunCalledWithInvalidMode上中断以进行调试。每次执行该消息只会出现一次。

*由于未捕获的异常'NSRangeException'而终止应用程序,原因:'* -[__ NSArrayM objectAtIndexedSubscript:]:索引0超出了空数组的范围'

如果我进行测试并尝试创建一个新的Mixer节点并附加/连接它,则不会崩溃。

我有更多相关信息
如果我这样做:

AVAudioFormat* instFormat = [instUnit_ outputFormatForBus:0];

我遇到相同的错误:
-[__ NSArrayM objectAtIndexedSubscript:]:空数组的索引0超出范围

几乎没有为任何输出总线设置AVAudioFormat,也没有为任何输入总线设置(我也检查了inputFormatForBus)。这很奇怪,因为如果我这样做:

AudioStreamBasicDescription f1;
UInt32 outsize = sizeof(f1);
AudioUnitGetProperty(instNode_.audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 0, &f1, &outsize);

然后,f1是有效的AudioStreamBasicDescription,它显示标准的44.1khz采样率,32位浮点,2个通道。因此,存在一种输出流格式,但似乎没有将其附加到AVAudioUnitMIDIInstrument实例的任何输出总线上。

编辑-进一步的信息 即使我只是尝试访问instUnite_.name,我也会得到NSRangeException。我现在想知道这是否与获取组件说明有关。我正在尝试使用应用间音频(我已经完成了所有适当的权利,功能和应用ID设置)。这就是我发现应用间音频组件的方式:

NSMutableArray* units = [[NSMutableArray alloc] init];
AudioComponentDescription searchDesc = { kAudioUnitType_RemoteInstrument, 0, 0, 0, 0 };

NSArray* componentArray = [[AVAudioUnitComponentManager sharedAudioUnitComponentManager] componentsMatchingDescription:searchDesc];

for(AVAudioUnitComponent* component in componentArray) {
    AudioComponentDescription description = component.audioComponentDescription;

    InterAppAudioUnit* unit = [[InterAppAudioUnit alloc] init];
    unit.componentDescription = description;
    unit.icon = AudioComponentGetIcon(component.audioComponent, 44.0f);
    unit.name = component.name;
    unit.avComponent = component;

    [units addObject:unit];
}

_units = units;
[self.tableView reloadData];

所有这些都在提供的UITableViewController中。单击一个后,我只需执行:

[self connectInstrument:unit.componentDescription];

如果我改为手动为本地单元构建组件说明,则AVAudioUnit实例化就很好,并且没有崩溃。

1 个答案:

答案 0 :(得分:1)

我找到了答案。创建时,AVAudioUnit对象内部的AUAudioUnit对象没有输出总线。我不知道为什么。您可以通过执行以下操作来解决它:

AUAudioUnit* auInst = instUnit_.AUAudioUnit;
NSMutableArray<AUAudioUnitBus*>* busArray = [[NSMutableArray alloc] init];
AVAudioFormat* outFormat = [[self->audioEngine_ outputNode] outputFormatForBus:0];
AUAudioUnitBus* bus = [[AUAudioUnitBus alloc] initWithFormat:outFormat error:&err];
[busArrays addObject:bus];
[[auInst outputBusses] replaceBusses:busArray];