Я работаю над проверкой концепции AudioKit
, чтобы оценить, соответствует ли она нашим потребностям.
В настоящее время мы используем AVAudioRecorder
, AVPlayer
и AVMutableComposition
для многодорожечного рекордера, и он прекрасно работает, но я хочу попробовать сделать то же самое с AudioKit
или AVAudioEngine
.
Я новичок в AudioKit
, поэтому мне нужно руководство:
Я использую AKClipRecorder
в качестве записывающего устройства и вызываю start(at:)
для синхронизации с плеерами, но я думаю, что-то настроено неправильно, потому что запись всегда задерживается. Почему это может происходить? Для игроков я использую массив AKPlayers
и вызываю play(at:)
для их синхронизации, и из моих тестов игроки, кажется, синхронизируются нормально.
Мне трудно найти способ синхронизации AKMetronome
с рекордером и плеерами, API start(at:)
отсутствует. Как мне этого добиться? И можно ли запустить рекордер и проигрыватели в определенный ритм?
Наконец, есть ли способ установить формат файла 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")
}
}
}