Swift 3 iOS - 与 AVAudioPlayer 同步暂停

Posted

技术标签:

【中文标题】Swift 3 iOS - 与 AVAudioPlayer 同步暂停【英文标题】:Swift 3 iOS - Synchronised Pause with AVAudioPlayer 【发布时间】:2016-12-11 02:21:02 【问题描述】:

我正在使用AVAudioPlayer 在播放器风格界面(播放/暂停/停止)中播放一组同步的 MP3 文件。我知道我可以使用play(atTime:) 同步播放它们,但我的问题是,如何同步暂停它们?目前,要暂停它们,我正在使用:

for (_, audioTrackPlayer) in audioTrackPlayers.enumerated() 
    audioTrackPlayer.pause()

当然,他们都一个接一个地停顿。没有等效的 pause(atTime:) 函数。那么如何实现暂停的精准同步呢?

编辑 - 额外信息

在 matt 询问它有多明显之后,我得到了一些相关数据。暂停 5 首曲目大约需要半秒钟。为了证明这一点,我在暂停循环之后添加了一个单独的循环,以报告每个轨道上的 currentTime,并在暂停之前添加了几个循环 - 以供参考并显示它们在开始时是同步的。

Loop benchmark, 0: 3.2118820861678
Loop benchmark, 0: 3.21580498866213
Loop benchmark, 0: 3.21888888888889
Loop benchmark, 0: 3.22126984126984
Loop benchmark, 0: 3.22328798185941

Before pause, 0: 3.22560090702948
Before pause, 1: 3.22750566893424
Before pause, 2: 3.22975056689342
Before pause, 3: 3.23185941043084
Before pause, 4: 3.23439909297052

After pause, 0: 3.35040816326531
After pause, 1: 3.46598639455782
After pause, 2: 3.56979591836735
After pause, 3: 3.67455782312925
After pause, 4: 3.77895691609977

所以轨道在暂停之前是同步的,时间差只是由于循环的每次迭代需要 3 或 4 毫秒。暂停之后,每首曲目之间大约有十分之一秒的间隔。

参考代码:

for _ in 0..<5 
    print ("Loop benchmark, 0: \(audioTrackPlayers[0].currentTime)")

for (index, audioTrackPlayer) in audioTrackPlayers.enumerated() 
    print ("Before pause, \(index): \(audioTrackPlayer.currentTime)")

for audioTrackPlayer in audioTrackPlayers 
    audioTrackPlayer.pause()

for (index, audioTrackPlayer) in audioTrackPlayers.enumerated() 
    print ("After pause, \(index): \(audioTrackPlayer.currentTime)")

【问题讨论】:

“当然,他们都一个接一个地停顿” 真的吗?这听得见吗? for 循环以闪电般的速度发生,因此暂停时间的差异会出现非常令人惊讶。 — 顺便说一句,您的代码毫无意义;如果您不需要索引,请不要使用enumerated。只需说for audioTrackPlayer in audioTrackPlayers 感谢 for 循环的提示。正在寻找如何在那里没有下划线!忘记了根本不需要枚举!是的,这很明显。我在播放后检查了 currentTime 值,然后暂停了一次。从第一个到最后一个相差几乎半秒:0: 2.46614512471655, 1: 2.57321995464853, 2: 2.68773242630385, 3: 2.8031746031746, 4: 2.90791383219955 每停顿十分之一秒! 启动 5 个踏板,所有 [尝试] 将歌曲暂停 N 秒。不知道有没有影响,只是一个想法。 谢谢。有什么建议我应该尝试实施吗? 【参考方案1】:

我已通过在停止或暂停音轨之前将所有音轨的音量设置为 0 来部分解决此问题。这为用户提供了音频方面的“即时响应”感觉,因此主要解决了这个问题。不需要半秒钟来暂停曲目仍然很好,所以我不接受这个答案,但它确实以一种可用的方式解决了问题。

示例代码(我用来演示这一点的简化版本),包括重置 currentTime 值以在因延迟暂停而感到不安后匹配的必要代码。 truncatingRemainder 是必要的,因为这些都是循环音频。

// Set volumes of all audio tracks to 0, so delay on pause is not noticed
for audioTrackPlayer in audioTrackPlayers 
    audioTrackPlayer.volume = 0

// Pause audio track players
for audioTrackPlayer in audioTrackPlayers 
    audioTrackPlayer.pause()

// Update the currentTime values so they all match
for index in 1..<audioTrackPlayers.count 
    audioTrackPlayers[index].currentTime = audioTrackPlayers[0].currentTime.truncatingRemainder(dividingBy: audioTrackPlayers[index].duration)

// Reset the volumes now the tracks are paused
for audioTrackPlayer in audioTrackPlayers 
    audioTrackPlayer.volume = 1

【讨论】:

以上是关于Swift 3 iOS - 与 AVAudioPlayer 同步暂停的主要内容,如果未能解决你的问题,请参考以下文章

swift 笔记:iOS与JavaScript的交互(三):WKWebView 3. WKUiDelegate - 3.处理提示符()

swift 笔记:iOS与JavaScript的交互(三):WKWebView 3. WKUiDelegate - 7.3

swift 笔记:iOS与JavaScript的交互(三):WKWebView 3. WKUiDelegate - 7.1确立暗号

swift 笔记:iOS与JavaScript的交互(三):WKWebView 3. WKUiDelegate - 4 - 1 loadUserScrip()

swift 笔记:iOS与JavaScript的交互(三):WKWebView 3. WKUiDelegate - 2.处理confirm()

swift 笔记:iOS与JavaScript的交互(三):WKWebView 3. WKUiDelegate - 1.处理alert()