見出し画像

iOSアプリ開発 入門 (4) - AVAudioEngine

iOSアプリの「AVAudioEngine」によるオーディオ制御の実装方法についてまとめました。

・iOS 14

前回

1. AVAudioEngine

iOSアプリでオーディオ制御を実装するには、「AVAudioEngine」を使います。「オーディオノード」で、どのような「入力」に、どのような「エフェクト」をかけ、どのような「出力」を行うのかを定義し、実行します。

画像1

2. 音ファイルの再生

AVAudioPlayerNode」を使って、音ファイルを再生します。

画像4

手順は、次のとおりです。

(1) 音ファイル(bgm.mp3)をプロジェクトに追加。
(2) ViewControllerを以下のように編集。

import UIKit
import AVFoundation

// ViewController
class ViewController: UIViewController {
    // UI
    let engine = AVAudioEngine()
   
    // ビューのロード時に呼ばれる
    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            // 音ファイルの読み込み
            let url = URL(fileURLWithPath: Bundle.main.path(forResource: "bgm", ofType: "mp3")!)
            let file = try AVAudioFile(forReading: url)
            
            // Playerノードの準備
            let playerNode = AVAudioPlayerNode()
            engine.attach(playerNode)
            
            // Playerノード→MainMixerノードを接続
            engine.connect(playerNode, to: engine.mainMixerNode, format: file.processingFormat)
            
            // 音ファイルの再生
            playerNode.scheduleFile(file, at: nil, completionHandler: nil)
            try engine.start()
            playerNode.play()
        } catch {
            print(error.localizedDescription)
        }
    }
}

3. 再生速度の変更

AVAudioUnitVarispeed」を使って、再生速度を変更します。

画像4

コードは、次のとおりです。

import UIKit
import AVFoundation

// ViewController
class ViewController: UIViewController {
    // UI
    let engine = AVAudioEngine()
   
    // ビューのロード時に呼ばれる
    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            // 音ファイルの読み込み
            let url = URL(fileURLWithPath: Bundle.main.path(forResource: "bgm", ofType: "mp3")!)
            let file = try AVAudioFile(forReading: url)
            
            // Playerノードの準備
            let playerNode = AVAudioPlayerNode()
            engine.attach(playerNode)
            
            // Varispeedノードの準備
            let varispeedNode = AVAudioUnitVarispeed()
            varispeedNode.rate = 0.5 // 速度0.5倍
            engine.attach(varispeedNode)
            
            // Playerノード→Varispeedノード→MainMixerノードを接続
            engine.connect(playerNode, to: varispeedNode, format: file.processingFormat)
            engine.connect(varispeedNode, to: engine.mainMixerNode, format: file.processingFormat)
            
            // 音ファイルの再生
            playerNode.scheduleFile(file, at: nil, completionHandler: nil)
            try engine.start()
            playerNode.play()
        } catch {
            print(error.localizedDescription)
        }
    }
}

4. ピッチの変更

AVAudioUnitTimePitch」を使って、ピッチを変更します。

画像4

コードは、次のとおりです。

import UIKit
import AVFoundation

// ViewController
class ViewController: UIViewController {
    // UI
    let engine = AVAudioEngine()
   
    // ビューのロード時に呼ばれる
    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            // 音ファイルの読み込み
            let url = URL(fileURLWithPath: Bundle.main.path(forResource: "bgm", ofType: "mp3")!)
            let file = try AVAudioFile(forReading: url)
            
            // Playerノードの準備
            let playerNode = AVAudioPlayerNode()
            engine.attach(playerNode)
            
            // TimePitchノードの準備
            let timePitchNode = AVAudioUnitTimePitch()
            timePitchNode.pitch = 440.0 // ピッチを440上げる
            engine.attach(timePitchNode)
            
            // Playerノード→TimePitchノード→MainMixerノードを接続
            engine.connect(playerNode, to: timePitchNode, format: file.processingFormat)
            engine.connect(timePitchNode, to: engine.mainMixerNode, format: file.processingFormat)
            
            // 音ファイルの再生
            playerNode.scheduleFile(file, at: nil, completionHandler: nil)
            try engine.start()
            playerNode.play()
        } catch {
            print(error.localizedDescription)
        }
    }
}

5. マイク入力の音レベルの取得

マイク入力の音レベルを取得する手順は、次のとおりです。

(1) 「Info.plist」に「NSMicrophoneUsageDescription」を追加。

画像5

(2) ViewControllerを以下のように編集。

import UIKit
import AVFoundation

// ViewController
class ViewController: UIViewController {
    // UI
    let engine = AVAudioEngine()
   
    // ビューのロード時に呼ばれる
    override func viewDidLoad() {
        super.viewDidLoad()
        
        do {
            // マイク入力ノードの準備
            let inputNode = self.engine.inputNode
            let recordingFormat = inputNode.outputFormat(forBus: 0)
            
            // ノード出力の監視
            inputNode.installTap(onBus: 0, bufferSize: 2048, format: recordingFormat) {(buffer, time) in
                // 音の大きさ(meterLevel)の計算
                let channelData = buffer.floatChannelData!
                let channelDataValue = channelData.pointee
                let channelDataValueArray = stride(from: 0, to: Int(buffer.frameLength), by: buffer.stride)
                    .map {channelDataValue[$0]}
                let rms = sqrt(channelDataValueArray.map {return $0 * $0} .reduce(0, +)/Float(buffer.frameLength))
                let avgPower = 20 * log10(rms)
                let meterLevel = self.scaledPower(power: avgPower)
                print(meterLevel)
            }
            
            // AudioEngineの開始
            try self.engine.start()
        } catch {
            print(error.localizedDescription)
        }
    }
    
    // 電圧dBの負値を正値に変換し、meterLevel値を調整
    func scaledPower(power: Float) -> Float {
        guard power.isFinite else {
            return 0.0
        }
        let minDb: Float = -80
        if power < minDb {
            return 0.0
        } else if power >= 1.0 {
            return 1.0
        } else {
            return (abs(minDb)-abs(power))/abs(minDb)
        }
    }
}

6. オーディオノード一覧

◎ 基本

・class AVAudioNode
オーディオの生成、処理、I/Oブロックの抽象クラス。

・class AVAudioIONode : AVAudioNode
オーディオ入力・出力に接続するノード。

・class AVAudioInputNode : AVAudioIONode
オーディオ入力に接続するノード。

・class AVAudioOutputNode : AVAudioIONode
オーディオ出力に接続するノード。

・class AVAudioMixerNode : AVAudioNode
入力を単一の出力に混合するノード。

・class AVAudioUnit : AVAudioNode
・オーディオを処理するノード。

◎ オーディオエフェクト

・class AVAudioUnitEffect : AVAudioUnit
リアルタイムにオーディオを処理するノード。

・class AVAudioUnitEQ : AVAudioUnitEffect
マルチバンドイコライザーのノード。

・class AVAudioUnitDistortion : AVAudioUnitEffect
多段ディストーションエフェクトのノード。

・class AVAudioUnitDelay : AVAudioUnitEffect
ディレイエフェクトのノード。

・class AVAudioUnitReverb : AVAudioUnitEffect
リバーブエフェクトのノード。

◎ タイムエフェクト

・class AVAudioUnitTimeEffect : AVAudioUnit
非リアルタイムにオーディオを処理するノード。

・class AVAudioUnitTimePitch : AVAudioUnitTimeEffect
再生速度とピッチシフトの制御を行うノード。

・class AVAudioUnitVarispeed : AVAudioUnitTimeEffect
再生速度の制御を行うノード。

◎ オーディオ生成

・class AVAudioUnitGenerator : AVAudioUnit
オーディオ出力を生成するノード。

次回


この記事が気に入ったらサポートをしてみませんか?