当使用 AVAudioPlayerNode 安排一个短缓冲区以在触摸事件(“Touch Up Inside”)上立即播放时,我注意到在测试时播放时会出现可听见的故障/伪影。iOS 模拟器中的音频完全没有故障,但是当我在实际的 iOS 设备上运行该应用程序时,播放时会出现声音失真。声音失真随机发生(触发的声音有时听起来很棒,而其他时候听起来失真)
我尝试过使用不同的音频文件、文件格式,并使用 prepareWithFrameCount 方法准备播放缓冲区,但不幸的是结果总是一样的,我想知道可能出了什么问题。
为了清晰和简单起见,我将代码简化为全局变量。任何帮助或见解将不胜感激。这是我第一次尝试开发 iOS 应用程序,也是我在 Stack Overflow 上发布的第一个问题。
let filePath = NSBundle.mainBundle().pathForResource("BD_withSilence", ofType: "caf")!
let fileURL: NSURL = NSURL(fileURLWithPath: filePath)!
var error: NSError?
let file = AVAudioFile(forReading: fileURL, error: &error)
let fileFormat = file.processingFormat
let frameCount = UInt32(file.length)
let buffer = AVAudioPCMBuffer(PCMFormat: fileFormat, frameCapacity: frameCount)
let audioEngine = AVAudioEngine()
let playerNode = AVAudioPlayerNode()
func startEngine() {
var error: NSError?
file.readIntoBuffer(buffer, error: &error)
audioEngine.attachNode(playerNode)
audioEngine.connect(playerNode, to: audioEngine.mainMixerNode, format: buffer.format)
audioEngine.prepare()
func start() {
var error: NSError?
audioEngine.startAndReturnError(&error)
}
start()
}
startEngine()
let frameCapacity = AVAudioFramePosition(buffer.frameCapacity)
let frameLength = buffer.frameLength
let sampleRate: Double = 44100.0
func play() {
func scheduleBuffer() {
playerNode.scheduleBuffer(buffer, atTime: nil, options: AVAudioPlayerNodeBufferOptions.Interrupts, completionHandler: nil)
playerNode.prepareWithFrameCount(frameLength)
}
if playerNode.playing == false {
scheduleBuffer()
let time = AVAudioTime(sampleTime: frameCapacity, atRate: sampleRate)
playerNode.playAtTime(time)
}
else {
scheduleBuffer()
}
}
// triggered by a "Touch Up Inside" event on a UIButton in my ViewController
@IBAction func triggerPlay(sender: AnyObject) {
play()
}
更新:
好的,我想我已经确定了失真的来源:节点的音量在输出时太大并导致削波。通过在我的 startEngine 函数中添加这两行,失真不再发生:
playerNode.volume = 0.8
audioEngine.mainMixerNode.volume = 0.8
但是,我仍然不知道为什么我需要降低输出 - 我的音频文件本身没有剪辑。我猜这可能是 AVAudioPlayerNodeBufferOptions.Interrupts 实现方式的结果。当一个缓冲区中断另一个缓冲区时,是否会因中断而导致输出音量增加,从而导致输出削波?我仍在寻找关于为什么会发生这种情况的可靠理解。如果有人愿意/能够对此提供任何澄清,那就太好了!