【发布时间】:2020-09-29 14:21:10
【问题描述】:
我学会了如何使用 AVAudioEngine 将音频处理成文件并且我的代码可以正常工作,只要我不使用 AVAudioUnitTimePitch 更改播放速率。
当速率改变时,渲染的音频与原始音频的长度相同(速率不变)。因此,如果音频放慢(速率 1),则渲染音频的最后一部分将静音。
代码如下:
// engine: AVAudioEngine
// playerNode: AVAudioPlayerNode
// audioFile: AVAudioFile
open func render(to destinationFile: AVAudioFile) throws {
playerNode.scheduleFile(audioFile, at: nil)
do {
let buffCapacity: AVAudioFrameCount = 4096
try engine.enableManualRenderingMode(.offline, format: audioFile.processingFormat, maximumFrameCount: buffCapacity)
}
catch {
print("Failed to enable manual rendering mode: \(error)")
throw error
}
do {
try engine.start()
}
catch {
print("Failed to start the engine: \(error)")
}
playerNode.play()
let outputBuff = AVAudioPCMBuffer(pcmFormat: engine.manualRenderingFormat,
frameCapacity: engine.manualRenderingMaximumFrameCount)!
while engine.manualRenderingSampleTime < audioFile.length {
let remainingSamples = audioFile.length - engine.manualRenderingSampleTime
let framesToRender = min(outputBuff.frameCapacity, AVAudioFrameCount(remainingSamples))
do {
let renderingStatus = try engine.renderOffline(framesToRender, to: outputBuff)
switch renderingStatus {
case .success:
do {
try destinationFile.write(from: outputBuff)
}
catch {
print("Failed to write from file to buffer: \(error)")
throw error
}
case .insufficientDataFromInputNode:
break
case.cannotDoInCurrentContext:
break
case .error:
print("An error occured during rendering.")
throw AudioPlayer.ExportError.renderingError
@unknown default:
fatalError("engine.renderOffline() returned an unknown value.")
}
}
catch {
print("Failed to render offline manually: \(error)")
throw error
}
}
playerNode.stop()
engine.stop()
engine.disableManualRenderingMode()
}
我试图通过渲染与播放速率成反比的样本量来解决这个问题。这只解决了比率大于 1 时的问题。
【问题讨论】:
标签: ios swift avfoundation avaudioengine