[iOS 8] AVFoundation Audio機能メモ

##
iOS 8で追加されたAudio機能に関するメモです

## [AVAudioEngine](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioEngine_Class/index.html#//apple_ref/occ/cl/AVAudioEngine)
* 接続されたAVAudioNodeのグループを定義
* オーディオ信号を生成・加工したり、inputやoutputに信号を流すためにAVAudioNodeを使用する
* 各AVAudioNodeをそれぞれ作成し、AVAudioEngineに装着する
* 実行中における、AVAudioNodeに対する操作(接続、接続解除、リムーブ)には多少制限がある
  * ミキサーのupstreamにあるAVAudioNodeである場合のみ再接続できる
  * inputとoutputのchannel数が異なるAVAudioNodeやミキサーをリムーブした場合、graphが壊れてしまう

## [AVAudioFile](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioFile_Class/index.html#//apple_ref/occ/cl/AVAudioFile)
* 読込／書込のために開くことができるオーディオファイルを表すクラス
* ファイルの実際のフォーマットに関係なく、 AVAudioPCMBufferを使用して読み書きする
  * AVAudioPCMBufferは、ファイルのprocessing formatに記述されているAVAudioCommonFormat上のサンプルを含む(?)
* 変換は、ファイルの実際のフォーマットから実行される
* 読込／書込は、sequentialに行われるが、framePositionプロパティを使用してrandom accessすることも可能

## [AVAudioNode](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioNode_Class/index.html#//apple_ref/occ/cl/AVAudioNode)
### 概要
* オーディオ生成・加工、I/O blockの基底となるクラス
  * AVAudioEngineオブジェクトは、様々なAVAudioNodeサブクラスのインスタンスを含む
  * AVAudioNodeは、一定の共通機能を提供する
* Nodeは、input／outputのbussを持ち、それらは接続ポイントだと考えることができる
  * 例えば、Effect Nodeは一般的に１つのinputと１つのoutputをもつ
  * Mixer Nodeは、複数のinputと１つのoutputをもつ
* Bussは、フォーマットを持ち、sample rateとchannel countで表す
  * 一方で、AVAudioMixerNode、AVAudioOutputNodeのようなクラスは例外である
* AVAudioEngineに装着されるまでは、Nodeは有益な機能を提供しない

### 関連
* NSObject
	* AVAudioNode
		* AVAudioEnvironmentNode
		* AVAudioIONode
			* AVAudioInputNode
			* AVAudioOutputNode
		* AVAudioMixerNode
		* AVAudioPlayerNode
		* AVAudioUnit
			* AVAudioUnitEffect
				* AVAudioUnitDelay
				* AVAudioUnitDistortion
				* AVAudioUnitEQ
				* AVAudioUnitReverb
			* AVAudioUnitGenerator
			* AVAudioUnitMIDIInstrument
				* AVAudioUnitSampler
			* AVAudioUnitTimeEffect
				* AVAudioUnitTimePitch
				* AVAudioUnitVarispeed

## [AVAudioMixerNode](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioMixerNode_Class/index.html#//apple_ref/occ/cl/AVAudioMixerNode)
* inputバスに入力された信号をMixしてoutputバスに出力するNodeを表すクラス
* Mixerは複数のinputをもつ
* AVAudioMixerNodeはどんなsample rateでも受け付け、sample rateの変換を効率的に行う
* また、どんなchannel数でも受け付け、適切にupmixまたはdownmixを行ってoutputに信号を流す

## [AVAudioPlayerNode](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioPlayerNode_Class/index.html#//apple_ref/occ/cl/AVAudioPlayerNode)
### 概要
* バッファ、または、audio filesのセグメントの再生のスケジューリングをサポートするクラス
  * AVAudioPlayerNodeは、AVAudioBufferインスタンス、または、AVAudioFile経由で読み込んだaudio fileのセグメントの再生をサポートする
  * バッファとセグメントは、ある特定のタイミングでの再生をスケジュールされるかもしれないし、セグメントの先頭からすぐに再生されるかもしれない
* 一般的には、Nodeのoutput formatを、再生されるファイルやバッファと同じチャンネル数にしたいだろう
  * もしそうでなければ、チャンネルが失われたり、追加したりすることが必要になる
  * これを解決する一般的な手段はAVAudioMixerNodeを使用することである
* 同様に、ファイルのセグメントを再生する際に、Nodeは必要に応じてsample rateを変換する必要がある
  * しかし、Nodeのoutputのsample rateをファイルのsample rateと合わせることが好ましい
  * また、Mixerを使用して、rateを変換できる
* バッファを再生する場合は、暗黙の推定が存在する
  * バッファのsample rateは、Nodeのoutputのフォーマットと同じだと推定される
* このクラスは、 AVAudioNodeのresetメソッドをオーバーライドしている
  * 以前スケジュールされたバッファとfileのセグメントの再生のスケジュールを破棄する
  * また、playerのtimelineをsample time 0にリセットする

### Player Timeline
* 通常のAVAudioNodeのsample timeは、任意のゼロ点を持っている
* AVAudioPlayerNodeは第二のtimelineを持ち、“player timeline”と呼ばれる
  * playerの再生や、一時停止された時のインターバルを反映するために使用される
  * これらの2種類のtimeはメソッドで変換できる
    * nodeTimeForPlayerTime:
    * playerTimeForNodeTime:

### Scheduling Playback Time
* 以下の3つのメソッドのwhenパラメーターにはAVAudioTimeが指定されている
  * when parameterがnilの場合
    * 前のコマンドが残っている場合、新しいものは、最後のもののすぐあとに再生される
    * (上記に該当しない場合は)Nodeが再生中の場合、eventはとても近い未来に再生される
    * (上記に該当しない場合は)sample time 0で再生される
  * whenパラメーターがsample timeの場合、"そのように"解釈される
  * whenパラメーターがhost timeの場合は無視される(サンプル時間が無効の場合を覗いて)

```
- (void)scheduleBuffer:(AVAudioPCMBuffer *)buffer
                atTime:(AVAudioTime *)when
               options:(AVAudioPlayerNodeBufferOptions)options
     completionHandler:(AVAudioNodeCompletionHandler)completionHandler

- (void)scheduleFile:(AVAudioFile *)file
              atTime:(AVAudioTime *)when
   completionHandler:(AVAudioNodeCompletionHandler)completionHandler

- (void)scheduleSegment:(AVAudioFile *)file
          startingFrame:(AVAudioFramePosition)startFrame
             frameCount:(AVAudioFrameCount)numberFrames
                 atTime:(AVAudioTime *)when
      completionHandler:(AVAudioNodeCompletionHandler)completionHandler
```

* scheduling methodは、以下の場合では失敗する
  * バッファのチャンネル数とnodeのoutputのフォーマットが一致しない場合
  * ファイルにアクセス出来ない場合
  * AVAudioTimeの指定が、sample timeでもhost timeでもない場合
  * セグメントのstart frame もしくは frame countが負の値の場合

## AVAudioUnit
* AVAudioNodeのサブクラス
* audio unitのタイプによって、real-time もしくは non real-time でオーディオを処理する

## [AVAudioMixing Protocol](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioMixing_Protocol/index.html#//apple_ref/occ/intf/AVAudioMixing)
### 概要
* AVAudioMixing Protocolはmixer nodeのinput busに適用できるプロパティを定義
* AVAudioMixing Protocolに適合したノードは、downstreamの(下流の)mixer nodeとやりとりできる
  * 特にAVAudioMixerNode と AVAudioEnvironmentNodeが該当する
* このProtocolで定義されたプロパティは、Source nodeが接続されたmixer nodeのinput busそれぞれに適用される
* effect nodeはdownstreamのmixerとやりとりできないので注意

#### キャッシュについて
* Source nodeがmixer nodeに接続される前に、Protocol経由でセットされるプロパティの状態は、キャッシュされる
  * 接続された時に適用される
* 同様に、接続が解除された後は、プロパティの状態は再度キャッシュされる

#### 設定の引継について
* Source nodeは、ひとつのmixer nodeから接続を解除し、別のmixer nodeへ繋ぎ直すことができる
  * mixingの設定は引き継ぐことができる
* 例えば、ゲームのシナリオを実現するために使われるAVAudioPlayerNodeインスタンス(AVAudioMixingに適合)は、3Dのmixingを設定でき、ある音響環境から、別の環境へ遷移できる

#### NOTE
* AVAudioMixing Protocolは多数のクラスで使用されている
* このプロトコルは、AVAudio3DMixing／AVAudioStereoMixing プロトコルを継承している

### プロパティ
* volume
  * float
  * input busのボリューム

### 関連
* Conforms To
  * [AVAudio3DMixing](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudio3DMixing_Protocol/index.html#//apple_ref/occ/intf/AVAudio3DMixing)
  * [AVAudioStereoMixing](https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioStereoMixing_Protocol/index.html#//apple_ref/occ/intf/AVAudioStereoMixing)