即使文件存在,AVAudioFile.length也为0

时间:2015-12-06 22:08:07

标签: swift core-audio avaudioengine avaudiofile

我正在创建一个AVAudioFile,用于将声音写入声音文件。如果文件已经存在,我想将framePosition移动到文件的末尾,以便在最后继续写入,而不是替换现有文件。

我做了一些测试,尝试将文件中的缓冲区读入一个具有不同URL的新文件,以便它不会覆盖原始文件。当我试图将缓冲区读入新文件时,我遇到了崩溃:

let audioFile = try AVAudioFile(forReading: [URL to existing .caf file])
let audioFrameCount = AVAudioFrameCount(UInt32(audioFile.length))
let audioBuffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: audioFrameCount)

let newAudioFile = try AVAudioFile(forWriting: [another URL], settings: self.engine.mainMixerNode.outputFormatForBus(0).settings)
try newAudioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!) <-- CRASHES ON THIS LINE

崩溃日志:由于未捕获的异常终止应用&#39; com.apple.coreaudio.avfaudio&#39;,原因:&#39;错误-50&#39;

伙计,我真的很讨厌CoreAudio崩溃日志。他们绝对没有告诉我!

是否可以将数据读入已创建用于撰写的文件中?

更新

好的,所以经过一些建议我做了一些改动。基本上,这些是我采取的步骤:

  1. 检查文件是否已存在。
  2. 如果是,请打开它进行阅读并获取音频缓冲区。
  3. 创建一个用于写入的新文件(使用相同的文件URL)
  4. 使用writeFromBuffer将缓冲区从旧文件写入新文件
  5. 将新文件的framePosition移至末尾,以便我可以继续写入/录制。
  6. 但是,写完文件后,新文件的长度为0。

    这是我的代码:

    //Check if a file already exists. If so continue to record at the end of it
    var audioBuffer : AVAudioPCMBuffer!
    var audioFrameCount : AVAudioFrameCount!
    if (NSFileManager.defaultManager().fileExistsAtPath(self.audioRecordURL.path!)) {
        do {
            let existingAudioFile = try AVAudioFile(forReading: self.audioRecordURL)
            audioFrameCount = AVAudioFrameCount(existingAudioFile.length)
            if (audioFrameCount > 0) {
                audioBuffer = AVAudioPCMBuffer(PCMFormat: existingAudioFile.processingFormat, frameCapacity: audioFrameCount)
            }
        } catch let error as NSError {
            NSLog("Error reading buffer from file %@", error.localizedDescription)
        }
    }
    
    //Create a new file. This will replace the old file
    do {
        self.audioFile = try AVAudioFile(forWriting: self.audioRecordURL, settings: self.engine.mainMixerNode.outputFormatForBus(0).settings)
    } catch let error as NSError {
        NSLog("Error creating AVAudioFile %@", error.localizedDescription)
    }
    
    //Read the audio buffer from the old file into the new file
    if (audioBuffer != nil) {
        do {
            try self.audioFile.writeFromBuffer(audioBuffer)
            self.audioFile.framePosition = self.audioFile.length
        } catch let error as NSError {
            NSLog("Error reading buffer into file %@", error.localizedDescription)
        }
    }
    

    顺便说一句,readIntoBuffer的命名对我来说非常困惑。听起来好像你应该使用该方法将文件读入缓冲区,但根据文档,您应该使用它来将缓冲区读入文件中?那么为什么我不能使用该方法将缓冲区添加到我的文件中呢?为什么我必须使用writeFromBuffer?

    更新2

    所以,我设法解决了这个问题。显然我必须先调用readIntoBuffer来实际用数据填充缓冲区才能使用它。所以我添加了这一行

    try existingAudioFile.readIntoBuffer(audioBuffer)
    

    audioBuffer = AVAudioPCMBuffer(PCMFormat: existingAudioFile.processingFormat, frameCapacity: audioFrameCount)
    

1 个答案:

答案 0 :(得分:1)

不确定这只是你在这里提供的代码中的一个拼写错误,而且我不是这方面的专家,但可能你想要崩溃的那条线:

try audioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!)

因为您无法从打开的文件中读取(newAudioFile)。

然后在填充该缓冲区后,您需要使用writeFromBuffer写入新文件 https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioFile_Class/#//apple_ref/occ/instm/AVAudioFile/writeFromBuffer:error