Attention! Translated article might be found on my English blog.

2016年7月10日日曜日

v3のAudioUnitをAudioComponentInstanceNew()しようとするとkAudioUnitErr_CannotDoInCurrentContextが返る

Xcode 7.3のtarget templateで作ったAudioUnitがAudioComponentInstanceNew()で-10863(kAudioUnitErr_CannotDoInCurrentContext)を返して失敗しており、
その原因を探っていました。

なお、そのAudioUnitはauvaltool -vでも失敗してしまうようでした。

$ auvaltool -v aufx vibr Symi

    AU Validation Tool
    Version: 1.6.1a1 
    Copyright 2003-2013, Apple Inc. All Rights Reserved.
    Specify -h (-help) for command options

--------------------------------------------------
VALIDATING AUDIO UNIT: 'aufx' - 'vibr' - 'Symi'
--------------------------------------------------
Manufacturer String: Shakeyama
AudioUnit Name: VibratoUnit
Component Version: 1.6.0 (0x10600)

* * PASS
--------------------------------------------------
TESTING OPEN TIMES:
COLD:
Time to open AudioUnit:         333.540 ms
WARM:
Time to open AudioUnit:         101.261  ms
This AudioUnit is a version 3 implementation.
FIRST TIME:
FATAL ERROR: Initialize: result: -50

メッセージを読むと、どうやらversion 3のAudioUnitのようです。
version 3のAudioUnitは例えばSwiftのAVAudioUnit.instantiateWithComponentDescription()で初期化できるようです。
参考: Shared/SimplePlayEngine.swift

色々試行錯誤した結果、
Obj-Cでは+[AUAudioUnit instantiateWithComponentDescription:options:completionHandler:]、
CではAudioComponentInstantiate()で同様に初期化できることを確認しました。

ただし、これらの方法は非同期に初期化が行われるので、
初期化後のコードをblock内に書くようホスト側を修正しなければなりません。

version 2のAudioUnitを作りたい場合はAudio Unit Examples (AudioUnit Effect, Generator, Instrument, MIDI Processor and Offline)を参考に作るといいかもしれません。
当面はこちらの方が楽かな…。