その後のその後

iOSエンジニア 堤 修一のブログ github.com/shu223

【iOS9】Audio Unit Extensions 〜オーディオエフェクトのアプリ間共有〜

昨日開催された「WWDC2015報告共有会@ネクスト」にて、iOS 9 で追加された新しい Extension Point のひとつ、「Audio Unit Extensions」についてLTをさせていただきました。


概要

Audio Unit とは?
  • Core Audio においてもっとも低レベル(ハードより)に位置するフレームワーク
  • 低遅延での音声処理が可能
  • ユニット同士を繋げて複雑なオーディオ処理を実現可能
  • iOS 8 より AVFoundation に AVAudioEngine が追加され、Audio Unit の利用ハードルがグッと下がった
Audio Unit Extensions とは?
  • iOS 9 で追加された Extension Point のひとつ
  • Audio Unit をアプリ間で共有できる

→ つまり自作エフェクトや他社製エフェクトを繋げてこういうこともできるようになる!


(※写真はイメージです)

  • Audio Unit にはエフェクト以外にもさまざまなタイプがある
    • GarageBand では Audio Unit Extensions の楽器を利用できるようになるらしい。
var kAudioUnitType_Output: UInt32 { get }
var kAudioUnitType_MusicDevice: UInt32 { get }
var kAudioUnitType_MusicEffect: UInt32 { get }
var kAudioUnitType_FormatConverter: UInt32 { get }
var kAudioUnitType_Effect: UInt32 { get }
var kAudioUnitType_Mixer: UInt32 { get }
var kAudioUnitType_Panner: UInt32 { get }
var kAudioUnitType_Generator: UInt32 { get }
var kAudioUnitType_OfflineEffect: UInt32 { get }
var kAudioUnitType_MIDIProcessor: UInt32 { get }

Audio Unit Extensions の利用方法

WWDC のサンプルコード "AudioUnitV3Example" に入っている "FilterDemo" というアプリには、Audio Unit Extensions が含まれています。まずはこのアプリをインストールして、「エクステンション利用側」を実装してみます。

利用可能なユニットのリストを取得する

iOS 9 で追加されたクラス AVAudioUnitComponentManager の `componentsMatchingDescription:` メソッドを呼ぶと、

var anyEffectDescription = AudioComponentDescription()
anyEffectDescription.componentType = kAudioUnitType_Effect
anyEffectDescription.componentSubType = 0
anyEffectDescription.componentManufacturer = 0
anyEffectDescription.componentFlags = 0
anyEffectDescription.componentFlagsMask = 0

availableEffects = AVAudioUnitComponentManager.sharedAudioUnitComponentManager()
    .componentsMatchingDescription(anyEffectDescription)

利用可能な Audio Unit の AVAudioUnitComponent (ユニットのタイプや制作者などの情報が入っているクラス)のリストが得られます。


この中に、インストールした"FilterDemo"サンプルが contain しているユニット "FilterDemo" も入ってきます。

ユニットを適用する

以下の手順で、所望の Audio Unit をサウンドに適用します。

  1. AVAudioUnitComponent の AudioComponentDescription (構造体)を取得する
  2. AVAudioUnit を `instantiateWithComponentDescription:options:` で生成する(このメソッドは iOS 9 で新規追加)
  3. AVAudioEngine に attachNodeする
  4. エフェクトノードと、プレイヤー・ミキサー等のノードを `connect:to:format:` で接続する


※AVAudioEngine を用いて Audio Unit のエフェクトをかける基本的なサンプルは、iOS8-Sampler にも入っているので、よろしければご参考に。


(iOS8-Sampler の "Audio Effects" サンプル)

Audio Unit Extensions の作成方法

なんと、Xcode 7 beta には Audio Unit Extensions を作成するためのテンプレートがまだありません(という話は WWDC セッション内でも話されています)。とりあえず現状では "FilterDemo" からコピペして使ってくれ、とのこと。