2

我正在编写一个应用程序,我应该在其中播放部分音频文件。每个音频文件都包含一个单独轨道的音频数据。这些部分是有开始时间和结束时间的部分,我正在尝试按照我选择的顺序播放这些部分。

例如,假设我有 4 个部分:

A B C D

然后我激活B和D,我想玩,B,然后D,然后再B,然后D,等等。

为了在播放中平滑“跳跃”,我认为淡入/淡出开始/结束部分缓冲区很重要。

所以,我有一个基本的AVAudioEngine设置,带有AVAudioPlayerNode, 和一个混音器。对于每个音频部分,我缓存了一些信息:

  • 该部分中第一个样本的缓冲区(我手动淡入)
  • AVAudioFramePosition, 和AVAudioFrameCount中间段的元组
  • 音频部分中结束样本的缓冲区(我手动淡出)

现在,当我安排播放部分时,我会说AVAudioPlayerNode

  • 安排启动缓冲区(scheduleBuffer(_:completionHandler:)无选项)
  • 安排中间段 ( scheduleSegment(_:startingFrame:frameCount:at:completionHandler:))
  • 最后安排结束缓冲区(scheduleBuffer(_:completionHandler:)无选项)

都在“时间” nil

这里的问题是我可以在音频部分边界听到 clic 和蹩脚的声音,我看不出我做错了什么。我的第一个想法是我手动进行的淡入淡出(基本上是将样本值乘以音量因子),但不这样做的结果相同。我以为我没有及时安排,但提前安排部分,例如事先 A - B - C 有相同的结果。然后我尝试了不同的帧位置计算,使用音频格式设置,结果相同。

所以我在这里没有想法,也许我没有得到正确的时间表机制。

任何人都可以确认我可以混合调度缓冲区和段AVAudioPlayerNode吗?还是我应该只安排缓冲区或段?我可以确认只安排分段有效,播放非常好。

关于我如何缓存音频部分信息的一点上下文。在下面的代码中,是从 a 加载到磁盘上file的类型,并且是值,代表我的音频部分的开始/结束。AVAudioFileURLbeginendTimeInterval

let format = file.processingFormat

let startBufferFrameCount: AVAudioFrameCount = 4096
let endBufferFrameCount: AVAudioFrameCount = 4096

let audioSectionStartFrame = framePosition(at: begin, format: format)
let audioSectionEndFrame = framePosition(at: end, format: format)

let segmentStartFrame = audioSectionStartFrame + AVAudioFramePosition(startBufferFrameCount)
let segmentEndFrame = audioSectionEndFrame - AVAudioFramePosition(endBufferFrameCount)

startBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: startBufferFrameCount)
endBuffer = AVAudioPCMBuffer(pcmFormat: format, frameCapacity: endBufferFrameCount)

file.framePosition = audioSectionStartFrame
try file.read(into: startBuffer)

file.framePosition = segmentEndFrame
try file.read(into: endBuffer)

middleSegment = (segmentStartFrame, AVAudioFrameCount(segmentEndFrame - segmentStartFrame))
frameCount = AVAudioFrameCount(audioSectionEndFrame - audioSectionStartFrame)

此外,将值framePosition(at:format:)乘以传入TimeInterval的采样率。AVAudioFormat

我为每个音频部分缓存此信息,但我在部分边界处听到咔嗒声,无论我是否提前安排它们。我也尝试在调度时不混合缓冲区和段,但我没有改变任何东西,所以我开始认为我在做错误的帧计算。

4

0 回答 0