swift - 如果轨道不是从头开始的,如何使用循环(缓冲类型 = .always 在 AKPlayer 中)
问题描述
我运行了几个具有不同文件和相同长度的AKPlayer——第一个从头开始,其他的从按钮开始,相对于第一个的时间。文件是无缝的,值得缓冲 type = .always,loop = true。如果AKPlayer 没有从头开始,那么只有从该曲目开始播放到结束的那部分曲目,并且当循环发生时,starts StartTime 不是零值。循环播放时,必须从头开始播放所有曲目。使用 AKWaveTable,一切正常,但播放器中没有平移和音高设置。
这是一个示例代码。在原版中,我使用了一系列播放器,并在循环中将所有文件上传到我的播放器。我正在做类似鼓机的事情 - 正在播放几个音频文件,我可以根据播放器首次启动的时间并行打开/关闭其他文件。每个文件的持续时间相同。当我在 AKWaveTable 中执行相同操作时,一切正常,但将来它不适合我。在此示例中,我首先运行 playPlayer1 方法,然后运行 playPlayer2。当 Player1 从头开始循环时,Player2 从上一个 currentTime 开始循环(例如从文件中间开始),并且它的长度永远相等(endTime - currentTime)
var player1: AKPlayer!
var player2: AKPlayer!
var playersMixer: AKMixer!
init() {
do {
let file1 = try AKAudioFile(readFileName: "Audio/file1.m4a")
let file2 = try AKAudioFile(readFileName: "Audio/file2.m4a")
player1.load(audioFile: file1)
player2.load(audioFile: file2)
} catch {
print(error.localizedDescription)
}
player1.buffering = .always
player1.isLooping = true
player2.buffering = .always
player2.isLooping = true
playersMixer = AKMixer (player1,player2)
AudioKit.output = playersMixer
do {
try AudioKit.start()
} catch {
print(error.localizedDescription)
}
}
func playPlayer1() {
player1.play()
}
func playPlayer2() {
player2.play(from: currentTime)
}
var currentTime: Double {
get {
if player1.isPlaying {
return player1.currentTime
}
return 0
}
}
解决方案
我认为这是 AudioKit 中缺少的功能或错误。同时,当前版本确实使用了startTime
for 循环点,正如我们在源代码中看到的那样(https://github.com/AudioKit/AudioKit/blob/master/AudioKit/Common/Nodes/Playback/Players/Player/AKPlayer .swift )
同时,我找到了一个解决方案,希望它对其他读者有用:
player.isLooping = false
player.buffering = .dynamic
player.completionHandler = {
player.isLooping = true
player.buffering = .always
player.play(from: 0, to: player.duration)
}
player.play(from: masterPlayer.currentTime)
我正在做的是创建一个玩家并设置.isLooping
错误.buffering
并调用.play
将其作为一次性或单发游戏运行!在.completionHandler
完成时调用回调,我在其中设置.isLooping
并.buffering
积极。最后,使用属性和from调用.play
设置所需的循环点。指的是一个单独的,用作获取当前播放位置的参考,我知道这很容易理解,但只是为了避免假设。from
to
self
masterPlayer
player
编辑:
在进行投掷测试后,我发现了一个我之前报告并删除的问题(是否支持同步循环,其持续时间为倍数的 AKPlayers?)并且不得不重新打开,所以希望我能得到答案并帮助理解它是否是应该工作与否。
也被迫player
并detach
创建了一个新的:
player.completionHandler = {
player.detach()
let player = self.createPlayer(audioFile: audioFile)
self.connectPlayerToMixer(player)
player.isLooping = true
player.buffering = .always
player.startTime = 0
player.endTime = audioFile.duration
player.play(at: AVAudioTime.now())
}
我现在已经测试过了AKWaveTable
,希望我做对了,但是在录制是预览录制大小的两倍之后它也失败了,例如:
- 循环 1 > 1 2 3 4
- 循环 2 > 1 2 3 4
- 循环 3 > 1 2 3 4 5 6 7 8
- 循环 4 > 1 2 3 4
- Loop5 > 5 6 7 8(记录为 1 2 3 4 5 6 7 8,但播放为 5 6 7 8)
我将不得不返回并测试原件AKNodeRecorder
以查看行为是否相似,但目前我将尝试使用AKWaveTable
.
- 经过一段时间的测试 * *
这是描述上述问题的录音:
https://drive.google.com/open?id=1zxIJgFFvTwGsve11RFpc-_Z94gEEzql7
在研究了一段时间后,我发现了所有的研究似乎是一个解决方案。通过转移使用的程序!与其将播放器设置为沿当前时间开始,不如将其安排为从开始时间开始。这是因为开始时间是用于循环开始和端点的!要了解更多信息,请点击我之前发布的另一篇 StackOverflow 帖子的链接(此处提供了解决方案(对于持续时间为倍数的 AKPlayers 是否支持同步循环?),谢谢!
推荐阅读
- java - 在 Java 中使用哈希映射来查找字符串中字符的频率
- ruby-on-rails - Rails 5 显示当前用户联系人
- angular - 订阅未完成后 NgRx 存储选择
- amazon-web-services - 创建具有相同名称的 ekscluster 时出错
- reactjs - 当 redux 状态改变时不要更新路由组件
- c - 如何在 URL 和 C 代码之间建立联系?
- r - 使用 papaja 将图形编织成单词失败
- css - 如何在 Gmail 的响应式电子邮件中使用 @media(首选颜色方案)?
- swift - CallKit :- Callkit 正在工作,但被叫方未接听电话
- authentication - 有没有办法使用带有匿名访问的 Spring Security 获取非空委托人/身份验证?