在 v4 中,如果您将
AKPlayer
与循环一起使用并使用 setPosition
API,则播放器会在 setPosition
设置的位置和播放器总持续时间之间循环。我需要的是从 setPosition
API 设置的位置开始,并在循环发生时循环到开头。我不确定这是否是有意的,但我需要能够找到播放器中的某个点并循环到开头,目前看来这不是 AudioKit 中的功能。
有没有办法或解决方法来实现这一目标?我需要按照要求完成此任务。
此处重现的是一个完整的游乐场示例:
import AudioKitPlaygrounds
import AudioKit
let file = try AKAudioFile(readFileName: "3.aac")
//: Set up a player to the loop the file's playback
var player = AKPlayer(audioFile: file)
player.isLooping = true
player.buffering = .always
AKManager.output = player
try AKManager.start()
player.setPosition(player.duration - 2)
player.play(at: AVAudioTime.now())
// player loops between player.duration - 2, player.duration forever. I want it to loop between 0, player.duration
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
预期行为 我预计它会回到开头。
详情:
如果您打算开发某种循环应用程序,我认为方法是使用音序器来协调音频文件的播放。在声音应开始播放的每个位置,您都可以向序列中添加一个事件。
定序器可以连接到回调工具,回调工具是将事件传递给用户定义函数的节点。在回调函数中,您将开始播放该事件指示的音频文件。
这是应该做什么的概述:
length
设置为歌曲的总持续时间(请注意,这些属性以节拍而不是秒表示)。根据需要设置音序器的 loopEnabled
。Note On
。您需要几个类来表示有关每个样本在歌曲中出现位置的一些基本信息:
class Beat {
var sample: Sample!
var onsetTime: Double
var endTime {
get {
return onsetTime + sample.duration
}
}
}
class Sample {
var url: URL!
var duration: Double
}
class ViewController: UIViewController {
var samples: [Sample] = []
var beats: [Beat] = []
var player: AKPlayer!
var sequencer: AKSequencer!
}
在音符的音高上,您可以存储要播放的样本的索引。这就是你的回调函数的样子:
func playCallback(status:UInt8, note:MIDINoteNumber, vel:MIDIVelocity) -> () {
guard let status = AKMIDIStatus(byte: status),
let type = status.type,
type == .noteOn else { return }
DispatchQueue.main.async {
player.load(samples[note].url)
player.play()
}
}
您可以使用
AKSequencer
的seek
方法在任意位置开始播放歌曲。
有一种特殊情况,音序器在节拍中间开始播放。在这种情况下,您必须手动开始播放该样本。
func play(at time: Double = 0) {
sequencer.seek(time)
sequencer.play()
for beat in beats {
if beat.onsetTime < time && time < beat.endTime {
player.load(beat.sample.url)
player.play(from: time - beat.onsetTime)
}
}
}
AKPlayer 还能用吗?看起来它已从 AudioKit 中删除。