我正在尝试写一个音频文件后,做了一些处理,并得到一个错误。我将错误简化为一个简单的独立案例:
import Foundation
import AVFoundation
do {
let inputFileURL = URL(fileURLWithPath: "/Users/andrewmadsen/Desktop/test.m4a")
let file = try AVAudioFile(forReading: inputFileURL, commonFormat: .pcmFormatFloat32, interleaved: true)
guard let buffer = AVAudioPCMBuffer(pcmFormat: file.processingFormat, frameCapacity: AVAudioFrameCount(file.length)) else {
throw NSError()
}
buffer.frameLength = buffer.frameCapacity
try file.read(into: buffer)
let tempURL =
URL(fileURLWithPath: NSTemporaryDirectory())
.appendingPathComponent("com.openreelsoftware.AudioWriteTest")
.appendingPathComponent(UUID().uuidString)
.appendingPathExtension("caf")
let fm = FileManager.default
let dirURL = tempURL.deletingLastPathComponent()
if !fm.fileExists(atPath: dirURL.path, isDirectory: nil) {
try fm.createDirectory(at: dirURL, withIntermediateDirectories: true, attributes: nil)
}
var settings = buffer.format.settings
settings[AVAudioFileTypeKey] = kAudioFileCAFType
let tempFile = try AVAudioFile(forWriting: tempURL, settings: settings)
try tempFile.write(from: buffer)
} catch {
print(error)
}运行此代码时,tempFile.write(from: buffer)调用将引发一个错误:
Error Domain=com.apple.coreaudio.avfaudio Code=-50 "(null)" UserInfo={failed call=ExtAudioFileWrite(_imp->_extAudioFile, buffer.frameLength, buffer.audioBufferList)}test.m4a是一个立体声文件,44.1 KHz AAC文件(来自iTunes存储),尽管其他立体声文件(AIFF和WAV)也会发生故障。
代码不会失败,相反,如果我在创建原始输入AVAudioFile (file)时将interleaved参数更改为false,则正确地将原始音频保存到新文件中。但是,在本例中,以下消息被记录到控制台:
Audio files cannot be non-interleaved. Ignoring setting AVLinearPCMIsNonInterleaved YES.编写非交错缓冲区似乎很奇怪,也令人困惑,尽管有消息说文件必须被交织,而编写交错缓冲区却失败了。这与我所期望的正好相反。
我知道,使用普通的AVAudioFile(forReading:)初始化器读取文件,而不指定格式,默认为使用非交织(即。以文件实际采样率和信道计数计算的“标准”AVAudioFormat )。这是否意味着在尝试编写之前,我真的必须将交错音频转换为非交错音频?
值得注意的是,在出现这个问题的实际程序中,我所做的事情比简单地读取文件并再次将其写回来要复杂得多,而且我确实需要处理交错的音频。然而,我已经证实,原来的,更复杂的代码也是失败的,只有交错立体声音频。
要让AVAudioFile 写出一个包含交错的PCM音频的缓冲区,我需要做一些棘手的事情吗?
发布于 2020-03-22 17:08:04
这里的混淆是有两种格式在发挥:输出文件的格式,和你要写的缓冲区的格式(处理格式)。初始化器AVAudioFile(forWriting: settings:)不允许您选择处理格式,默认为去交织,因此您的错误。
--这将打开文件,以便使用标准格式(解交错浮点)写入文件。
您需要使用另一个初始化器:AVAudioFile(forWriting:settings: commonFormat:interleaved:),它的最后两个参数指定了处理格式(参数名本来可以更清楚地说明那个tbh)。
var settings: [String : Any] = [:]
settings[AVFormatIDKey] = kAudioFormatMPEG4AAC
settings[AVAudioFileTypeKey] = kAudioFileCAFType
settings[AVSampleRateKey] = buffer.format.sampleRate
settings[AVNumberOfChannelsKey] = 2
settings[AVLinearPCMIsFloatKey] = (buffer.format.commonFormat == .pcmFormatInt32)
let tempFile = try AVAudioFile(forWriting: tempURL, settings: settings, commonFormat: buffer.format.commonFormat, interleaved: buffer.format.isInterleaved)
try tempFile.write(from: buffer)附注:直接将缓冲区格式设置传递给AVAudioFile将为您提供一个LPCM文件,您可能不想要该文件,因此我重新构建文件设置。
发布于 2020-03-22 16:33:23
这里不是正数,但可能是因为您使outputFile设置与处理格式相同,所以处理格式有可能在交织方面有一个不灵活的策略,而文件设置格式则可以,反之亦然。
这是我首先要尝试的。不完整的例子,但应该足以说明需要测试的领域。
let sourceFile: AVAudioFile
let format: AVAudioFormat
do {
// for the moment, try this without any specific format and see what it gives you
let sourceFile = try AVAudioFile(forReading: inputFileURL)
format = sourceFile.processingFormat
print(format) // let's see what we're getting so far, maybe some clues
} catch {
fatalError("Unable to load the source audio file: \(error.localizedDescription).")
}
let sourceSettings = sourceFile.fileFormat.settings
var outputSettings = sourceSettings // start with the settings of the original file rather than the buffer format settings
outputSettings[AVAudioFileTypeKey] = kAudioFileCAFType
// etc...https://stackoverflow.com/questions/60801572
复制相似问题