首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当缓冲区包含交错音频时,AVAudioFile.write(from:)失败

当缓冲区包含交错音频时,AVAudioFile.write(from:)失败
EN

Stack Overflow用户
提问于 2020-03-22 16:00:24
回答 2查看 2.3K关注 0票数 3

我正在尝试写一个音频文件后,做了一些处理,并得到一个错误。我将错误简化为一个简单的独立案例:

代码语言:javascript
复制
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)调用将引发一个错误:

代码语言:javascript
复制
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,则正确地将原始音频保存到新文件中。但是,在本例中,以下消息被记录到控制台:

代码语言:javascript
复制
Audio files cannot be non-interleaved. Ignoring setting AVLinearPCMIsNonInterleaved YES.

编写非交错缓冲区似乎很奇怪,也令人困惑,尽管有消息说文件必须被交织,而编写交错缓冲区却失败了。这与我所期望的正好相反。

我知道,使用普通的AVAudioFile(forReading:)初始化器读取文件,而不指定格式,默认为使用非交织(即。以文件实际采样率和信道计数计算的“标准”AVAudioFormat )。这是否意味着在尝试编写之前,我真的必须将交错音频转换为非交错音频?

值得注意的是,在出现这个问题的实际程序中,我所做的事情比简单地读取文件并再次将其写回来要复杂得多,而且我确实需要处理交错的音频。然而,我已经证实,原来的,更复杂的代码也是失败的,只有交错立体声音频。

要让AVAudioFile 写出一个包含交错的PCM音频的缓冲区,我需要做一些棘手的事情吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-03-22 17:08:04

这里的混淆是有两种格式在发挥:输出文件的格式,和你要写的缓冲区的格式(处理格式)。初始化器AVAudioFile(forWriting: settings:)不允许您选择处理格式,默认为去交织,因此您的错误。

--这将打开文件,以便使用标准格式(解交错浮点)写入文件。

您需要使用另一个初始化器:AVAudioFile(forWriting:settings: commonFormat:interleaved:),它的最后两个参数指定了处理格式(参数名本来可以更清楚地说明那个tbh)。

代码语言:javascript
复制
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文件,您可能不想要该文件,因此我重新构建文件设置。

票数 6
EN

Stack Overflow用户

发布于 2020-03-22 16:33:23

这里不是正数,但可能是因为您使outputFile设置与处理格式相同,所以处理格式有可能在交织方面有一个不灵活的策略,而文件设置格式则可以,反之亦然。

这是我首先要尝试的。不完整的例子,但应该足以说明需要测试的领域。

代码语言:javascript
复制
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...
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60801572

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档