iOSアプリ開発 入門 (4) - AVAudioEngine
iOSアプリの「AVAudioEngine」によるオーディオ制御の実装方法についてまとめました。
・iOS 14
前回
1. AVAudioEngine
iOSアプリでオーディオ制御を実装するには、「AVAudioEngine」を使います。「オーディオノード」で、どのような「入力」に、どのような「エフェクト」をかけ、どのような「出力」を行うのかを定義し、実行します。
2. 音ファイルの再生
「AVAudioPlayerNode」を使って、音ファイルを再生します。
手順は、次のとおりです。
(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」を使って、再生速度を変更します。
コードは、次のとおりです。
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」を使って、ピッチを変更します。
コードは、次のとおりです。
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」を追加。
(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
オーディオ出力を生成するノード。
次回
この記事が気に入ったらサポートをしてみませんか?