LoginSignup
10
12

More than 3 years have passed since last update.

[Swift5]AVAudioEngineを使ってリアルタイム処理を行う最小実装

Last updated at Posted at 2020-08-12

環境

  • 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してから

inputNodeoutputNodeattachする必要性がなかったが、エフェクトNodeを使用する際にはattachしないといけない。


遅延を入れてリバーブをかけるとコンサートホールにいるみたいなエフェクトになった!Bluetoothでもわかるくらいリバーブがいい感じにかかってて感動!

エフェクトクラス一覧

他にもエフェクトがあるので紹介(今回のも含めて)

  • AVAudioUnitReverb リバーブ処理
  • AVAudioUnitTimeEffect 非リアルタイムエフェクト処理
  • AVAudioUnitTimePitch 高品質の再生速度と音程シフトを互いに独立して提供
  • AVAudioUnitVarispeed 再生速度の制御
  • AVAudioUnitDelay 遅延処理
  • AVAudioUnitEQ マルチバンドイコライザの実行 EQ→イコライザの略
  • AVAudioUnitDistortion 歪みエフェクト

まだ使っていないエフェクトを使って音遊びしていきたい。

まとめ

AVAudioEngineは暗黙的にinputとoutputを持っているためノードをつなげる必要性がない。

WWDC2019に新しくAVAudioEngineが新しくなったらしいので、

このセッションを見て復習する。

What's New in AVAudioEngine

10
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
12