我正在做一个概念验证,AudioKit
以评估它是否符合我们的需求。
我们目前正在使用AVAudioRecorder
,AVPlayer
和AVMutableComposition
用于多轨录音机,效果很好,但我想尝试用AudioKit
or做同样的事情AVAudioEngine
。
我是新手,AudioKit
所以我需要一些指导:
我正在
AKClipRecorder
用作录音机并调用start(at:)
与播放器同步,但我认为有些地方设置不正确,因为录音总是有延迟。为什么会发生这种情况?对于玩家,我正在使用一系列AKPlayers
并调用play(at:)
来同步它们,从我的测试来看,玩家似乎可以同步。我很难找到如何
AKMetronome
与录音机和播放器同步,没有start(at:)
API。我怎样才能做到这一点?是否可以在某个节拍中启动录音机和播放器?最后,有没有办法设置的文件格式
AKClipRecorder
?
我在下面添加我的代码。
import Foundation
import AudioKit
class MultiTrackRecorder {
// MARK: - Constants & Vars
private var mic: AKMicrophone!
private var micBooster: AKBooster!
private var mainMixer: AKMixer!
private var recorder: AKClipRecorder!
private var players: [AKPlayer] = []
private var metronome: AKMetronome!
// MARK: - Public Methods
func startEngine() throws {
AKSettings.bufferLength = .medium
AKSettings.defaultToSpeaker = true
try AKSettings.setSession(category: .playAndRecord)
mic = AKMicrophone()
recorder = AKClipRecorder(node: mic)
micBooster = AKBooster(mic)
micBooster.gain = 0
metronome = AKMetronome()
metronome.tempo = 120
mainMixer = AKMixer()
mainMixer.connect(input: micBooster)
mainMixer.connect(input: metronome)
AudioKit.output = mainMixer
try AudioKit.start()
}
func startRecording() throws {
try recorder.recordClip(completion: recordingEnded)
let startTime = AVAudioTime.now() + 0.25
recorder.start(at: startTime)
players.forEach { $0.play(at: startTime) }
//metronome.start()
}
func stopRecording() {
recorder.stopRecording()
recorder.stop()
players.forEach { $0.stop() }
metronome.stop()
}
func play() {
let startTime = AVAudioTime.now() + 0.25
players.forEach { $0.play(at: startTime) }
}
func stop() {
players.forEach { $0.stop() }
}
// MARK: - Private Methods
private func addPlayer(withFileURL url: URL) {
guard let player = AKPlayer(url: url) else { return }
players.append(player)
mainMixer.connect(input: player)
}
private func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
private func getDocsPathWithRandomFileName() -> URL {
let docsDirectory = getDocumentsDirectory()
let fileName = "\(UUID().uuidString).caf"
return docsDirectory.appendingPathComponent(fileName, isDirectory: false)
}
private func recordingEnded(url: URL?, somethimg: Double, error: Error?) {
guard let savedFile = url else {
print("TODO: Handle this error")
return
}
do {
let moveToDirectory = getDocsPathWithRandomFileName()
try FileManager.default.moveItem(at: savedFile, to: moveToDirectory)
addPlayer(withFileURL: moveToDirectory)
print("New track has been saved in: \(moveToDirectory.absoluteString)")
} catch {
print("TODO: Handle this error")
}
}
}