当使用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实现方式的结果。当缓冲区中断另一个缓冲区时,由于中断会导致输出量增加,从而导致输出削波?我仍然在寻找一个可靠的理解为什么会发生这种情况。如果有人愿意/能够提供任何关于此的澄清,这将是太棒了!
答案 0 :(得分:0)
不确定这是否是您在2015年遇到的问题,可能与@suthar在2018年遇到的问题相同。
我遇到了一个非常相似的问题,这是由于设备上的sampleRate与模拟器不同。在macOS上是44100,在iOS设备(最新型号)上是48000。
因此,当在48000台设备上用44100个样本填充缓冲区时,您将获得3900个静默样本。播放时听起来不像是沉默,听起来像是小故障。
在连接playerNode以及创建pcmBuffer时,我使用了mainMixer格式。不要在代码中的任何地方引用48000或44100。
audioEngine.attach( playerNode)
audioEngine.connect( playerNode, to:mixerNode, format:mixerNode.outputFormat(forBus:0))
let pcmBuffer = AVAudioPCMBuffer( pcmFormat:SynthEngine.shared.audioEngine.mainMixerNode.outputFormat( forBus:0),
frameCapacity:AVAudioFrameCount(bufferSize))