AVAudioEngineというクラスを使って、mp3をエフェクト付きで再生してみました。
まずはプロジェクトにmp3ファイルを追加します。
追加したファイルがBuild Phasesにも入っているか確認します。
入っていない場合は+ボタンからmp3を追加します。
まずは普通にmp3を再生します。
下のようにAVAudioEngineとAVAudioPlayerNodeのインスタンスを作成、それらをconnectする事で再生します。
import UIKit import AVFoundation class ViewController: UIViewController { let engine = AVAudioEngine() override func viewDidLoad() { super.viewDidLoad() let player = AVAudioPlayerNode() if let path = Bundle.main.path(forResource: "music", ofType: "mp3") { let url = URL(fileURLWithPath: path) if let file = try? AVAudioFile(forReading: url) { engine.attach(player) engine.connect(player, to: engine.mainMixerNode, format: file.processingFormat) player.scheduleFile(file, at: nil, completionHandler: nil) try? engine.start() player.play() } } } }
もしmp3を再生するだけならAVAudioPlayerを使う方が簡単そうでした。
続けてエフェクトをかけてみます。
ViewControllerを以下のように書き換えます。
下コードでは再生速度を2倍にしています。
class ViewController: UIViewController { let engine = AVAudioEngine() override func viewDidLoad() { super.viewDidLoad() let player = AVAudioPlayerNode() if let path = Bundle.main.path(forResource: "music", ofType: "mp3") { let url = URL(fileURLWithPath: path) if let file = try? AVAudioFile(forReading: url) { engine.attach(player) let unit = AVAudioUnitVarispeed() unit.rate = 2.0 engine.attach(unit) engine.connect(player, to: unit, format: file.processingFormat) engine.connect(unit, to: engine.mainMixerNode, format: file.processingFormat) player.scheduleFile(file, at: nil, completionHandler: nil) try? engine.start() player.play() } } } }
今回の変更点は下の箇所です。
AVAudioUnitVarispeedという再生スピード変更ノードを作成してそれをconnectしています。
engine.attach(player) let unit = AVAudioUnitVarispeed() unit.rate = 2.0 engine.attach(unit) engine.connect(player, to: unit, format: file.processingFormat) engine.connect(unit, to: engine.mainMixerNode, format: file.processingFormat)
続けて違うエフェクトも使ってみます。
次はAVAudioUnitTimePitchを試しました。
AVAudioUnitTimePitchは音程と速度を調整するユニットで、音の高低を変更したり音程そのままで速度アップしたりできます。
let unit = AVAudioUnitTimePitch() unit.pitch = 1200.0 engine.attach(unit) engine.connect(player, to: unit, format: file.processingFormat) engine.connect(unit, to: engine.mainMixerNode, format: file.processingFormat)
ファイルへの書き込みは下のように行います。
installTapメソッドでbufferを取得できるので、それを順番にファイルに書き込んでいきます。
if let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { let settings = [ AVFormatIDKey: kAudioFormatMPEG4AAC, AVSampleRateKey: 44100.0, AVNumberOfChannelsKey: 2 ] as [String : Any] if let file = try? AVAudioFile(forWriting: url.appendingPathComponent("test.aac"), settings: settings) { unit.installTap(onBus: 0, bufferSize: 4096, format: unit.inputFormat(forBus: 0), block: { buffer, when in try? file.write(from: buffer) }) } }
録音を停止したい場合はremoveTapメソッドを利用します。
unit.removeTap(onBus: 0)