環境
- macOS: Catalina
- Xcode 11.6
- Swift 5.2
リアルタイムに音声に処理を行う
- 入力をそのまま出力
- 入力にエフェクトをかけて出力
入力をそのまま出力するコード
class ViewController: UIViewController {
    var engine = AVAudioEngine()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupAudioSession()
        
        let input = engine.inputNode
        let output = engine.outputNode
        let format = engine.inputNode.inputFormat(forBus: 0)
        engine.connect(input, to: output, format: format)
        try! engine.start()
        
    }
func setupAudioSession() {
        do {
            let session = AVAudioSession.sharedInstance()
            try session.setCategory(.playAndRecord, options: [.defaultToSpeaker, .allowBluetooth])
            try session.setActive(true)
        } catch {
            fatalError("Failed to configure and activate session.")
        }
    }
補足1 AVAudioEngine
AVAudioEngineは暗黙的にinputとoutputを持っているためノードをattachする必要性がない。
つなげる時はconnectを用いる。
補足2 AudioSession
func setupAudioSession() {
        do {
            let session = AVAudioSession.sharedInstance()
            try session.setCategory(.playAndRecord, options: [.defaultToSpeaker, .allowBluetooth])
            try session.setActive(true)
        } catch {
            fatalError("Failed to configure and activate session.")
        }
    }
これはAVAudioSessionの設定で
ステレオオーディオを録音するには、recordまたはplayAndRecordカテゴリのいずれかを使用するアプリのオーディオセッションが必要。
また、optionでiPhoneのデフォルトのスピーカーを使用することとBluetoothイヤホンで再生と録音が可能に設定。
詳しくはappleサンプルを参考にしてください!
入力にエフェクトをかけて出力するコード
エフェクトをかけたい時にはノードを追加してあげると簡単にエフェクトをかけることができる。
アプリ起動時はイヤホン付けてデバックしないととハウリングが起きるので注意!
    var engine = AVAudioEngine()
    var delay = AVAudioUnitDelay()
    var reverb = AVAudioUnitReverb()
override func viewDidLoad() {
        super.viewDidLoad()
        setupAudioSession()
        
        let input = engine.inputNode
        let output = engine.outputNode
        let format = engine.inputNode.inputFormat(forBus: 0)
        delay.delayTime = 2.0
        reverb.loadFactoryPreset(.largeHall)
        reverb.wetDryMix = 40
        
        engine.attach(delay)
        engine.attach(reverb)
        engine.connect(input, to: delay, format: format)
        engine.connect(delay, to: reverb, format: format)
        engine.connect(reverb, to: output, format: format)
        try! engine.start()
        
    }
補足3 エフェクトをつなげる時はattachしてから
inputNodeとoutputNodeはattachする必要性がなかったが、エフェクトNodeを使用する際にはattachしないといけない。
遅延を入れてリバーブをかけるとコンサートホールにいるみたいなエフェクトになった!Bluetoothでもわかるくらいリバーブがいい感じにかかってて感動!
エフェクトクラス一覧
他にもエフェクトがあるので紹介(今回のも含めて)
- AVAudioUnitReverb
 リバーブ処理
- AVAudioUnitTimeEffect
 非リアルタイムエフェクト処理
- AVAudioUnitTimePitch
 高品質の再生速度と音程シフトを互いに独立して提供
- AVAudioUnitVarispeed
 再生速度の制御
- AVAudioUnitDelay
 遅延処理
- AVAudioUnitEQ
 マルチバンドイコライザの実行 EQ→イコライザの略
- AVAudioUnitDistortion
 歪みエフェクト
まだ使っていないエフェクトを使って音遊びしていきたい。
まとめ
AVAudioEngineは暗黙的にinputとoutputを持っているためノードをつなげる必要性がない。
WWDC2019に新しくAVAudioEngineが新しくなったらしいので、
このセッションを見て復習する。

